@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 +123 -43
- package/dist/PlayRenderer.d.ts +17 -5
- package/dist/PlayRenderer.d.ts.map +1 -1
- package/dist/PlayRenderer.js +25 -17
- package/dist/PlayRenderer.js.map +1 -1
- package/dist/create-play-ui.d.ts +45 -17
- package/dist/create-play-ui.d.ts.map +1 -1
- package/dist/create-play-ui.js +35 -34
- package/dist/create-play-ui.js.map +1 -1
- package/dist/create-renderer.d.ts +2 -1
- package/dist/create-renderer.d.ts.map +1 -1
- package/dist/create-renderer.js +2 -1
- package/dist/create-renderer.js.map +1 -1
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +3 -3
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/json-render/renderer.d.ts +30 -17
- package/dist/json-render/renderer.d.ts.map +1 -1
- package/dist/json-render/renderer.js +53 -20
- package/dist/json-render/renderer.js.map +1 -1
- package/dist/json-render/types.d.ts +132 -14
- package/dist/json-render/types.d.ts.map +1 -1
- package/dist/json-render/types.js +25 -14
- package/dist/json-render/types.js.map +1 -1
- package/dist/types.d.ts +24 -89
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -5
- package/dist/connect-renderer.d.ts +0 -63
- package/dist/connect-renderer.d.ts.map +0 -1
- package/dist/connect-renderer.js +0 -87
- package/dist/connect-renderer.js.map +0 -1
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 [
|
|
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
|
|
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
|
-
|
|
157
|
+
## Provider Options
|
|
152
158
|
|
|
153
|
-
`
|
|
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
|
-
|
|
156
|
-
import { connectRenderer, defineRegistry, schema } from "@xmachines/play-dom";
|
|
161
|
+
### `functions` — named compute functions for `$computed` prop expressions
|
|
157
162
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
167
|
-
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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`
|
|
207
|
-
| `
|
|
208
|
-
| `
|
|
209
|
-
| `
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
|
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()`
|
|
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.
|
package/dist/PlayRenderer.d.ts
CHANGED
|
@@ -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`
|
|
70
|
-
* - `
|
|
71
|
-
* - `
|
|
72
|
-
* - `
|
|
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
|
|
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"}
|
package/dist/PlayRenderer.js
CHANGED
|
@@ -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`
|
|
92
|
-
* - `
|
|
93
|
-
* - `
|
|
94
|
-
* - `
|
|
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
|
-
//
|
|
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
|
-
:
|
|
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,
|
|
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
|
};
|
package/dist/PlayRenderer.js.map
CHANGED
|
@@ -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
|
|
1
|
+
{"version":3,"file":"PlayRenderer.js","sourceRoot":"","sources":["../src/PlayRenderer.ts"],"names":[],"mappings":"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"}
|
package/dist/create-play-ui.d.ts
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* createPlayUI — batteries-included DOM factory.
|
|
3
3
|
*
|
|
4
|
-
* Takes a DefineRegistryResult (
|
|
5
|
-
* a
|
|
6
|
-
* a disconnect function
|
|
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
|
-
*
|
|
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, {
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
41
|
-
*
|
|
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
|
|
48
|
-
* createPlayUI closes over
|
|
49
|
-
*
|
|
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()
|
|
52
|
-
*
|
|
53
|
-
* @
|
|
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
|
|
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"}
|
package/dist/create-play-ui.js
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* createPlayUI — batteries-included DOM factory.
|
|
3
3
|
*
|
|
4
|
-
* Takes a DefineRegistryResult (
|
|
5
|
-
* a
|
|
6
|
-
* a disconnect function
|
|
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
|
-
*
|
|
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, {
|
|
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
|
|
29
|
-
* createPlayUI closes over
|
|
30
|
-
*
|
|
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()
|
|
33
|
-
*
|
|
34
|
-
* @
|
|
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
|
-
//
|
|
44
|
-
//
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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"}
|
package/dist/create-renderer.js
CHANGED
|
@@ -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
|
|
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) {
|