Skip to content

ComposableView actions: callbacks back into Swift - #40

Merged
colemancda merged 5 commits into
masterfrom
feature/composable-actions
Jul 23, 2026
Merged

ComposableView actions: callbacks back into Swift#40
colemancda merged 5 commits into
masterfrom
feature/composable-actions

Conversation

@colemancda

Copy link
Copy Markdown
Member

Completes the custom-view mechanism (#39) with the "coordinator" half — a custom composable can now send events back into Swift state, so interop is two-way.

API

ComposableView gains an actions: parameter — a dictionary of named ComposableActions, each a typed closure matching the fixed bridge surface:

ComposableView("RatingBar",
    props: ["rating": .double(stars), "max": 5],
    actions: ["onRatingChanged": .double { stars = $0 }])

Each action registers a callback in the resolve context (exactly like Button's tap) and crosses as an id prop. On the Kotlin side, Props exposes typed action lambdas — props.doubleAction("onRatingChanged") returns a (Double) -> Unit that dispatches back to Swift; the factory never sees the id or the bridge:

val onChanged = props.doubleAction("onRatingChanged")
RatingBar(context).setOnRatingBarChangeListener { _, value, fromUser ->
    if (fromUser) onChanged?.invoke(value.toDouble())
}

Verification

  • swift test — new test invoking a registered action through the callback registry, 61 total passing
  • Emulator (Custom Views screen): the demo RatingBar is now interactive — dragging the stars updates Swift @State (drag → 1.5, and the sibling Text reads "1.5 / 5"), while the ±½ buttons drive it the other way. Both directions share one state with no feedback loop (the fromUser guard filters programmatic updates).

Deferred

Actions are per-event fire-and-forget (no return values back to the composable); coordinator-style object state lives in the Kotlin factory's remember.

@colemancda
colemancda merged commit 88094fe into master Jul 23, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant