@qontinui/ui-bridge-native 0.6.12 → 0.6.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +36 -16
  2. package/dist/control/action-executor.d.ts +42 -2
  3. package/dist/control/action-executor.d.ts.map +1 -1
  4. package/dist/control/index.js +723 -4
  5. package/dist/control/index.js.map +1 -1
  6. package/dist/control/index.mjs +723 -5
  7. package/dist/control/index.mjs.map +1 -1
  8. package/dist/control/types.d.ts +82 -1
  9. package/dist/control/types.d.ts.map +1 -1
  10. package/dist/core/abortable.d.ts +151 -0
  11. package/dist/core/abortable.d.ts.map +1 -0
  12. package/dist/core/action-effect.d.ts +74 -0
  13. package/dist/core/action-effect.d.ts.map +1 -0
  14. package/dist/core/element-actions.d.ts +38 -0
  15. package/dist/core/element-actions.d.ts.map +1 -0
  16. package/dist/core/index.d.ts +4 -0
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/core/index.js +756 -15
  19. package/dist/core/index.js.map +1 -1
  20. package/dist/core/index.mjs +738 -16
  21. package/dist/core/index.mjs.map +1 -1
  22. package/dist/core/param-schema.d.ts +282 -0
  23. package/dist/core/param-schema.d.ts.map +1 -0
  24. package/dist/core/registry.d.ts +272 -2
  25. package/dist/core/registry.d.ts.map +1 -1
  26. package/dist/core/types.d.ts +231 -32
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/debug/index.js.map +1 -1
  29. package/dist/debug/index.mjs.map +1 -1
  30. package/dist/index.d.ts +10 -5
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +1568 -135
  33. package/dist/index.js.map +1 -1
  34. package/dist/index.mjs +1550 -136
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/react/UIBridgeNativeProvider.d.ts +18 -24
  37. package/dist/react/UIBridgeNativeProvider.d.ts.map +1 -1
  38. package/dist/react/index.js +1385 -130
  39. package/dist/react/index.js.map +1 -1
  40. package/dist/react/index.mjs +1385 -130
  41. package/dist/react/index.mjs.map +1 -1
  42. package/dist/react/useUIBridge.d.ts +19 -22
  43. package/dist/react/useUIBridge.d.ts.map +1 -1
  44. package/dist/react/useUIComponent.d.ts +113 -8
  45. package/dist/react/useUIComponent.d.ts.map +1 -1
  46. package/dist/react/useUIElement.d.ts +34 -8
  47. package/dist/react/useUIElement.d.ts.map +1 -1
  48. package/dist/server/handlers.d.ts.map +1 -1
  49. package/dist/server/http-server.d.ts +15 -2
  50. package/dist/server/http-server.d.ts.map +1 -1
  51. package/dist/server/index.js +345 -43
  52. package/dist/server/index.js.map +1 -1
  53. package/dist/server/index.mjs +345 -44
  54. package/dist/server/index.mjs.map +1 -1
  55. package/dist/server/observability.d.ts +40 -0
  56. package/dist/server/observability.d.ts.map +1 -1
  57. package/dist/server/types.d.ts +57 -1
  58. package/dist/server/types.d.ts.map +1 -1
  59. package/dist/transport/CloudRelayClient.d.ts.map +1 -1
  60. package/dist/transport/DeviceAnnouncer.d.ts +35 -7
  61. package/dist/transport/DeviceAnnouncer.d.ts.map +1 -1
  62. package/dist/transport/index.d.ts +1 -1
  63. package/dist/transport/index.d.ts.map +1 -1
  64. package/dist/transport/relay-logging.d.ts +50 -0
  65. package/dist/transport/relay-logging.d.ts.map +1 -0
  66. package/package.json +2 -2
@@ -4,6 +4,7 @@
4
4
  * Types for action execution and control operations.
5
5
  */
