@xmachines/play-dom 1.0.0-beta.50 → 1.0.0-beta.52

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.
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Vanilla DOM renderer for XMachines Play architecture with signal-driven rendering.
6
6
 
7
- Part of the [xmachines-js monorepo](../../README.md).
7
+ Part of the [XMachines Play monorepo](../../README.md).
8
8
 
9
9
  ## Installation
10
10
 
@@ -87,7 +87,9 @@ disconnect();
87
87
 
88
88
  ### `createPlayUI` — batteries-included factory with full options
89
89
 
90
- Use `createPlayUI` when you need render error handling, a fallback element, or a shared `registryResult` that you also need to reference programmatically (e.g. for `executeAction`).
90
+ Use `createPlayUI` when you need render error handling, a fallback element, navigation integration, computed functions, or custom validation — or when you need to reference `registryResult` programmatically (e.g. for `executeAction`).
91
+
92
+ Factory-level options (`functions`, `validationFunctions`, `navigate`, `onRenderError`, `fallback`) are closed over at creation time and applied on every `mount()` call. Per-mount options (`store`, `loading`) are passed to `mount()` itself.
91
93
 
92
94
  ```typescript
93
95
  import { defineRegistry, createPlayUI, schema } from "@xmachines/play-dom";
@@ -110,6 +112,10 @@ const registryResult = defineRegistry(catalog, {
110
112
  const mount = createPlayUI(registryResult, {
111
113
  onRenderError: console.error,
112
114
  fallback: document.getElementById("loading")!,
115
+ navigate: (path) => myRouter.push(path),
116
+ functions: {
117
+ fullName: (args) => `${args.first} ${args.last}`,
118
+ },
113
119
  });
114
120
 
115
121
  const disconnect = mount(actor, document.getElementById("app")!);
@@ -148,35 +154,112 @@ const renderer = new PlayRenderer(container, actor, registryResult.registry, {
148
154
  renderer.connect();
149
155
  ```
150
156
 
151
- ### `connectRenderer` — functional API (backward-compatible)
157
+ ## Provider Options
152
158
 
153
- `connectRenderer` is the original functional API, equivalent to creating a `PlayRenderer` and calling `connect()` in one step. Prefer `createRenderer` or `createPlayUI` for new code.
159
+ All entry points (`createPlayUI`, `PlayRenderer`) accept the same set of UI-provider options via `UIProviderOptions`. These are forwarded into `DomRenderContext` on every render pass, making them available to component implementations via `ctx.ctx.*`.
154
160
 
155
- ```typescript
156
- import { connectRenderer, defineRegistry, schema } from "@xmachines/play-dom";
161
+ ### `functions` — named compute functions for `$computed` prop expressions
157
162
 
158
- const registryResult = defineRegistry(catalog, {
159
- components: {
160
- Home: ({ props }) => {
161
- const el = document.createElement("section");
162
- el.textContent = props.title;
163
- return el;
164
- },
163
+ Enables `{ "$computed": "name", "args": {...} }` dynamic prop values in specs. Each function receives the resolved `args` object and returns the computed value.
164
+
165
+ ```typescript
166
+ const mount = createPlayUI(registryResult, {
167
+ functions: {
168
+ fullName: (args) => `${args.first} ${args.last}`,
169
+ formatDate: (args) => new Date(args.iso as string).toLocaleDateString(),
165
170
  },
166
- actions: {
167
- logout: async () => actor.send({ type: "auth.logout" }),
171
+ });
172
+ ```
173
+
174
+ Without `functions`, any `$computed` expression silently resolves to `undefined` (no throw, backward-compatible).
175
+
176
+ ### `validationFunctions` — custom field validation
177
+
178
+ Provides named validation functions for inline field validation within components. Functions receive `(value, args?)` and return `true` (valid) or `false` (invalid).
179
+
180
+ Unlike the framework renderers, the DOM renderer has no automatic `ValidationProvider` tree. Components must invoke validation explicitly using `runValidationCheck` / `runValidation` from `@json-render/core`, passing `ctx.ctx.validationFunctions` as `customFunctions`.
181
+
182
+ ```typescript
183
+ import { runValidationCheck } from "@json-render/core";
184
+
185
+ const mount = createPlayUI(registryResult, {
186
+ validationFunctions: {
187
+ isEven: (value) => typeof value === "number" && value % 2 === 0,
188
+ phoneNumber: (value) => /^\+?[\d\s\-()]{7,}$/.test(String(value)),
168
189
  },
169
190
  });
170
191
 
171
- const disconnect = connectRenderer({
172
- actor,
173
- registry: registryResult.registry,
174
- registryResult,
175
- container: document.getElementById("app")!,
192
+ // Inside a ComponentFn:
193
+ const MyField: ComponentFn<typeof catalog, "MyField"> = ({ ctx }) => {
194
+ const result = runValidationCheck(
195
+ { type: "isEven", message: "must be even" },
196
+ { value: someValue, stateModel: {}, customFunctions: ctx.ctx.validationFunctions },
197
+ );
198
+ // result.valid, result.message
199
+ };
200
+ ```
201
+
202
+ ### `navigate` — programmatic navigation from action bindings
203
+
204
+ A callback invoked when an action binding resolves with `onSuccess: { navigate: "/path" }`. The resolved path string is passed as the sole argument. Integrate with any router:
205
+
206
+ ```typescript
207
+ // React Router / TanStack Router / any push-based router:
208
+ const mount = createPlayUI(registryResult, {
209
+ navigate: (path) => myRouter.push(path),
176
210
  });
211
+ ```
177
212
 
178
- // Later:
179
- disconnect();
213
+ With a spec binding:
214
+
215
+ ```json
216
+ {
217
+ "on": {
218
+ "click": {
219
+ "action": "submitForm",
220
+ "onSuccess": { "navigate": "/dashboard" }
221
+ }
222
+ }
223
+ }
224
+ ```
225
+
226
+ When `submitForm` completes successfully, `navigate("/dashboard")` is called automatically.
227
+
228
+ The function is also readable by component implementations directly via `ctx.ctx.navigate` for cases where navigation needs to be triggered outside of an action binding.
229
+
230
+ ### `onRenderError` — unified error handler
231
+
232
+ Receives `(error, name)` for three distinct error classes:
233
+
234
+ - **Component render errors** — when a `ComponentFn` throws synchronously during `renderSpec`. `name` is the catalog component name (e.g. `"Home"`).
235
+ - **Action handler rejections (emit path)** — when an `ActionFn` throws or returns a rejected promise during `emit()`. `name` is the catalog action name (e.g. `"submitForm"`).
236
+ - **Action handler rejections (watch path)** — when an `ActionFn` rejects during a `watch` binding callback. `name` is the catalog action name.
237
+
238
+ ```typescript
239
+ const mount = createPlayUI(registryResult, {
240
+ onRenderError: (err, name) => {
241
+ // Route to your application's error tracking
242
+ Sentry.captureException(err, { extra: { name } });
243
+ },
244
+ });
245
+ ```
246
+
247
+ The argument order matches the upstream `RenderErrorHandler` type from `@json-render/core`: **error first, name second**. This is consistent with the framework renderers (`@json-render/solid`, `@json-render/react`).
248
+
249
+ Without `onRenderError`, all three error types are logged via `console.error` and swallowed. No exception propagates, and no unhandled promise rejection is created.
250
+
251
+ The handler is also available to component implementations via `ctx.ctx.onRenderError`, enabling components to route their own internal errors through the same channel:
252
+
253
+ ```typescript
254
+ const MyComponent: ComponentFn<typeof catalog, "MyComponent"> = ({ ctx }) => {
255
+ try {
256
+ const el = doSomethingRisky();
257
+ return el;
258
+ } catch (err) {
259
+ ctx.ctx.onRenderError?.(err, "MyComponent");
260
+ return null;
261
+ }
262
+ };
180
263
  ```
181
264
 
182
265
  ## API Summary
@@ -188,36 +271,33 @@ disconnect();
188
271
  | `createRenderer(catalog, components)` | function | One-call factory — returns `mount(actor, container, options?) → disconnect` |
189
272
  | `createPlayUI(registryResult, options?)` | function | Batteries-included factory — returns `MountFn` |
190
273
  | `PlayRenderer` | class | Class-based renderer with `connect()` / `disconnect()` lifecycle |
191
- | `connectRenderer(options)` | function | Functional API; backward-compatible alternative to `PlayRenderer` |
192
274
  | `defineRegistry(catalog, options)` | function | Build a catalog-typed `DomRegistry` with typed handlers |
193
275
  | `renderSpec(...)` | function | Pure Spec → DOM renderer (low-level) |
194
276
  | `schema` | const | The `@json-render/dom` schema — pass to `defineCatalog()` |
195
277
 
196
278
  ### Key Types
197
279
 
198
- | Type | Description |
199
- | ------------------------ | -------------------------------------------------------------------------------------- |
200
- | `ComponentFn<C, K>` | Catalog-typed component function — returns `HTMLElement \| Text \| null` |
201
- | `ComponentContext<C, K>` | Context passed to each component: `props`, `children`, `emit`, `on`, `bindings`, `ctx` |
202
- | `ActionFn<C, K>` | Catalog-typed action function — receives `(params, setState, state)` |
203
- | `EventHandle` | Handle returned by `on(eventName)` — has `emit()`, `shouldPreventDefault`, `bound` |
204
- | `SetState` | State updater: `(prev => next) => void` |
205
- | `DefineRegistryResult` | Result from `defineRegistry` — has `registry`, `handlers`, `executeAction` |
206
- | `PlayDomOptions` | Options for `PlayRenderer` and `connectRenderer` |
207
- | `BaseComponentProps<P>` | Catalog-agnostic component props for shared component libraries |
208
- | `DomRegistry` | Raw registry type: `Record<string, DomComponentRenderer>` |
209
- | `DomSchema` | Type of the `schema` export |
210
-
211
- ### Error Classes
212
-
213
- | Class | Error Code | Description |
214
- | ----------------------- | --------------------------------- | ---------------------------------------- |
215
- | `MissingCatalogError` | `PLAY_RENDERER_MISSING_CATALOG` | Components map was `null` or `undefined` |
216
- | `MissingComponentError` | `PLAY_RENDERER_MISSING_COMPONENT` | Component name not found in catalog |
280
+ | Type | Description |
281
+ | ------------------------ | ------------------------------------------------------------------------------------------ |
282
+ | `ComponentFn<C, K>` | Catalog-typed component function — returns `HTMLElement \| Text \| null` |
283
+ | `ComponentContext<C, K>` | Context passed to each component: `props`, `children`, `emit`, `on`, `bindings`, `ctx` |
284
+ | `ActionFn<C, K>` | Catalog-typed action function — receives `(params, setState, state)` |
285
+ | `EventHandle` | Handle returned by `on(eventName)` — has `emit()`, `shouldPreventDefault`, `bound` |
286
+ | `SetState` | State updater: `(prev => next) => void` |
287
+ | `DefineRegistryResult` | Result from `defineRegistry` — has `registry`, `handlers`, `executeAction` |
288
+ | `PlayDomOptions` | Options for `PlayRenderer` — extends `UIProviderOptions` |
289
+ | `CreatePlayUIOptions` | Options for `createPlayUI` — extends `UIProviderOptions`, adds `fallback` |
290
+ | `MountOptions` | Per-mount options for `MountFn`: `store`, `loading` |
291
+ | `MountFn` | The mount function returned by `createPlayUI`: `(actor, container, options?) → disconnect` |
292
+ | `UIProviderOptions` | Shared options: `functions`, `validationFunctions`, `navigate`, `onRenderError` |
293
+ | `BaseComponentProps<P>` | Catalog-agnostic component props for shared component libraries |
294
+ | `DomRegistry` | Raw registry type: `Record<string, DomComponentRenderer>` |
295
+ | `DomSchema` | Type of the `schema` export |
296
+ | `ComputedFunction` | Type for named compute functions used with the `functions` option |
217
297
 
218
298
  ## Rendering Behaviour
219
299
 
220
- - **Initial render is synchronous** — the container is populated before `connect()` or `connectRenderer()` returns.
300
+ - **Initial render is synchronous** — the container is populated before `connect()` returns.
221
301
  - **Signal-driven re-renders are microtask-deferred** — `watchSignal` schedules updates on the next microtask queue tick.
222
302
  - **Null view** clears the container. A `fallback` element can be shown on initial mount when the view is `null`; it is **not** re-appended if the view later transitions back to `null` after a non-null view.
223
303
  - **Double `connect()` is safe** — calling `connect()` on an already-connected renderer auto-disconnects first.
@@ -18,6 +18,13 @@ import type { PlayDomOptions } from "./types.js";
18
18
  * Watches `actor.currentView` via TC39 Signals and renders `DomComponentRenderer`
19
19
  * functions into `container` on every view transition. Cleared on `disconnect()`.
20
20
  *
21
+ * Options from `PlayDomOptions` (which extends `UIProviderOptions`) are all forwarded
22
+ * into `DomRenderContext` on every render pass:
23
+ * - `functions` — named compute functions for `{ $computed: "name" }` prop expressions
24
+ * - `validationFunctions` — custom validation functions, available at `ctx.ctx.validationFunctions`
25
+ * - `navigate` — navigation callback, invoked on `onSuccess: { navigate: "..." }` action bindings
26
+ * - `onRenderError` — called with `(error, name)` for component render errors and action handler rejections
27
+ *
21
28
  * **Preferred usage — via `registryResult`:**
22
29
  * ```typescript
23
30
  * import { PlayRenderer, defineRegistry } from "@xmachines/play-dom";
@@ -25,6 +32,8 @@ import type { PlayDomOptions } from "./types.js";
25
32
  * const registryResult = defineRegistry(catalog, { components, actions });
26
33
  * const renderer = new PlayRenderer(container, actor, registryResult.registry, {
27
34
  * registryResult, // wires setState/getState from xstate store automatically
35
+ * navigate: (path) => myRouter.push(path),
36
+ * functions: { fullName: (args) => `${args.first} ${args.last}` },
28
37
  * });
29
38
  * renderer.connect();
30
39
  * // Later:
@@ -65,11 +74,14 @@ export declare class PlayRenderer {
65
74
  * @param container - `HTMLElement` to render into. Cleared and repopulated on every view transition.
66
75
  * @param actor - Actor providing the `currentView` signal (must implement `Viewable`).
67
76
  * @param registry - Component renderer map — typically `registryResult.registry` from `defineRegistry`.
68
- * @param options - Configuration:
69
- * - `registryResult` — preferred; auto-wires `setState`/`state` from the xstate store.
70
- * - `handlers` — pre-resolved handler map (legacy; used when `registryResult` is absent).
71
- * - `store` — external `StateStore` (controlled mode; overrides `spec.state` seeding).
72
- * - `loading` — streaming mode flag; suppresses missing-child warnings.
77
+ * @param options - Configuration (see {@link PlayDomOptions}):
78
+ * - `registryResult` — auto-wires `setState`/`state` from the xstate store.
79
+ * - `store` — external `StateStore` (controlled mode; overrides `spec.state` seeding).
80
+ * - `loading` — streaming mode flag; suppresses missing-child warnings.
81
+ * - `functions` — named compute functions for `$computed` prop expressions.
82
+ * - `validationFunctions` — custom validation functions; available at `ctx.ctx.validationFunctions`.
83
+ * - `navigate` — navigation callback; invoked on `onSuccess: { navigate: "..." }`.
84
+ * - `onRenderError` — `(error, name)` handler for component render errors and action handler rejections; suppresses `console.error` fallback.
73
85
  */
74
86
  constructor(container: HTMLElement, actor: AbstractActor<AnyActorLogic> & Viewable, registry: DomRegistry, options?: PlayDomOptions);
75
87
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"PlayRenderer.d.ts","sourceRoot":"","sources":["../src/PlayRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAY,MAAM,uBAAuB,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAyBjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,qBAAa,YAAY;IAwBvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IA1BzB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,aAAa,CAAsB;IAC3C;;;;;;OAMG;IACH,OAAO,CAAC,KAAK,CAAQ;IAErB;;;;;;;;;OASG;gBAEe,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,EAC9C,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,cAAmB;IAG9C;;;;;;;;OAQG;IACH,OAAO,IAAI,IAAI;IAMf;;OAEG;IACH,UAAU,IAAI,IAAI;IAmBlB,OAAO,CAAC,MAAM;CAkGd"}
1
+ {"version":3,"file":"PlayRenderer.d.ts","sourceRoot":"","sources":["../src/PlayRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAY,MAAM,uBAAuB,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAY,MAAM,wBAAwB,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAyBjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,YAAY;IA2BvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7BzB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,aAAa,CAAsB;IAC3C;;;;;;OAMG;IACH,OAAO,CAAC,KAAK,CAAQ;IAErB;;;;;;;;;;;;OAYG;gBAEe,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,EAC9C,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,cAAmB;IAG9C;;;;;;;;OAQG;IACH,OAAO,IAAI,IAAI;IAMf;;OAEG;IACH,UAAU,IAAI,IAAI;IAmBlB,OAAO,CAAC,MAAM;CA8Fd"}
@@ -40,6 +40,13 @@ function toAtomState(state) {
40
40
  * Watches `actor.currentView` via TC39 Signals and renders `DomComponentRenderer`
41
41
  * functions into `container` on every view transition. Cleared on `disconnect()`.
42
42
  *
43
+ * Options from `PlayDomOptions` (which extends `UIProviderOptions`) are all forwarded
44
+ * into `DomRenderContext` on every render pass:
45
+ * - `functions` — named compute functions for `{ $computed: "name" }` prop expressions
46
+ * - `validationFunctions` — custom validation functions, available at `ctx.ctx.validationFunctions`
47
+ * - `navigate` — navigation callback, invoked on `onSuccess: { navigate: "..." }` action bindings
48
+ * - `onRenderError` — called with `(error, name)` for component render errors and action handler rejections
49
+ *
43
50
  * **Preferred usage — via `registryResult`:**
44
51
  * ```typescript
45
52
  * import { PlayRenderer, defineRegistry } from "@xmachines/play-dom";
@@ -47,6 +54,8 @@ function toAtomState(state) {
47
54
  * const registryResult = defineRegistry(catalog, { components, actions });
48
55
  * const renderer = new PlayRenderer(container, actor, registryResult.registry, {
49
56
  * registryResult, // wires setState/getState from xstate store automatically
57
+ * navigate: (path) => myRouter.push(path),
58
+ * functions: { fullName: (args) => `${args.first} ${args.last}` },
50
59
  * });
51
60
  * renderer.connect();
52
61
  * // Later:
@@ -87,11 +96,14 @@ export class PlayRenderer {
87
96
  * @param container - `HTMLElement` to render into. Cleared and repopulated on every view transition.
88
97
  * @param actor - Actor providing the `currentView` signal (must implement `Viewable`).
89
98
  * @param registry - Component renderer map — typically `registryResult.registry` from `defineRegistry`.
90
- * @param options - Configuration:
91
- * - `registryResult` — preferred; auto-wires `setState`/`state` from the xstate store.
92
- * - `handlers` — pre-resolved handler map (legacy; used when `registryResult` is absent).
93
- * - `store` — external `StateStore` (controlled mode; overrides `spec.state` seeding).
94
- * - `loading` — streaming mode flag; suppresses missing-child warnings.
99
+ * @param options - Configuration (see {@link PlayDomOptions}):
100
+ * - `registryResult` — auto-wires `setState`/`state` from the xstate store.
101
+ * - `store` — external `StateStore` (controlled mode; overrides `spec.state` seeding).
102
+ * - `loading` — streaming mode flag; suppresses missing-child warnings.
103
+ * - `functions` — named compute functions for `$computed` prop expressions.
104
+ * - `validationFunctions` — custom validation functions; available at `ctx.ctx.validationFunctions`.
105
+ * - `navigate` — navigation callback; invoked on `onSuccess: { navigate: "..." }`.
106
+ * - `onRenderError` — `(error, name)` handler for component render errors and action handler rejections; suppresses `console.error` fallback.
95
107
  */
96
108
  constructor(container, actor, registry, options = {}) {
97
109
  this.container = container;
@@ -179,19 +191,15 @@ export class PlayRenderer {
179
191
  // patch unless the StateStore contract is updated to match.
180
192
  store.update(next);
181
193
  };
182
- // Warn when both registryResult and handlers are provided — handlers is silently ignored.
183
- // This prevents silent data loss during migration from the legacy pattern.
184
- if (this.options.registryResult && this.options.handlers) {
185
- console.warn("[play-dom] Both registryResult and handlers were provided. " +
186
- "handlers is ignored when registryResult is present. " +
187
- "Remove the handlers option to silence this warning.");
188
- }
189
- // Resolve handlers: prefer registryResult (wires setState/getState from store),
190
- // fall back to pre-resolved handlers map for backward compatibility.
194
+ // Resolve handlers from registryResult (wires setState/getState from store).
191
195
  const handlers = this.options.registryResult
192
196
  ? this.options.registryResult.handlers(() => setState, () => store.getSnapshot())
193
- : (this.options.handlers ?? {});
197
+ : {};
194
198
  const loading = this.options.loading;
199
+ const functions = this.options.functions;
200
+ const validationFunctions = this.options.validationFunctions;
201
+ const navigate = this.options.navigate;
202
+ const onRenderError = this.options.onRenderError;
195
203
  const rerender = () => {
196
204
  // Guard: skip if PlayRenderer has been disconnected.
197
205
  // Handles the edge case where a StateStore implementation fires its
@@ -203,9 +211,9 @@ export class PlayRenderer {
203
211
  cleanup();
204
212
  this.watchCleanups = [];
205
213
  this.container.replaceChildren();
206
- const node = renderSpec(view, store, this.registry, send, handlers, undefined, undefined, undefined, loading, (cleanup) => {
214
+ const node = renderSpec(view, store, this.registry, send, handlers, undefined, onRenderError, functions, loading, (cleanup) => {
207
215
  this.watchCleanups.push(cleanup);
208
- });
216
+ }, validationFunctions, navigate);
209
217
  if (node)
210
218
  this.container.appendChild(node);
211
219
  };
@@ -1 +1 @@
1
- {"version":3,"file":"PlayRenderer.js","sourceRoot":"","sources":["../src/PlayRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAIvD;;;;;;;;;;;;GAYG;AACH,SAAS,WAAW,CAAC,KAAc;IAClC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAY,CAAC;QACtD,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAClD,OAAO,KAAgC,CAAC;QACzC,CAAC;IACF,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,OAAO,YAAY;IAwBN;IACA;IACA;IACA;IA1BV,OAAO,GAAwB,IAAI,CAAC;IACpC,gBAAgB,GAAwB,IAAI,CAAC;IAC7C,aAAa,GAAmB,EAAE,CAAC;IAC3C;;;;;;OAMG;IACK,KAAK,GAAG,IAAI,CAAC;IAErB;;;;;;;;;OASG;IACH,YACkB,SAAsB,EACtB,KAA8C,EAC9C,QAAqB,EACrB,UAA0B,EAAE;QAH5B,cAAS,GAAT,SAAS,CAAa;QACtB,UAAK,GAAL,KAAK,CAAyC;QAC9C,aAAQ,GAAR,QAAQ,CAAa;QACrB,YAAO,GAAP,OAAO,CAAqB;IAC3C,CAAC;IAEJ;;;;;;;;OAQG;IACH,OAAO;QACN,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;YAAE,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACjF,CAAC;IAED;;OAEG;IACH,UAAU;QACT,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,8EAA8E;QAC9E,+EAA+E;QAC/E,6EAA6E;QAC7E,4DAA4D;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACzC,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,wEAAwE;QACxE,sEAAsE;QACtE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,UAAU,EAAE,EAAE,CAAC;QACf,KAAK,MAAM,OAAO,IAAI,aAAa;YAAE,OAAO,EAAE,CAAC;QAC/C,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC;IAClC,CAAC;IAEO,MAAM,CAAC,IAAqB;QACnC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,6EAA6E;QAC7E,sEAAsE;QACtE,4EAA4E;QAC5E,+DAA+D;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACvC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,QAAQ,EAAE,EAAE,CAAC;QAEb,kEAAkE;QAClE,sEAAsE;QACtE,wEAAwE;QACxE,8DAA8D;QAC9D,MAAM,iBAAiB,GAAG,IAAI,CAAC,aAAa,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,KAAK,MAAM,OAAO,IAAI,iBAAiB;YAAE,OAAO,EAAE,CAAC;QAEnD,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,mEAAmE;QACnE,kEAAkE;QAClE,2EAA2E;QAC3E,sEAAsE;QACtE,MAAM,KAAK,GAAe,IAAI,CAAC,OAAO,CAAC,KAAK;YAC3C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK;YACpB,CAAC,CAAC,qBAAqB,CAAC;gBACtB,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACzC,CAAC,CAAC;QAEL,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE9C,wDAAwD;QACxD,wEAAwE;QACxE,gDAAgD;QAChD,MAAM,QAAQ,GAAa,CAAC,OAAO,EAAE,EAAE;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAC3B,yEAAyE;YACzE,6EAA6E;YAC7E,uEAAuE;YACvE,uEAAuE;YACvE,4DAA4D;YAC5D,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,CAAC;QAEF,0FAA0F;QAC1F,2EAA2E;QAC3E,IAAI,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC1D,OAAO,CAAC,IAAI,CACX,6DAA6D;gBAC5D,sDAAsD;gBACtD,qDAAqD,CACtD,CAAC;QACH,CAAC;QAED,gFAAgF;QAChF,qEAAqE;QACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc;YAC3C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CACpC,GAAG,EAAE,CAAC,QAAQ,EACd,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CACzB;YACF,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QAEjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;QAErC,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC3B,qDAAqD;YACrD,oEAAoE;YACpE,wEAAwE;YACxE,IAAI,CAAC,IAAI,CAAC,KAAK;gBAAE,OAAO;YACxB,2EAA2E;YAC3E,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa;gBAAE,OAAO,EAAE,CAAC;YACpD,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;YAExB,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,UAAU,CACtB,IAAI,EACJ,KAAK,EACL,IAAI,CAAC,QAAQ,EACb,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EACT,OAAO,EACP,CAAC,OAAO,EAAE,EAAE;gBACX,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC,CACD,CAAC;YACF,IAAI,IAAI;gBAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC,CAAC;QAEF,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAClD,QAAQ,EAAE,CAAC;IACZ,CAAC;CACD"}
1
+ {"version":3,"file":"PlayRenderer.js","sourceRoot":"","sources":["../src/PlayRenderer.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,27 @@
1
1
  /**
2
2
  * createPlayUI — batteries-included DOM factory.
3
3
  *
4
- * Takes a DefineRegistryResult (user calls defineRegistry themselves) and returns
5
- * a mount function. Calling mount(actor, container) starts the renderer and returns
6
- * a disconnect function for cleanup.
4
+ * Takes a `DefineRegistryResult` (the caller is responsible for calling
5
+ * `defineRegistry`) and returns a `MountFn`. Calling `mount(actor, container)`
6
+ * starts the renderer and returns a `disconnect` cleanup function.
7
7
  *
8
- * Parallel to <PlayUIProvider registryResult={...}> in framework renderers.
8
+ * Factory-level options (`functions`, `validationFunctions`, `navigate`,
9
+ * `onRenderError`, `fallback`) are closed over at creation time and applied on
10
+ * every `mount()` call. Per-mount options (`store`, `loading`) can be passed
11
+ * to the `mount()` call itself via `MountOptions`.
12
+ *
13
+ * Parallel to `<PlayUIProvider registryResult={...}>` in the framework renderers.
9
14
  *
10
15
  * @example
11
16
  * ```typescript
12
17
  * import { defineRegistry, createPlayUI } from "@xmachines/play-dom";
13
18
  *
14
19
  * const registryResult = defineRegistry(catalog, { components, actions });
15
- * const mount = createPlayUI(registryResult, { onRenderError: console.error });
20
+ * const mount = createPlayUI(registryResult, {
21
+ * onRenderError: console.error,
22
+ * navigate: (path) => myRouter.push(path),
23
+ * functions: { fullName: (args) => `${args.first} ${args.last}` },
24
+ * });
16
25
  * const disconnect = mount(actor, document.getElementById("app")!);
17
26
  *
18
27
  * // Later:
@@ -27,30 +36,49 @@ import type { StateStore } from "@json-render/core";
27
36
  import type { DefineRegistryResult } from "./json-render/types.js";
28
37
  import type { CreatePlayUIOptions } from "./types.js";
29
38
  /**
30
- * Per-mount options that can override factory-level settings.
39
+ * Per-mount options passed to the `MountFn` returned by `createPlayUI`.
40
+ *
41
+ * These override or supplement the factory-level options on a per-actor/container
42
+ * basis. Factory-level options (`functions`, `validationFunctions`, `navigate`,
43
+ * `onRenderError`, `fallback`) are set once when calling `createPlayUI`.
31
44
  */
32
45
  export interface MountOptions {
33
- /** Optional external StateStore (controlled mode). When omitted, a fresh atom is created per view. */
46
+ /**
47
+ * Optional external `StateStore` (controlled mode).
48
+ * When omitted, a fresh `@xstate/store` atom is created per view transition
49
+ * seeded from `spec.state`.
50
+ */
34
51
  store?: StateStore;
35
- /** When true, suppresses missing-child warnings during streaming spec ingestion. */
52
+ /**
53
+ * When `true`, suppresses missing-child warnings during streaming spec ingestion
54
+ * and exposes `ctx.ctx.loading` to component implementations.
55
+ */
36
56
  loading?: boolean;
37
57
  }
38
58
  /**
39
- * The mount function returned by createPlayUI.
40
- * Call with (actor, container, mountOptions?) to start the renderer.
41
- * Returns a disconnect function for cleanup.
59
+ * The mount function returned by `createPlayUI`.
60
+ *
61
+ * Call with `(actor, container, mountOptions?)` to start the renderer.
62
+ * Returns a `disconnect` cleanup function that stops rendering and clears
63
+ * the container.
42
64
  */
43
65
  export type MountFn = (actor: AbstractActor<AnyActorLogic> & Viewable, container: HTMLElement, options?: MountOptions) => () => void;
44
66
  /**
45
67
  * Create a batteries-included DOM renderer mount function.
46
68
  *
47
- * The user is responsible for calling defineRegistry to produce registryResult.
48
- * createPlayUI closes over the registryResult and returns a mount function that
49
- * can be called once per actor/container pair.
69
+ * The caller is responsible for producing `registryResult` via `defineRegistry`.
70
+ * `createPlayUI` closes over it and returns a `MountFn` that can be invoked
71
+ * once per actor/container pair.
50
72
  *
51
- * @param registryResult - Result from defineRegistry() containing registry + handlers factory.
52
- * @param options - Optional factory-level configuration (validationFunctions, navigate, etc.)
53
- * @returns mount function: (actor, container, mountOptions?) → disconnect
73
+ * @param registryResult - Result from `defineRegistry()` — provides the registry
74
+ * and the lazy handlers factory.
75
+ * @param options - Factory-level configuration (see {@link CreatePlayUIOptions}):
76
+ * - `functions` — named compute functions for `$computed` prop expressions.
77
+ * - `validationFunctions` — custom validation functions; available at `ctx.ctx.validationFunctions`.
78
+ * - `navigate` — navigation callback; invoked on `onSuccess: { navigate: "..." }`.
79
+ * - `onRenderError` — `(error, name)` handler for component render errors and action handler rejections.
80
+ * - `fallback` — element shown when the actor's initial view is `null`.
81
+ * @returns `MountFn`: `(actor, container, mountOptions?) → disconnect`
54
82
  */
55
83
  export declare function createPlayUI(registryResult: DefineRegistryResult, options?: CreatePlayUIOptions): MountFn;
56
84
  //# sourceMappingURL=create-play-ui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-play-ui.d.ts","sourceRoot":"","sources":["../src/create-play-ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,sGAAsG;IACtG,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,oFAAoF;IACpF,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,CACrB,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,EAC9C,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,YAAY,KAClB,MAAM,IAAI,CAAC;AAEhB;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC3B,cAAc,EAAE,oBAAoB,EACpC,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CA6CT"}
1
+ {"version":3,"file":"create-play-ui.d.ts","sourceRoot":"","sources":["../src/create-play-ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC5B;;;;OAIG;IACH,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,CACrB,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,EAC9C,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,YAAY,KAClB,MAAM,IAAI,CAAC;AAEhB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAC3B,cAAc,EAAE,oBAAoB,EACpC,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAmCT"}
@@ -1,18 +1,27 @@
1
1
  /**
2
2
  * createPlayUI — batteries-included DOM factory.
3
3
  *
4
- * Takes a DefineRegistryResult (user calls defineRegistry themselves) and returns
5
- * a mount function. Calling mount(actor, container) starts the renderer and returns
6
- * a disconnect function for cleanup.
4
+ * Takes a `DefineRegistryResult` (the caller is responsible for calling
5
+ * `defineRegistry`) and returns a `MountFn`. Calling `mount(actor, container)`
6
+ * starts the renderer and returns a `disconnect` cleanup function.
7
7
  *
8
- * Parallel to <PlayUIProvider registryResult={...}> in framework renderers.
8
+ * Factory-level options (`functions`, `validationFunctions`, `navigate`,
9
+ * `onRenderError`, `fallback`) are closed over at creation time and applied on
10
+ * every `mount()` call. Per-mount options (`store`, `loading`) can be passed
11
+ * to the `mount()` call itself via `MountOptions`.
12
+ *
13
+ * Parallel to `<PlayUIProvider registryResult={...}>` in the framework renderers.
9
14
  *
10
15
  * @example
11
16
  * ```typescript
12
17
  * import { defineRegistry, createPlayUI } from "@xmachines/play-dom";
13
18
  *
14
19
  * const registryResult = defineRegistry(catalog, { components, actions });
15
- * const mount = createPlayUI(registryResult, { onRenderError: console.error });
20
+ * const mount = createPlayUI(registryResult, {
21
+ * onRenderError: console.error,
22
+ * navigate: (path) => myRouter.push(path),
23
+ * functions: { fullName: (args) => `${args.first} ${args.last}` },
24
+ * });
16
25
  * const disconnect = mount(actor, document.getElementById("app")!);
17
26
  *
18
27
  * // Later:
@@ -25,45 +34,37 @@ import { PlayRenderer } from "./PlayRenderer.js";
25
34
  /**
26
35
  * Create a batteries-included DOM renderer mount function.
27
36
  *
28
- * The user is responsible for calling defineRegistry to produce registryResult.
29
- * createPlayUI closes over the registryResult and returns a mount function that
30
- * can be called once per actor/container pair.
37
+ * The caller is responsible for producing `registryResult` via `defineRegistry`.
38
+ * `createPlayUI` closes over it and returns a `MountFn` that can be invoked
39
+ * once per actor/container pair.
31
40
  *
32
- * @param registryResult - Result from defineRegistry() containing registry + handlers factory.
33
- * @param options - Optional factory-level configuration (validationFunctions, navigate, etc.)
34
- * @returns mount function: (actor, container, mountOptions?) → disconnect
41
+ * @param registryResult - Result from `defineRegistry()` — provides the registry
42
+ * and the lazy handlers factory.
43
+ * @param options - Factory-level configuration (see {@link CreatePlayUIOptions}):
44
+ * - `functions` — named compute functions for `$computed` prop expressions.
45
+ * - `validationFunctions` — custom validation functions; available at `ctx.ctx.validationFunctions`.
46
+ * - `navigate` — navigation callback; invoked on `onSuccess: { navigate: "..." }`.
47
+ * - `onRenderError` — `(error, name)` handler for component render errors and action handler rejections.
48
+ * - `fallback` — element shown when the actor's initial view is `null`.
49
+ * @returns `MountFn`: `(actor, container, mountOptions?) → disconnect`
35
50
  */
36
51
  export function createPlayUI(registryResult, options = {}) {
37
- const { onRenderError, fallback } = options;
38
- // Note: validationFunctions, navigate, functions are json-render provider features.
39
- // The DOM layer doesn't have a provider tree — these are noted for future integration
40
- // if a DOM ValidationProvider equivalent is introduced in @json-render/dom.
41
- // For now they are accepted in options for API parity but not forwarded.
52
+ const { onRenderError, fallback, functions, validationFunctions, navigate } = options;
42
53
  return function mount(actor, container, mountOptions) {
43
- // Build the registry: if onRenderError is provided, inject it via Object.defineProperty
44
- // (same pattern as framework renderers, centralised per D-19).
45
- // Note: spreading registryResult.registry does NOT copy non-enumerable properties —
46
- // this intentionally drops any registry-level onRenderError so the options-level
47
- // handler has sole authority (D-19 pattern).
48
- const registry = onRenderError
49
- ? (() => {
50
- const r = { ...registryResult.registry };
51
- Object.defineProperty(r, "onRenderError", {
52
- value: onRenderError,
53
- enumerable: false,
54
- configurable: true,
55
- });
56
- return r;
57
- })()
58
- : registryResult.registry;
54
+ // All UIProviderOptions (onRenderError, functions, validationFunctions, navigate) are
55
+ // forwarded directly through PlayDomOptions → PlayRenderer → renderSpec → DomRenderContext.
59
56
  const rendererOptions = {
60
57
  registryResult,
61
58
  ...(mountOptions?.store !== undefined && { store: mountOptions.store }),
62
59
  ...(mountOptions?.loading !== undefined && { loading: mountOptions.loading }),
60
+ ...(functions !== undefined && { functions }),
61
+ ...(validationFunctions !== undefined && { validationFunctions }),
62
+ ...(navigate !== undefined && { navigate }),
63
+ ...(onRenderError !== undefined && { onRenderError }),
63
64
  };
64
- const renderer = new PlayRenderer(container, actor, registry, rendererOptions);
65
+ const renderer = new PlayRenderer(container, actor, registryResult.registry, rendererOptions);
65
66
  renderer.connect();
66
- // Handle fallback for null view on initial mount (same pattern as connectRenderer).
67
+ // Handle fallback for null view on initial mount.
67
68
  // connect() calls _render() synchronously so the container is already populated
68
69
  // at this point if actor.currentView is non-null.
69
70
  if (fallback != null && container.childNodes.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"create-play-ui.js","sourceRoot":"","sources":["../src/create-play-ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAyBjD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAC3B,cAAoC,EACpC,UAA+B,EAAE;IAEjC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAC5C,oFAAoF;IACpF,sFAAsF;IACtF,4EAA4E;IAC5E,yEAAyE;IAEzE,OAAO,SAAS,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY;QACnD,wFAAwF;QACxF,+DAA+D;QAC/D,oFAAoF;QACpF,iFAAiF;QACjF,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,aAAa;YAC7B,CAAC,CAAC,CAAC,GAAG,EAAE;gBACN,MAAM,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;gBACzC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,eAAe,EAAE;oBACzC,KAAK,EAAE,aAAa;oBACpB,UAAU,EAAE,KAAK;oBACjB,YAAY,EAAE,IAAI;iBAClB,CAAC,CAAC;gBACH,OAAO,CAAC,CAAC;YACV,CAAC,CAAC,EAAE;YACL,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC;QAE3B,MAAM,eAAe,GAAG;YACvB,cAAc;YACd,GAAG,CAAC,YAAY,EAAE,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,CAAC;YACvE,GAAG,CAAC,YAAY,EAAE,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,EAAE,CAAC;SAC7E,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC/E,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEnB,oFAAoF;QACpF,gFAAgF;QAChF,kDAAkD;QAClD,IAAI,QAAQ,IAAI,IAAI,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;QAED,OAAO,SAAS,UAAU;YACzB,QAAQ,CAAC,UAAU,EAAE,CAAC;QACvB,CAAC,CAAC;IACH,CAAC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"create-play-ui.js","sourceRoot":"","sources":["../src/create-play-ui.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAsCjD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAC3B,cAAoC,EACpC,UAA+B,EAAE;IAEjC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,mBAAmB,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAEtF,OAAO,SAAS,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,YAAY;QACnD,sFAAsF;QACtF,4FAA4F;QAC5F,MAAM,eAAe,GAAG;YACvB,cAAc;YACd,GAAG,CAAC,YAAY,EAAE,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,CAAC;YACvE,GAAG,CAAC,YAAY,EAAE,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,OAAO,EAAE,CAAC;YAC7E,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;YAC7C,GAAG,CAAC,mBAAmB,KAAK,SAAS,IAAI,EAAE,mBAAmB,EAAE,CAAC;YACjE,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,EAAE,QAAQ,EAAE,CAAC;YAC3C,GAAG,CAAC,aAAa,KAAK,SAAS,IAAI,EAAE,aAAa,EAAE,CAAC;SACrD,CAAC;QAEF,MAAM,QAAQ,GAAG,IAAI,YAAY,CAChC,SAAS,EACT,KAAK,EACL,cAAc,CAAC,QAAQ,EACvB,eAAe,CACf,CAAC;QACF,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEnB,kDAAkD;QAClD,gFAAgF;QAChF,kDAAkD;QAClD,IAAI,QAAQ,IAAI,IAAI,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,CAAC;QAED,OAAO,SAAS,UAAU;YACzB,QAAQ,CAAC,UAAU,EAAE,CAAC;QACvB,CAAC,CAAC;IACH,CAAC,CAAC;AACH,CAAC"}
@@ -73,7 +73,8 @@ import type { PlayDomOptions } from "./types.js";
73
73
  * `registryResult` (it is always provided by `createRenderer` itself and cannot be overridden).
74
74
  *
75
75
  * If you need to call `registryResult.executeAction()` programmatically (outside the emit/on
76
- * flow), or share the same `registryResult` with `connectRenderer`, use `defineRegistry` and
76
+ * flow), or pass additional provider options (`navigate`, `onRenderError`, `functions`, etc.),
77
+ * use `createPlayUI` (which accepts the full `CreatePlayUIOptions`) or `defineRegistry` with
77
78
  * `PlayRenderer` directly rather than `createRenderer`.
78
79
  */
79
80
  export declare function createRenderer<C extends Catalog>(catalog: C, componentMap: ComponentRegistry<C>): (actor: AbstractActor<AnyActorLogic> & Viewable, container: HTMLElement, options?: Omit<PlayDomOptions, "registryResult">) => () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"create-renderer.d.ts","sourceRoot":"","sources":["../src/create-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,EAC/C,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAChC,CACF,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,EAC9C,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,KAC5C,MAAM,IAAI,CAWd"}
1
+ {"version":3,"file":"create-renderer.d.ts","sourceRoot":"","sources":["../src/create-renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,EAC/C,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAChC,CACF,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,EAC9C,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,gBAAgB,CAAC,KAC5C,MAAM,IAAI,CAWd"}
@@ -70,7 +70,8 @@ import { defineRegistry } from "./json-render/types.js";
70
70
  * `registryResult` (it is always provided by `createRenderer` itself and cannot be overridden).
71
71
  *
72
72
  * If you need to call `registryResult.executeAction()` programmatically (outside the emit/on
73
- * flow), or share the same `registryResult` with `connectRenderer`, use `defineRegistry` and
73
+ * flow), or pass additional provider options (`navigate`, `onRenderError`, `functions`, etc.),
74
+ * use `createPlayUI` (which accepts the full `CreatePlayUIOptions`) or `defineRegistry` with
74
75
  * `PlayRenderer` directly rather than `createRenderer`.
75
76
  */
76
77
  export function createRenderer(catalog, componentMap) {