6
6
  import type { NativeActionRequest, NativeActionResponse, NativeFindRequest, NativeFindResponse, NativeElementState, WaitOptions } from '../core/types';
7
+ import type { ParamValidationMode } from '../core/param-schema';
7
8
  /**
8
9
  * Extended action request with control-specific options
9
10
  */
@@ -24,6 +25,13 @@ export interface ControlActionRequest extends NativeActionRequest {
24
25
  export interface ControlActionResponse extends NativeActionResponse {
25
26
  /** Request ID for correlation */
26
27
  requestId?: string;
28
+ /**
29
+ * Machine-readable failure code, set only when an action failed for a
30
+ * reason with an honest code of its own — today only `NOT_SUPPORTED`
31
+ * (`scrollIntoView` with no usable declared scroll container). Absent on
32
+ * every other failure, which the HTTP handler reports as `ACTION_FAILED`.
33
+ */
34
+ code?: string;
27
35
  /** Retry count */
28
36
  retryCount?: number;
29
37
  }
@@ -37,6 +45,57 @@ export interface ComponentActionRequest {
37
45
  params?: Record<string, unknown>;
38
46
  /** Request ID for correlation */
39
47
  requestId?: string;
48
+ /**
49
+ * Abandon the action if it has not produced a result within this many
50
+ * milliseconds (plan `2026-08-20-ui-bridge-action-declaration-shape`,
51
+ * Phase 3). Omitted = no timeout.
52
+ *
53
+ * The wire-reachable half of cancellation: an `AbortSignal` cannot be
54
+ * JSON-serialized, so an HTTP caller has no other way to call off a hung
55
+ * handler. In-process callers should prefer the `{ signal }` option bag on
56
+ * `executeComponentAction`; whichever fires first wins.
57
+ *
58
+ * Abandonment does not depend on the handler observing its signal — the
59
+ * executor races the handler promise.
60
+ *
61
+ * **Validated and clamped at the executor**, so no wire caller reaches a
62
+ * timer unchecked: `0` abandons on the next tick; a negative, `NaN`,
63
+ * infinite or non-numeric value is REFUSED (the response is `success: false`
64
+ * naming `timeoutMs`); anything above 24h is clamped, because past 2^31-1
65
+ * `setTimeout` wraps negative and fires immediately. See
66
+ * `core/abortable.ts` `normalizeActionTimeoutMs`.
67
+ */
68
+ timeoutMs?: number;
69
+ }
70
+ /**
71
+ * Per-invocation options for `NativeActionExecutor.executeComponentAction`.
72
+ *
73
+ * In-process only — nothing here survives JSON serialization, which is why the
74
+ * wire-reachable timeout lives on {@link ComponentActionRequest} instead.
75
+ *
76
+ * Mirrors `@qontinui/ui-bridge` `ComponentActionInvokeOptions`; kept local
77
+ * because that package is an OPTIONAL peer dependency here (see
78
+ * `core/types.ts`).
79
+ */
80
+ export interface ComponentActionInvokeOptions {
81
+ /**
82
+ * Cancellation signal owned by the caller. Aborting it abandons the
83
+ * invocation whether or not the handler observes the signal it is given.
84
+ */
85
+ signal?: AbortSignal;
86
+ /**
87
+ * What to do when `params` violate the action's declared `paramSchema`
88
+ * (Phase 2). Omitted = `getDefaultParamValidationMode()`, which starts at
89
+ * `'warn'`. Deliberately NOT on {@link ComponentActionRequest}: enforcement
90
+ * is a deployment's policy, not the validated caller's to switch off.
91
+ *
92
+ * NOTE: this tree's {@link ComponentActionResponse} carries no
93
+ * `failureDetails`, so an enforced rejection surfaces as a prose `error`
94
+ * naming each offending param — the same limitation Phase 3's cancellation
95
+ * path hit here. Giving the native channel structured failure details is a
96
+ * separate change.
97
+ */
98
+ paramValidation?: ParamValidationMode;
40
99
  }
41
100
  /**
42
101
  * Component action response
@@ -97,7 +156,7 @@ export interface NativeActionExecutor {
97
156
  /**
98
157
  * Execute a component action
99
158
  */
100
- executeComponentAction(componentId: string, request: ComponentActionRequest): Promise<ComponentActionResponse>;
159
+ executeComponentAction(componentId: string, request: ComponentActionRequest, options?: ComponentActionInvokeOptions): Promise<ComponentActionResponse>;
101
160
  /**
102
161
  * Find elements
103
162
  */
@@ -168,6 +227,28 @@ export interface ScrollActionParams {
168
227
  /** Animate the scroll */
169
228
  animated?: boolean;
170
229
  }
230
+ /**
231
+ * `scrollIntoView` action params.
232
+ *
233
+ * Vertical containers only. A container declared `horizontal` is answered
234
+ * `NOT_SUPPORTED` where the bridge can see the declaration (captured props, or
235
+ * a FlatList / SectionList instance), or where the element is measured laid
236
+ * out beyond the container's width — which also refuses an element wider than
237
+ * its vertical container, or one inside a nested horizontal carousel whose
238
+ * declared ancestor is the outer vertical feed; see `performScrollIntoView`.
239
+ */
240
+ export interface ScrollIntoViewActionParams {
241
+ /**
242
+ * Gap (logical dp) left between the top of the scroll container's viewport
243
+ * and the element after scrolling. Finite and non-negative; default 16.
244
+ *
245
+ * Measured from the container's CONTENT origin, so a `paddingTop` on the
246
+ * ScrollView's own style, or an iOS `contentInset.top` / automatic
247
+ * safe-area inset, shifts where the element lands — add it here if the row
248
+ * must clear a header.
249
+ */
250
+ padding?: number;
251
+ }
171
252
  /**
172
253
  * Swipe action params
173
254
  */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/control/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACZ,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oBAAoB;IACpB,YAAY,CAAC,EAAE;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;IACjE,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,kCAAkC;IAClC,GAAG,EAAE,OAAO,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAEhG;;OAEG;IACH,sBAAsB,CACpB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAEpC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE9D;;OAEG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAE7E,mEAAmE;IACnE,gBAAgB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI,CAAC;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,mCAAmC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,oBAAoB;IACpB,MAAM,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,kCAAkC;IAClC,QAAQ,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sBAAsB;IACtB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC5C,iCAAiC;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,QAAQ,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/control/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Abandonment primitive for action invocation.
3
+ *
4
+ * Plan `2026-08-20-ui-bridge-action-declaration-shape`, Phase 3.
5
+ *
6
+ * `ActionHandler`'s `options.signal` is **cooperative**: a well-behaved handler
7
+ * observes it and returns early. Cooperation cannot be enforced, and a handler
8
+ * that hangs is exactly the case cancellation exists for — so the executor
9
+ * never trusts the handler to observe the signal. It races the handler promise
10
+ * against the abort and reports the outcome either way.
11
+ *
12
+ * DUPLICATE OF `@qontinui/ui-bridge` `src/core/abortable.ts` — DELIBERATELY NOT
13
+ * AN IMPORT. `@qontinui/ui-bridge` is an OPTIONAL peerDependency of this
14
+ * package and is absent from `dependencies`, so a consumer may install
15
+ * `@qontinui/ui-bridge-native` alone; importing from it would resolve inside
16
+ * this monorepo and then fail for that consumer. See the same note on
17
+ * `core/types.ts` `ActionHandler`.
18
+ *
19
+ * KEEP IN SYNC with `@qontinui/ui-bridge` `src/core/abortable.ts` — including
20
+ * `MAX_ACTION_TIMEOUT_MS` and `normalizeActionTimeoutMs` below. The module has
21
+ * no imports and touches no DOM API — only `AbortController` and `setTimeout`,
22
+ * both present in React Native.
23
+ */
24
+ /** Which of the two cancellation sources fired. */
25
+ export type AbortReason = 'signal' | 'timeout';
26
+ /**
27
+ * Ceiling applied to a caller-supplied `timeoutMs` — **24 hours**.
28
+ *
29
+ * `ComponentActionRequest.timeoutMs` crosses the wire, so it is attacker- (or
30
+ * typo-) controlled: an HTTP or WebSocket caller can put any JSON number in
31
+ * it and it would otherwise land in `setTimeout` unchecked. Two concrete
32
+ * hazards that ceiling closes:
33
+ *
34
+ * - **`setTimeout`'s 32-bit delay overflow.** Any delay above 2147483647ms
35
+ * wraps to a *negative* 32-bit int in every major runtime and the timer
36
+ * fires **immediately** — so `timeoutMs: 2147483648` ("about 25 days,
37
+ * effectively no timeout") would abandon the action on the next tick, the
38
+ * exact opposite of what the caller asked for. Clamping below that boundary
39
+ * makes the semantics monotonic: a bigger number never means a shorter wait.
40
+ * - **A pinned timer per in-flight request.** Nothing here is unbounded work,
41
+ * but a 100-year timeout is indistinguishable from "no timeout" while still
42
+ * holding the handler's abandonment machinery alive, so there is nothing to
43
+ * buy above a day.
44
+ *
45
+ * Clamping (rather than rejecting) is right at the top end because the intent
46
+ * is unambiguous — "effectively forever" — and the clamped value honours it as
47
+ * closely as the platform can. The malformed cases below are rejected instead,
48
+ * because there the intent is NOT recoverable.
49
+ */
50
+ export declare const MAX_ACTION_TIMEOUT_MS = 86400000;
51
+ /**
52
+ * Outcome of {@link normalizeActionTimeoutMs}. Discriminated on `ok` so a
53
+ * rejected value cannot be read as a timeout by accident.
54
+ */
55
+ export type TimeoutNormalization = {
56
+ ok: true;
57
+ /** `undefined` ≡ no timeout. Always a finite integer in `[0, MAX]`. */
58
+ timeoutMs: number | undefined;
59
+ /** True iff the caller's value was above {@link MAX_ACTION_TIMEOUT_MS}. */
60
+ clamped: boolean;
61
+ } | {
62
+ ok: false;
63
+ reason: string;
64
+ };
65
+ /**
66
+ * Validate and clamp a wire-supplied `timeoutMs` before it can reach a timer.
67
+ *
68
+ * The policy, stated once so all three executors share it:
69
+ *
70
+ * | Supplied | Result | Why |
71
+ * |---|---|---|
72
+ * | absent / `null` | no timeout | the documented "omitted ⇒ no timeout" default |
73
+ * | `0` | abandon on the next tick | a coherent request ("don't let it run"), and what `setTimeout(…, 0)` already means |
74
+ * | `1 … MAX` | honoured, floored to an integer | fractional ms is not a thing a timer can express |
75
+ * | `> MAX` | clamped to {@link MAX_ACTION_TIMEOUT_MS} | see that constant — above 2^31-1 the platform timer silently inverts |
76
+ * | negative | **rejected** | `setTimeout` would treat it as `0`, i.e. a sign typo would abandon every call instantly and silently |
77
+ * | `NaN` / `±Infinity` | **rejected** | `setTimeout(NaN)` is `setTimeout(0)` — same silent-instant-abandon trap |
78
+ * | not a number (`"5000"`, `{}`, `true`) | **rejected** | JSON has numbers; a string here means the caller built the body wrong, and coercing would hide it |
79
+ *
80
+ * Rejection is loud on purpose: every rejected case is one where *ignoring*
81
+ * the field fails open (the action runs uncancellable) and *coercing* it fails
82
+ * closed at zero. Neither is what the caller asked for, and both are silent —
83
+ * which is the defect class this whole plan exists to remove.
84
+ */
85
+ export declare function normalizeActionTimeoutMs(raw: unknown): TimeoutNormalization;
86
+ /**
87
+ * Result of {@link runAbortable}. Discriminated on `aborted` so the caller
88
+ * cannot read `result` off an abandoned invocation.
89
+ */
90
+ export type AbortableOutcome<T> = {
91
+ aborted: false;
92
+ result: T;
93
+ } | {
94
+ aborted: true;
95
+ reason: AbortReason;
96
+ };
97
+ /** Cancellation sources composed by {@link runAbortable}. */
98
+ export interface RunAbortableOptions {
99
+ /**
100
+ * An in-process caller's signal. Cannot cross the wire — that is what
101
+ * `timeoutMs` is for.
102
+ */
103
+ signal?: AbortSignal;
104
+ /**
105
+ * Milliseconds after which the invocation is abandoned. Serializable, so
106
+ * this is the arm an HTTP/WebSocket caller can actually use.
107
+ *
108
+ * Expected to have been through {@link normalizeActionTimeoutMs} already —
109
+ * every executor seam runs it, because this value arrives from the wire.
110
+ * The `Number.isFinite` / `>= 0` guard below is defence in depth for a
111
+ * direct in-process caller, and ignores anything malformed rather than
112
+ * letting it reach `setTimeout`.
113
+ */
114
+ timeoutMs?: number;
115
+ }
116
+ /**
117
+ * A fresh `AbortSignal` that is never aborted.
118
+ *
119
+ * `ActionHandlerOptions` promises the bag is *always* supplied, so a handler
120
+ * written the way the docs describe — `(params, { signal }) => …` — must never
121
+ * be called with `undefined` as its second argument. Not every invocation seam
122
+ * has a cancellation source to give it though: an ELEMENT custom action
123
+ * (`ControlActionRequest`) carries no `timeoutMs` and the executor holds no
124
+ * controller for it, so there is nothing that could ever abort. Those seams
125
+ * pass this instead of `undefined`, which keeps the destructure safe and keeps
126
+ * `signal.aborted` honestly `false`.
127
+ *
128
+ * **Fresh per call, deliberately.** A shared singleton would accumulate one
129
+ * listener per handler that calls `signal.addEventListener('abort', …)` and
130
+ * never releases them — a leak on a hot path. A `AbortController` allocation
131
+ * is a few bytes and custom element actions are not a hot path.
132
+ *
133
+ * When element actions grow a cancellation source, replace the call sites with
134
+ * a real `runAbortable` race — the handler contract does not change.
135
+ */
136
+ export declare function inertAbortSignal(): AbortSignal;
137
+ /**
138
+ * Invoke `invoke` with a derived `AbortSignal`, abandoning it if either the
139
+ * caller's signal aborts or `timeoutMs` elapses.
140
+ *
141
+ * - Returns `{ aborted: true, reason }` **without invoking at all** when the
142
+ * caller's signal is already aborted.
143
+ * - Returns `{ aborted: false, result }` on normal completion.
144
+ * - **Rejects** if `invoke` throws/rejects while the race is still live, so a
145
+ * genuine handler error stays distinguishable from a cancellation.
146
+ * - A rejection that arrives *after* an abort already won is swallowed:
147
+ * `Promise.race` has a rejection handler attached, so the abandoned handler
148
+ * cannot surface as an unhandled rejection.
149
+ */
150
+ export declare function runAbortable<T>(invoke: (signal: AbortSignal) => T | Promise<T>, options?: RunAbortableOptions): Promise<AbortableOutcome<T>>;
151
+ //# sourceMappingURL=abortable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abortable.d.ts","sourceRoot":"","sources":["../../src/core/abortable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,mDAAmD;AACnD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,qBAAqB,WAAa,CAAC;AAEhD;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IACE,EAAE,EAAE,IAAI,CAAC;IACT,uEAAuE;IACvE,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;CAClB,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB,CA0B3E;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,GAC7B;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAE3C,6DAA6D;AAC7D,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAE9C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,MAAM,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC/C,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAsD9B"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Action effect defaults for `@qontinui/ui-bridge-native`.
3
+ *
4
+ * Plan `2026-08-20-ui-bridge-action-declaration-shape`, Phase 4.
5
+ *
6
+ * `IREffect` ("read" | "write" | "destructive") has exactly one job: **exclude
7
+ * destructive actions from automatic walks.** Two sources feed it, in order:
8
+ *
9
+ * 1. `action.effect` — the author's explicit per-registration declaration.
10
+ * 2. `NATIVE_STANDARD_ACTION_EFFECTS[action.id]` — the static default below.
11
+ *
12
+ * **1 wins.** A static `press → write` map is wrong precisely on a delete
13
+ * control — guaranteed wrong in the one case the annotation exists for — and it
14
+ * fails *open*, so an unmarked destructive action gets walked.
15
+ *
16
+ * DUPLICATE of `@qontinui/ui-bridge` `src/core/action-effect.ts` +
17
+ * `src/native/core/action-effect.ts`, and deliberately not a re-export:
18
+ * `@qontinui/ui-bridge` is an OPTIONAL peer of this package, so a consumer may
19
+ * install `@qontinui/ui-bridge-native` alone. Same constraint that keeps
20
+ * `ActionHandler` / `ComponentAction` / `IREffect` duplicated in
21
+ * `./types` — see the long note there. KEEP IN SYNC.
22
+ */
23
+ import type { IREffect, NativeStandardAction } from './types';
24
+ /**
25
+ * Static default effect for each {@link NativeStandardAction} verb.
26
+ *
27
+ * Typed `Record<NativeStandardAction, IREffect>` so adding a verb without
28
+ * classifying it is a compile error — a *map* silently falling behind the
29
+ * *union* it describes is exactly the drift class this plan exists to fix.
30
+ *
31
+ * **No verb maps to `'destructive'`, and none ever should.** Destructiveness
32
+ * is a property of what a control does, not of the verb used to reach it;
33
+ * `'destructive'` is reachable only through an explicit `effect`.
34
+ *
35
+ * The non-obvious calls, justified:
36
+ *
37
+ * - **`longPress` → `read`.** The touch analogue of a right-click: it reveals
38
+ * a context menu / selection affordance. Long-press is *associated* with
39
+ * delete on mobile, but it only surfaces the option — the delete is a
40
+ * separate press with its own effect.
41
+ * - **`swipe` → `write`.** Genuinely ambiguous, and it resolves the other way
42
+ * from `longPress`: a swipe is sometimes just a scroll gesture (read), but
43
+ * swipe-to-delete / swipe-to-archive **commits on the gesture itself**, with
44
+ * nothing in the verb to tell the two apart. It takes the more cautious
45
+ * classification, and a swipe-to-delete row must still declare
46
+ * `effect: 'destructive'`.
47
+ * - **`focus` / `blur` → `read`.** They move focus, which is UI state, not
48
+ * persistent state.
49
+ * - **`scrollIntoView` → `read`.** It moves the declared scroll container's
50
+ * content offset (UI state) and fires no element handler.
51
+ *
52
+ * Note this union carries `click`, `setValue` and `scrollIntoView` that the
53
+ * `@qontinui/ui-bridge` `native/core` copy does not — a real divergence
54
+ * between the two native unions, not a sync error.
55
+ */
56
+ export declare const NATIVE_STANDARD_ACTION_EFFECTS: Record<NativeStandardAction, IREffect>;
57
+ /**
58
+ * The static default for a native action id, or `undefined` when the id is not
59
+ * one of the native standard verbs (the normal case for a `ComponentAction`,
60
+ * whose ids are free-form).
61
+ *
62
+ * `undefined` means **unknown**, not "safe" — a caller that walks unknown
63
+ * actions is choosing to fail open and should say so.
64
+ */
65
+ export declare function nativeStandardActionEffect(actionId: string): IREffect | undefined;
66
+ /**
67
+ * Resolve the effective annotation for a declared action: **explicit
68
+ * declaration first, static verb map second.**
69
+ */
70
+ export declare function resolveActionEffect(action: {
71
+ id: string;
72
+ effect?: IREffect;
73
+ }): IREffect | undefined;
74
+ //# sourceMappingURL=action-effect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-effect.d.ts","sourceRoot":"","sources":["../../src/core/action-effect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,oBAAoB,EAAE,QAAQ,CAiBjF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAIjF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,QAAQ,CAAC;CACnB,GAAG,QAAQ,GAAG,SAAS,CAEvB"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The ONE wire projection for an element's custom actions.
3
+ *
4
+ * Plan `2026-09-04-effect-calculus-joins-the-component-action-registry`,
5
+ * Design decision 4 step 3.
6
+ *
7
+ * DUPLICATE of `@qontinui/ui-bridge` `src/core/element-actions.ts`, for the same
8
+ * reason the types beside it are duplicated: this package must not import from
9
+ * `@qontinui/ui-bridge` (an optional peer). KEEP IN SYNC — a divergence here is
10
+ * a divergence in what the two channels advertise about the same annotation.
11
+ *
12
+ * ---------------------------------------------------------------------------
13
+ * WHAT THIS DOES NOT DO: default the effect
14
+ * ---------------------------------------------------------------------------
15
+ *
16
+ * `effect` is carried through **verbatim and undefaulted**. An action whose
17
+ * author declared nothing is emitted with `effect` absent, never with a
18
+ * manufactured `'read'` — a default rendered as a declaration is a fail-open lie
19
+ * on exactly the surface the annotation exists to protect. **Absent means
20
+ * UNCLASSIFIED, not safe**, which is what served policy `operating-rules`
21
+ * `what-makes-an-action-destructive` requires of an unestablished effect.
22
+ */
23
+ import type { CustomAction, SerializedElementAction } from './types';
24
+ type ProjectableCustomActions = Record<string, Pick<CustomAction, 'label' | 'description' | 'effect'> | undefined>;
25
+ /**
26
+ * Project `RegisteredNativeElement.customActions` to its wire shape.
27
+ *
28
+ * - `undefined` in → `undefined` out (an element with no custom actions must not
29
+ * start emitting `[]`; `JSON.stringify` keeps `[]` and drops `undefined`).
30
+ * - An empty record in → `[]` out, matching what `Object.keys({})` gave before.
31
+ *
32
+ * The emitted `id` is the RECORD KEY — the executor dispatches by key, so the
33
+ * key is the name a caller must send. Nullish entries are skipped: they carry no
34
+ * handler, so advertising them would advertise a capability that does not exist.
35
+ */
36
+ export declare function serializeElementCustomActions(customActions: ProjectableCustomActions | undefined): SerializedElementAction[] | undefined;
37
+ export {};
38
+ //# sourceMappingURL=element-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-actions.d.ts","sourceRoot":"","sources":["../../src/core/element-actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAErE,KAAK,wBAAwB,GAAG,MAAM,CACpC,MAAM,EACN,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,aAAa,GAAG,QAAQ,CAAC,GAAG,SAAS,CACnE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,wBAAwB,GAAG,SAAS,GAClD,uBAAuB,EAAE,GAAG,SAAS,CAcvC"}
@@ -4,6 +4,10 @@
4
4
  * Core types and registry for React Native.
5
5
  */
6
6
  export * from './types';
7
+ export * from './abortable';
8
+ export * from './param-schema';
9
+ export * from './action-effect';
7
10
  export * from './registry';
8
11
  export * from './element-identifier';
12
+ export { serializeElementCustomActions } from './element-actions';
9
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AAGxB,cAAc,aAAa,CAAC;AAG5B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AAGrC,OAAO,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC"}