@xmachines/play-vue 1.0.0-beta.30 → 1.0.0-beta.32
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 +31 -31
- package/dist/PlayRenderer.js.map +1 -1
- package/dist/PlayRenderer.vue.d.ts +5 -14
- package/dist/PlayRenderer.vue.d.ts.map +1 -1
- package/dist/PlayRenderer.vue_vue_type_script_lang.js +51 -34
- package/dist/PlayRenderer.vue_vue_type_script_lang.js.map +1 -1
- package/dist/define-registry.d.ts.map +1 -1
- package/dist/define-registry.js +1 -1
- package/dist/define-registry.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/node_modules/@json-render/core/dist/index.js +134 -81
- package/dist/node_modules/@json-render/core/dist/index.js.map +1 -1
- package/dist/node_modules/@json-render/vue/dist/index.js +259 -220
- package/dist/node_modules/@json-render/vue/dist/index.js.map +1 -1
- package/dist/node_modules/zod/v4/core/util.js +1 -1
- package/dist/node_modules/zod/v4/core/util.js.map +1 -1
- package/dist/types.d.ts +12 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/useActor.d.ts.map +1 -1
- package/dist/useActor.js +7 -8
- package/dist/useActor.js.map +1 -1
- package/package.json +19 -19
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ without muting console output.
|
|
|
36
36
|
- `PlayRenderer` — main renderer component (Vue SFC)
|
|
37
37
|
- `useActor` — composable for accessing the actor inside a `PlayRenderer` tree
|
|
38
38
|
- `defineRegistry` — SFC-aware wrapper; auto-wraps `.vue` SFCs via `h(SFC, ctx)`
|
|
39
|
-
- `
|
|
39
|
+
- `useBoundProp` — re-exported from `@json-render/vue`
|
|
40
40
|
- `ComponentFn` (type) — re-exported from `@json-render/vue`
|
|
41
41
|
- `ComponentContext` (type) — re-exported from `@json-render/vue`
|
|
42
42
|
- `PlayRendererProps` (type)
|
|
@@ -60,14 +60,14 @@ export type Catalog = typeof catalog;
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
```vue
|
|
63
|
-
<!-- Login.vue — Vue SFC;
|
|
63
|
+
<!-- Login.vue — Vue SFC; useBoundProp works in <script setup> -->
|
|
64
64
|
<script setup lang="ts">
|
|
65
|
-
import {
|
|
65
|
+
import { useBoundProp } from "@xmachines/play-vue";
|
|
66
66
|
import type { ComponentContext } from "@xmachines/play-vue";
|
|
67
67
|
import type { Catalog } from "./catalog.js";
|
|
68
68
|
|
|
69
69
|
const { props, emit, bindings } = defineProps<ComponentContext<Catalog, "Login">>();
|
|
70
|
-
const [username, setUsername] =
|
|
70
|
+
const [username, setUsername] = useBoundProp<string>(bindings?.username ?? "/username");
|
|
71
71
|
</script>
|
|
72
72
|
|
|
73
73
|
<template>
|
|
@@ -88,9 +88,17 @@ import { catalog } from "./catalog.js";
|
|
|
88
88
|
import LoginSFC from "./Login.vue";
|
|
89
89
|
import DashboardSFC from "./Dashboard.vue";
|
|
90
90
|
|
|
91
|
-
export const
|
|
91
|
+
export const registryResult = defineRegistry(catalog, {
|
|
92
92
|
components: { Login: LoginSFC, Dashboard: DashboardSFC },
|
|
93
|
-
actions: {
|
|
93
|
+
actions: {
|
|
94
|
+
login: async (params) => {
|
|
95
|
+
if (!params) return;
|
|
96
|
+
actor.send({ type: "auth.login", username: params.username });
|
|
97
|
+
},
|
|
98
|
+
logout: async (params) => {
|
|
99
|
+
actor.send({ type: "auth.logout" });
|
|
100
|
+
},
|
|
101
|
+
},
|
|
94
102
|
});
|
|
95
103
|
```
|
|
96
104
|
|
|
@@ -171,7 +179,7 @@ export const machine = setup({
|
|
|
171
179
|
import { definePlayer } from "@xmachines/play-xstate";
|
|
172
180
|
import { PlayRenderer } from "@xmachines/play-vue";
|
|
173
181
|
import { machine } from "./machine.js";
|
|
174
|
-
import {
|
|
182
|
+
import { registryResult } from "./registry.js";
|
|
175
183
|
|
|
176
184
|
const createPlayer = definePlayer({ machine });
|
|
177
185
|
const actor = createPlayer();
|
|
@@ -179,11 +187,7 @@ actor.start();
|
|
|
179
187
|
</script>
|
|
180
188
|
|
|
181
189
|
<template>
|
|
182
|
-
<PlayRenderer
|
|
183
|
-
:actor="actor"
|
|
184
|
-
:registry="registry"
|
|
185
|
-
:actions="{ login: 'auth.login', logout: 'auth.logout' }"
|
|
186
|
-
/>
|
|
190
|
+
<PlayRenderer :actor="actor" :registryResult="registryResult" />
|
|
187
191
|
</template>
|
|
188
192
|
```
|
|
189
193
|
|
|
@@ -194,23 +198,16 @@ actor.start();
|
|
|
194
198
|
Main Vue component. Subscribes to `actor.currentView` and renders the spec.
|
|
195
199
|
|
|
196
200
|
```vue
|
|
197
|
-
<PlayRenderer
|
|
198
|
-
:actor="actor"
|
|
199
|
-
:registry="registry"
|
|
200
|
-
:actions="{ login: 'auth.login' }"
|
|
201
|
-
:store="myStore"
|
|
202
|
-
/>
|
|
201
|
+
<PlayRenderer :actor="actor" :registryResult="registryResult" :store="myStore" />
|
|
203
202
|
```
|
|
204
203
|
|
|
205
204
|
**`actor`** — A `PlayerActor` (or any `AbstractActor & Viewable`). Provides the `currentView` signal.
|
|
206
205
|
|
|
207
|
-
**`
|
|
206
|
+
**`registryResult`** — The full `DefineRegistryResult` returned by `defineRegistry(catalog, { components, actions })` from `@xmachines/play-vue`. Pass `.vue` SFCs directly — they are auto-wrapped via `h(SFC, ctx)` so `useBoundProp` and other composables work inside `<script setup>`.
|
|
208
207
|
|
|
209
208
|
`defineRegistry` also accepts `onRenderError(error, elementType)`, which receives errors
|
|
210
209
|
caught by `@json-render/vue`'s inner element boundary before the default logger is used.
|
|
211
210
|
|
|
212
|
-
**`actions`** — Maps json-render action names (from spec `on` bindings) to XState event type strings. Type-checked against `EventFromLogic<TLogic>["type"]` when `TLogic` is specified.
|
|
213
|
-
|
|
214
211
|
**`store`** (optional) — Controls per-view UI state (`$state` bindings, form values):
|
|
215
212
|
|
|
216
213
|
- **Omitted (uncontrolled, default):** A fresh `@xstate/store` atom is created per view transition, seeded from `view.spec.state`.
|
|
@@ -228,9 +225,17 @@ const store: StateStore = xstateStoreStateStore({ atom: createAtom({ username: "
|
|
|
228
225
|
overriding the outer Vue error boundary:
|
|
229
226
|
|
|
230
227
|
```ts
|
|
231
|
-
export const
|
|
228
|
+
export const registryResult = defineRegistry(catalog, {
|
|
232
229
|
components: { Login: LoginSFC, Dashboard: DashboardSFC },
|
|
233
|
-
actions: {
|
|
230
|
+
actions: {
|
|
231
|
+
login: async (params) => {
|
|
232
|
+
if (!params) return;
|
|
233
|
+
actor.send({ type: "auth.login", username: params.username });
|
|
234
|
+
},
|
|
235
|
+
logout: async (params) => {
|
|
236
|
+
actor.send({ type: "auth.logout" });
|
|
237
|
+
},
|
|
238
|
+
},
|
|
234
239
|
onRenderError(error, elementType) {
|
|
235
240
|
reportExpectedRenderError(error, elementType);
|
|
236
241
|
},
|
|
@@ -238,12 +243,7 @@ export const { registry } = defineRegistry(catalog, {
|
|
|
238
243
|
```
|
|
239
244
|
|
|
240
245
|
```vue
|
|
241
|
-
<PlayRenderer
|
|
242
|
-
:actor="actor"
|
|
243
|
-
:registry="registry"
|
|
244
|
-
:store="store"
|
|
245
|
-
:actions="{ login: 'auth.login' }"
|
|
246
|
-
/>
|
|
246
|
+
<PlayRenderer :actor="actor" :registryResult="registryResult" :store="store" />
|
|
247
247
|
```
|
|
248
248
|
|
|
249
249
|
---
|
|
@@ -283,5 +283,5 @@ Priority: **route param fills `undefined` slots; explicit non-`undefined` spec p
|
|
|
283
283
|
- Vue reactivity is only used to trigger re-renders — not for business logic
|
|
284
284
|
- `actor.currentView` (TC39 Signal) is bridged to Vue's reactive system inside `PlayRenderer`
|
|
285
285
|
- Per-view UI state lives in an `@xstate/store` atom, not in Vue reactive state
|
|
286
|
-
- `@json-render/vue` drives rendering; `PlayRenderer` is the signal bridge — import `defineRegistry`, `ComponentFn`, `ComponentContext`, and `
|
|
287
|
-
- Vue views should be `.vue` SFCs using `ComponentContext<MyCatalog, "X">` — `defineRegistry` from `@xmachines/play-vue` auto-wraps them via `h(SFC, ctx)`, giving each SFC its own `setup()` context where `
|
|
286
|
+
- `@json-render/vue` drives rendering; `PlayRenderer` is the signal bridge — import `defineRegistry`, `ComponentFn`, `ComponentContext`, and `useBoundProp` from `@xmachines/play-vue`
|
|
287
|
+
- Vue views should be `.vue` SFCs using `ComponentContext<MyCatalog, "X">` — `defineRegistry` from `@xmachines/play-vue` auto-wraps them via `h(SFC, ctx)`, giving each SFC its own `setup()` context where `useBoundProp` and Vue composables work correctly
|
package/dist/PlayRenderer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlayRenderer.js","names":[],"sources":["../src/PlayRenderer.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayRenderer - Main Vue renderer component for XMachines Play architecture\n *\n * Architecture
|
|
1
|
+
{"version":3,"file":"PlayRenderer.js","names":[],"sources":["../src/PlayRenderer.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayRenderer - Main Vue renderer component for XMachines Play architecture\n *\n * Architecture:\n * - Subscribes to actor.currentView signal via TC39 Signal watcher\n * - Renders view.spec via StateProvider → ActionProvider → VisibilityProvider → Renderer\n * - Routes actor actions via registryResult.handlers() — real async dispatch functions\n * - Vue ref only for triggering renders, NOT business logic\n *\n * State store: uses external `store` prop if provided (controlled mode); otherwise\n * creates a fresh @xstate/store atom per view transition seeded from spec.state.\n *\n * @invariant Actor Authority - Actor decides all state transitions via guards\n * @invariant Passive Infrastructure - Component observes signals, sends events\n * @invariant Signal-Only Reactivity - Business logic state lives in actor signals\n */\n\nimport { defineComponent, ref, toRaw, markRaw, onUnmounted, h } from \"vue\";\nimport type { PropType } from \"vue\";\nimport { watchSignal } from \"@xmachines/play-signals\";\nimport type { PlayRendererProps } from \"./types.js\";\nimport type { AbstractActor, Viewable, ViewMetadata } from \"@xmachines/play-actor\";\nimport type { AnyActorLogic } from \"xstate\";\nimport type { DefineRegistryResult } from \"@json-render/vue\";\nimport type { StateStore } from \"@json-render/core\";\nimport {\n\tRenderer,\n\tStateProvider,\n\tActionProvider,\n\tVisibilityProvider,\n\tuseStateStore,\n} from \"@json-render/vue\";\nimport type { SetState } from \"@json-render/vue\";\nimport { createAtom } from \"@xstate/store\";\nimport { xstateStoreStateStore } from \"@json-render/xstate\";\nimport { provideActor, type PlayActor } from \"./useActor.js\";\n\n/**\n * Inner component that renders inside StateProvider so it can call useStateStore()\n * to get the live set/getSnapshot functions needed by registryResult.handlers().\n */\nconst PlayRendererInner = defineComponent({\n\tname: \"PlayRendererInner\",\n\tprops: {\n\t\tregistryResult: {\n\t\t\ttype: Object as PropType<DefineRegistryResult>,\n\t\t\trequired: true,\n\t\t},\n\t\tspec: {\n\t\t\ttype: Object as PropType<import(\"@json-render/core\").Spec | null>,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tsetup(props) {\n\t\treturn () => {\n\t\t\tconst { update, getSnapshot } = useStateStore();\n\t\t\t// Build a SetState adapter: handlers factory expects updater-function pattern\n\t\t\tconst setStateAdapter: SetState = (updater) => {\n\t\t\t\tconst prev = getSnapshot();\n\t\t\t\tupdate(updater(prev));\n\t\t\t};\n\t\t\tconst handlers = props.registryResult.handlers(\n\t\t\t\t() => setStateAdapter,\n\t\t\t\t() => getSnapshot(),\n\t\t\t);\n\t\t\tconst rawRegistry = props.registryResult.registry;\n\n\t\t\treturn h(ActionProvider, { handlers }, () =>\n\t\t\t\th(VisibilityProvider, {}, () =>\n\t\t\t\t\th(Renderer, { spec: props.spec, registry: rawRegistry }),\n\t\t\t\t),\n\t\t\t);\n\t\t};\n\t},\n});\n\nexport default defineComponent({\n\tname: \"PlayRenderer\",\n\tprops: {\n\t\tactor: {\n\t\t\ttype: Object as PropType<AbstractActor<AnyActorLogic> & Viewable>,\n\t\t\trequired: true,\n\t\t},\n\t\tregistryResult: {\n\t\t\ttype: Object as PropType<DefineRegistryResult>,\n\t\t\trequired: true,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<StateStore>,\n\t\t\tdefault: undefined,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\t// Unwrap actor from Vue's reactive proxy to access raw Signal objects\n\t\tconst actor = toRaw(props.actor);\n\n\t\t// Unwrap the registryResult and mark components as raw to avoid Vue reactivity overhead\n\t\tconst rawRegistryResult: DefineRegistryResult = {\n\t\t\t...toRaw(props.registryResult),\n\t\t\tregistry: markRaw(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tObject.entries(toRaw(props.registryResult).registry).map(([k, v]) => [\n\t\t\t\t\t\tk,\n\t\t\t\t\t\tmarkRaw(v as object),\n\t\t\t\t\t]),\n\t\t\t\t) as DefineRegistryResult[\"registry\"],\n\t\t\t),\n\t\t};\n\n\t\t// Provide the raw actor to all descendants via Vue's provide/inject mechanism\n\t\tprovideActor(actor as PlayActor);\n\n\t\t// Get initial value from unwrapped signal\n\t\tconst initialView = actor.currentView.get();\n\n\t\t// Vue ref for triggering re-renders (NOT business logic state)\n\t\tconst view = ref<ViewMetadata | null>(initialView);\n\n\t\t// Internal per-view store — recreated on each view transition when no external store.\n\t\tlet internalStore: StateStore | null = null;\n\t\tlet lastView: ViewMetadata | null = null;\n\t\tlet storeKey = 0;\n\n\t\t// Signal watcher for bridging TC39 Signals to Vue reactivity\n\t\tconst unwatch = watchSignal(actor.currentView, (nextView) => {\n\t\t\tview.value = nextView;\n\t\t});\n\n\t\tonUnmounted(() => {\n\t\t\tunwatch();\n\t\t});\n\n\t\treturn () => {\n\t\t\t// No view — show fallback slot\n\t\t\tif (!view.value) {\n\t\t\t\treturn slots.fallback ? slots.fallback() : null;\n\t\t\t}\n\n\t\t\tconst spec = view.value.spec;\n\n\t\t\t// Resolve the store: external (controlled) or internal per-view atom\n\t\t\tlet store: StateStore;\n\t\t\tif (props.store) {\n\t\t\t\tstore = props.store;\n\t\t\t} else {\n\t\t\t\tif (internalStore === null || lastView !== view.value) {\n\t\t\t\t\tconst initialState = (spec.state as Record<string, unknown>) ?? {};\n\t\t\t\t\tinternalStore = xstateStoreStateStore({ atom: createAtom(initialState) });\n\t\t\t\t\tlastView = view.value;\n\t\t\t\t\tstoreKey++;\n\t\t\t\t}\n\t\t\t\tstore = internalStore;\n\t\t\t}\n\n\t\t\t// PlayRendererInner renders inside StateProvider so useStateStore() works\n\t\t\treturn h(StateProvider, { store, key: storeKey }, () =>\n\t\t\t\th(PlayRendererInner, { registryResult: rawRegistryResult, spec }),\n\t\t\t);\n\t\t};\n\t},\n});\n</script>\n"],"mappings":""}
|
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
import { PropType } from 'vue';
|
|
2
2
|
import { AbstractActor, Viewable } from '@xmachines/play-actor';
|
|
3
3
|
import { AnyActorLogic } from 'xstate';
|
|
4
|
-
import {
|
|
4
|
+
import { DefineRegistryResult } from '@json-render/vue';
|
|
5
5
|
import { StateStore } from '@json-render/core';
|
|
6
6
|
declare const _default: import('vue', { with: { "resolution-mode": "import" } }).DefineComponent<import('vue', { with: { "resolution-mode": "import" } }).ExtractPropTypes<{
|
|
7
7
|
actor: {
|
|
8
8
|
type: PropType<AbstractActor<AnyActorLogic> & Viewable>;
|
|
9
9
|
required: true;
|
|
10
10
|
};
|
|
11
|
-
|
|
12
|
-
type: PropType<
|
|
11
|
+
registryResult: {
|
|
12
|
+
type: PropType<DefineRegistryResult>;
|
|
13
13
|
required: true;
|
|
14
14
|
};
|
|
15
15
|
store: {
|
|
16
16
|
type: PropType<StateStore>;
|
|
17
17
|
default: undefined;
|
|
18
18
|
};
|
|
19
|
-
actions: {
|
|
20
|
-
type: PropType<Record<string, string>>;
|
|
21
|
-
default: () => {};
|
|
22
|
-
};
|
|
23
19
|
}>, () => import('vue', { with: { "resolution-mode": "import" } }).VNode<import('vue', { with: { "resolution-mode": "import" } }).RendererNode, import('vue', { with: { "resolution-mode": "import" } }).RendererElement, {
|
|
24
20
|
[key: string]: any;
|
|
25
21
|
}> | import('vue', { with: { "resolution-mode": "import" } }).VNode<import('vue', { with: { "resolution-mode": "import" } }).RendererNode, import('vue', { with: { "resolution-mode": "import" } }).RendererElement, {
|
|
@@ -29,21 +25,16 @@ declare const _default: import('vue', { with: { "resolution-mode": "import" } })
|
|
|
29
25
|
type: PropType<AbstractActor<AnyActorLogic> & Viewable>;
|
|
30
26
|
required: true;
|
|
31
27
|
};
|
|
32
|
-
|
|
33
|
-
type: PropType<
|
|
28
|
+
registryResult: {
|
|
29
|
+
type: PropType<DefineRegistryResult>;
|
|
34
30
|
required: true;
|
|
35
31
|
};
|
|
36
32
|
store: {
|
|
37
33
|
type: PropType<StateStore>;
|
|
38
34
|
default: undefined;
|
|
39
35
|
};
|
|
40
|
-
actions: {
|
|
41
|
-
type: PropType<Record<string, string>>;
|
|
42
|
-
default: () => {};
|
|
43
|
-
};
|
|
44
36
|
}>> & Readonly<{}>, {
|
|
45
37
|
store: StateStore;
|
|
46
|
-
actions: Record<string, string>;
|
|
47
38
|
}, {}, {}, {}, string, import('vue', { with: { "resolution-mode": "import" } }).ComponentProvideOptions, true, {}, any>;
|
|
48
39
|
export default _default;
|
|
49
40
|
//# sourceMappingURL=PlayRenderer.vue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlayRenderer.vue.d.ts","sourceRoot":"","sources":["../src/PlayRenderer.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PlayRenderer.vue.d.ts","sourceRoot":"","sources":["../src/PlayRenderer.vue"],"names":[],"mappings":"AAuLA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAGpC,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAgB,MAAM,uBAAuB,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;;;cAwDjC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC;;;;cAIjD,QAAQ,CAAC,oBAAoB,CAAC;;;;cAI9B,QAAQ,CAAC,UAAU,CAAC;;;;;;;;;cARpB,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,GAAG,QAAQ,CAAC;;;;cAIjD,QAAQ,CAAC,oBAAoB,CAAC;;;;cAI9B,QAAQ,CAAC,UAAU,CAAC;;;;;;AAZvC,wBAoFG"}
|
|
@@ -1,57 +1,74 @@
|
|
|
1
|
-
import { ActionProvider as e, Renderer as t, StateProvider as n, VisibilityProvider as r } from "./node_modules/@json-render/vue/dist/index.js";
|
|
2
|
-
import { createAtom as
|
|
3
|
-
import { xstateStoreStateStore as
|
|
4
|
-
import { provideActor as
|
|
5
|
-
import { defineComponent as
|
|
6
|
-
import { watchSignal as
|
|
1
|
+
import { ActionProvider as e, Renderer as t, StateProvider as n, VisibilityProvider as r, useStateStore as i } from "./node_modules/@json-render/vue/dist/index.js";
|
|
2
|
+
import { createAtom as a } from "./node_modules/@xstate/store/dist/store-69e7e2d5.esm.js";
|
|
3
|
+
import { xstateStoreStateStore as o } from "./node_modules/@json-render/xstate/dist/index.js";
|
|
4
|
+
import { provideActor as s } from "./useActor.js";
|
|
5
|
+
import { defineComponent as c, h as l, markRaw as u, onUnmounted as d, ref as f, toRaw as p } from "vue";
|
|
6
|
+
import { watchSignal as m } from "@xmachines/play-signals";
|
|
7
7
|
//#region src/PlayRenderer.vue?vue&type=script&lang.ts
|
|
8
|
-
var
|
|
8
|
+
var h = c({
|
|
9
|
+
name: "PlayRendererInner",
|
|
10
|
+
props: {
|
|
11
|
+
registryResult: {
|
|
12
|
+
type: Object,
|
|
13
|
+
required: !0
|
|
14
|
+
},
|
|
15
|
+
spec: {
|
|
16
|
+
type: Object,
|
|
17
|
+
default: null
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
setup(n) {
|
|
21
|
+
return () => {
|
|
22
|
+
let { update: a, getSnapshot: o } = i(), s = (e) => {
|
|
23
|
+
a(e(o()));
|
|
24
|
+
}, c = n.registryResult.handlers(() => s, () => o()), u = n.registryResult.registry;
|
|
25
|
+
return l(e, { handlers: c }, () => l(r, {}, () => l(t, {
|
|
26
|
+
spec: n.spec,
|
|
27
|
+
registry: u
|
|
28
|
+
})));
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}), g = c({
|
|
9
32
|
name: "PlayRenderer",
|
|
10
33
|
props: {
|
|
11
34
|
actor: {
|
|
12
35
|
type: Object,
|
|
13
36
|
required: !0
|
|
14
37
|
},
|
|
15
|
-
|
|
38
|
+
registryResult: {
|
|
16
39
|
type: Object,
|
|
17
40
|
required: !0
|
|
18
41
|
},
|
|
19
42
|
store: {
|
|
20
43
|
type: Object,
|
|
21
44
|
default: void 0
|
|
22
|
-
},
|
|
23
|
-
actions: {
|
|
24
|
-
type: Object,
|
|
25
|
-
default: () => ({})
|
|
26
45
|
}
|
|
27
46
|
},
|
|
28
|
-
setup(
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
47
|
+
setup(e, { slots: t }) {
|
|
48
|
+
let r = p(e.actor), i = {
|
|
49
|
+
...p(e.registryResult),
|
|
50
|
+
registry: u(Object.fromEntries(Object.entries(p(e.registryResult).registry).map(([e, t]) => [e, u(t)])))
|
|
51
|
+
};
|
|
52
|
+
s(r);
|
|
53
|
+
let c = f(r.currentView.get()), g = null, _ = null, v = 0, y = m(r.currentView, (e) => {
|
|
54
|
+
c.value = e;
|
|
33
55
|
});
|
|
34
|
-
return
|
|
35
|
-
|
|
56
|
+
return d(() => {
|
|
57
|
+
y();
|
|
36
58
|
}), () => {
|
|
37
|
-
if (!
|
|
38
|
-
let
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
key: b
|
|
47
|
-
}, () => c(e, { handlers: u }, () => c(r, {}, () => c(t, {
|
|
48
|
-
spec: o,
|
|
49
|
-
registry: g
|
|
50
|
-
}))));
|
|
59
|
+
if (!c.value) return t.fallback ? t.fallback() : null;
|
|
60
|
+
let r = c.value.spec, s;
|
|
61
|
+
return e.store ? s = e.store : ((g === null || _ !== c.value) && (g = o({ atom: a(r.state ?? {}) }), _ = c.value, v++), s = g), l(n, {
|
|
62
|
+
store: s,
|
|
63
|
+
key: v
|
|
64
|
+
}, () => l(h, {
|
|
65
|
+
registryResult: i,
|
|
66
|
+
spec: r
|
|
67
|
+
}));
|
|
51
68
|
};
|
|
52
69
|
}
|
|
53
70
|
});
|
|
54
71
|
//#endregion
|
|
55
|
-
export {
|
|
72
|
+
export { g as default };
|
|
56
73
|
|
|
57
74
|
//# sourceMappingURL=PlayRenderer.vue_vue_type_script_lang.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlayRenderer.vue_vue_type_script_lang.js","names":[],"sources":["../src/PlayRenderer.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayRenderer - Main Vue renderer component for XMachines Play architecture\n *\n * Architecture
|
|
1
|
+
{"version":3,"file":"PlayRenderer.vue_vue_type_script_lang.js","names":[],"sources":["../src/PlayRenderer.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayRenderer - Main Vue renderer component for XMachines Play architecture\n *\n * Architecture:\n * - Subscribes to actor.currentView signal via TC39 Signal watcher\n * - Renders view.spec via StateProvider → ActionProvider → VisibilityProvider → Renderer\n * - Routes actor actions via registryResult.handlers() — real async dispatch functions\n * - Vue ref only for triggering renders, NOT business logic\n *\n * State store: uses external `store` prop if provided (controlled mode); otherwise\n * creates a fresh @xstate/store atom per view transition seeded from spec.state.\n *\n * @invariant Actor Authority - Actor decides all state transitions via guards\n * @invariant Passive Infrastructure - Component observes signals, sends events\n * @invariant Signal-Only Reactivity - Business logic state lives in actor signals\n */\n\nimport { defineComponent, ref, toRaw, markRaw, onUnmounted, h } from \"vue\";\nimport type { PropType } from \"vue\";\nimport { watchSignal } from \"@xmachines/play-signals\";\nimport type { PlayRendererProps } from \"./types.js\";\nimport type { AbstractActor, Viewable, ViewMetadata } from \"@xmachines/play-actor\";\nimport type { AnyActorLogic } from \"xstate\";\nimport type { DefineRegistryResult } from \"@json-render/vue\";\nimport type { StateStore } from \"@json-render/core\";\nimport {\n\tRenderer,\n\tStateProvider,\n\tActionProvider,\n\tVisibilityProvider,\n\tuseStateStore,\n} from \"@json-render/vue\";\nimport type { SetState } from \"@json-render/vue\";\nimport { createAtom } from \"@xstate/store\";\nimport { xstateStoreStateStore } from \"@json-render/xstate\";\nimport { provideActor, type PlayActor } from \"./useActor.js\";\n\n/**\n * Inner component that renders inside StateProvider so it can call useStateStore()\n * to get the live set/getSnapshot functions needed by registryResult.handlers().\n */\nconst PlayRendererInner = defineComponent({\n\tname: \"PlayRendererInner\",\n\tprops: {\n\t\tregistryResult: {\n\t\t\ttype: Object as PropType<DefineRegistryResult>,\n\t\t\trequired: true,\n\t\t},\n\t\tspec: {\n\t\t\ttype: Object as PropType<import(\"@json-render/core\").Spec | null>,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\tsetup(props) {\n\t\treturn () => {\n\t\t\tconst { update, getSnapshot } = useStateStore();\n\t\t\t// Build a SetState adapter: handlers factory expects updater-function pattern\n\t\t\tconst setStateAdapter: SetState = (updater) => {\n\t\t\t\tconst prev = getSnapshot();\n\t\t\t\tupdate(updater(prev));\n\t\t\t};\n\t\t\tconst handlers = props.registryResult.handlers(\n\t\t\t\t() => setStateAdapter,\n\t\t\t\t() => getSnapshot(),\n\t\t\t);\n\t\t\tconst rawRegistry = props.registryResult.registry;\n\n\t\t\treturn h(ActionProvider, { handlers }, () =>\n\t\t\t\th(VisibilityProvider, {}, () =>\n\t\t\t\t\th(Renderer, { spec: props.spec, registry: rawRegistry }),\n\t\t\t\t),\n\t\t\t);\n\t\t};\n\t},\n});\n\nexport default defineComponent({\n\tname: \"PlayRenderer\",\n\tprops: {\n\t\tactor: {\n\t\t\ttype: Object as PropType<AbstractActor<AnyActorLogic> & Viewable>,\n\t\t\trequired: true,\n\t\t},\n\t\tregistryResult: {\n\t\t\ttype: Object as PropType<DefineRegistryResult>,\n\t\t\trequired: true,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<StateStore>,\n\t\t\tdefault: undefined,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\t// Unwrap actor from Vue's reactive proxy to access raw Signal objects\n\t\tconst actor = toRaw(props.actor);\n\n\t\t// Unwrap the registryResult and mark components as raw to avoid Vue reactivity overhead\n\t\tconst rawRegistryResult: DefineRegistryResult = {\n\t\t\t...toRaw(props.registryResult),\n\t\t\tregistry: markRaw(\n\t\t\t\tObject.fromEntries(\n\t\t\t\t\tObject.entries(toRaw(props.registryResult).registry).map(([k, v]) => [\n\t\t\t\t\t\tk,\n\t\t\t\t\t\tmarkRaw(v as object),\n\t\t\t\t\t]),\n\t\t\t\t) as DefineRegistryResult[\"registry\"],\n\t\t\t),\n\t\t};\n\n\t\t// Provide the raw actor to all descendants via Vue's provide/inject mechanism\n\t\tprovideActor(actor as PlayActor);\n\n\t\t// Get initial value from unwrapped signal\n\t\tconst initialView = actor.currentView.get();\n\n\t\t// Vue ref for triggering re-renders (NOT business logic state)\n\t\tconst view = ref<ViewMetadata | null>(initialView);\n\n\t\t// Internal per-view store — recreated on each view transition when no external store.\n\t\tlet internalStore: StateStore | null = null;\n\t\tlet lastView: ViewMetadata | null = null;\n\t\tlet storeKey = 0;\n\n\t\t// Signal watcher for bridging TC39 Signals to Vue reactivity\n\t\tconst unwatch = watchSignal(actor.currentView, (nextView) => {\n\t\t\tview.value = nextView;\n\t\t});\n\n\t\tonUnmounted(() => {\n\t\t\tunwatch();\n\t\t});\n\n\t\treturn () => {\n\t\t\t// No view — show fallback slot\n\t\t\tif (!view.value) {\n\t\t\t\treturn slots.fallback ? slots.fallback() : null;\n\t\t\t}\n\n\t\t\tconst spec = view.value.spec;\n\n\t\t\t// Resolve the store: external (controlled) or internal per-view atom\n\t\t\tlet store: StateStore;\n\t\t\tif (props.store) {\n\t\t\t\tstore = props.store;\n\t\t\t} else {\n\t\t\t\tif (internalStore === null || lastView !== view.value) {\n\t\t\t\t\tconst initialState = (spec.state as Record<string, unknown>) ?? {};\n\t\t\t\t\tinternalStore = xstateStoreStateStore({ atom: createAtom(initialState) });\n\t\t\t\t\tlastView = view.value;\n\t\t\t\t\tstoreKey++;\n\t\t\t\t}\n\t\t\t\tstore = internalStore;\n\t\t\t}\n\n\t\t\t// PlayRendererInner renders inside StateProvider so useStateStore() works\n\t\t\treturn h(StateProvider, { store, key: storeKey }, () =>\n\t\t\t\th(PlayRendererInner, { registryResult: rawRegistryResult, spec }),\n\t\t\t);\n\t\t};\n\t},\n});\n</script>\n"],"mappings":";;;;;;;AA0CA,IAAM,IAAoB,EAAgB;CACzC,MAAM;CACN,OAAO;EACN,gBAAgB;GACf,MAAM;GACN,UAAU;GACV;EACD,MAAM;GACL,MAAM;GACN,SAAS;GACT;EACD;CACD,MAAM,GAAO;AACZ,eAAa;GACZ,IAAM,EAAE,WAAQ,mBAAgB,GAAe,EAEzC,KAA6B,MAAY;AAE9C,MAAO,EADM,GAAa,CACN,CAAC;MAEhB,IAAW,EAAM,eAAe,eAC/B,SACA,GAAa,CACnB,EACK,IAAc,EAAM,eAAe;AAEzC,UAAO,EAAE,GAAgB,EAAE,aAAU,QACpC,EAAE,GAAoB,EAAE,QACvB,EAAE,GAAU;IAAE,MAAM,EAAM;IAAM,UAAU;IAAa,CAAC,CACxD,CACD;;;CAGH,CAAC,EAEF,IAAe,EAAgB;CAC9B,MAAM;CACN,OAAO;EACN,OAAO;GACN,MAAM;GACN,UAAU;GACV;EACD,gBAAgB;GACf,MAAM;GACN,UAAU;GACV;EACD,OAAO;GACN,MAAM;GACN,SAAS,KAAA;GACT;EACD;CACD,MAAM,GAAO,EAAE,YAAS;EAEvB,IAAM,IAAQ,EAAM,EAAM,MAAM,EAG1B,IAA0C;GAC/C,GAAG,EAAM,EAAM,eAAe;GAC9B,UAAU,EACT,OAAO,YACN,OAAO,QAAQ,EAAM,EAAM,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,OAAO,CACpE,GACA,EAAQ,EAAY,CACpB,CAAC,CACH,CACA;GACD;AAGD,IAAa,EAAmB;EAMhC,IAAM,IAAO,EAHO,EAAM,YAAY,KAAK,CAGO,EAG9C,IAAmC,MACnC,IAAgC,MAChC,IAAW,GAGT,IAAU,EAAY,EAAM,cAAc,MAAa;AAC5D,KAAK,QAAQ;IACZ;AAMF,SAJA,QAAkB;AACjB,MAAS;IACR,QAEW;AAEZ,OAAI,CAAC,EAAK,MACT,QAAO,EAAM,WAAW,EAAM,UAAS,GAAI;GAG5C,IAAM,IAAO,EAAK,MAAM,MAGpB;AAcJ,UAbI,EAAM,QACT,IAAQ,EAAM,UAEV,MAAkB,QAAQ,MAAa,EAAK,WAE/C,IAAgB,EAAsB,EAAE,MAAM,EADxB,EAAK,SAAqC,EAAE,CACG,EAAG,CAAC,EACzE,IAAW,EAAK,OAChB,MAED,IAAQ,IAIF,EAAE,GAAe;IAAE;IAAO,KAAK;IAAU,QAC/C,EAAE,GAAmB;IAAE,gBAAgB;IAAmB;IAAM,CAAC,CACjE;;;CAGH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-registry.d.ts","sourceRoot":"","sources":["../src/define-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,EAAK,KAAK,SAAS,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,EACN,cAAc,IAAI,kBAAkB,EAEpC,KAAK,WAAW,EAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"define-registry.d.ts","sourceRoot":"","sources":["../src/define-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AAEH,OAAO,EAAK,KAAK,SAAS,EAAE,MAAM,KAAK,CAAC;AACxC,OAAO,EACN,cAAc,IAAI,kBAAkB,EAEpC,KAAK,WAAW,EAEhB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AA+BzE,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,OAAO,EAAE,CAAC,SAAS,MAAM,sBAAsB,CAAC,CAAC,CAAC,IACpF,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,GACjB,SAAS,CAAC;AAEb,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,OAAO,IAAI;KAC7C,CAAC,IAAI,MAAM,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,OAAO,IAAI,IAAI,CAC1D,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAC3C,YAAY,CACZ,GAAG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,OAAO,EAC/C,OAAO,EAAE,CAAC,EACV,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC/B,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAa1C"}
|
package/dist/define-registry.js
CHANGED
|
@@ -2,7 +2,7 @@ import { defineRegistry as e } from "./node_modules/@json-render/vue/dist/index.
|
|
|
2
2
|
import { h as t } from "vue";
|
|
3
3
|
//#region src/define-registry.ts
|
|
4
4
|
function n(e) {
|
|
5
|
-
return typeof e
|
|
5
|
+
return typeof e != "object" || !e ? !1 : "__vccOpts" in e ? !0 : typeof e != "function" && ("setup" in e || "render" in e);
|
|
6
6
|
}
|
|
7
7
|
function r(e) {
|
|
8
8
|
return (n) => t(e, n);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-registry.js","names":[],"sources":["../src/define-registry.ts"],"sourcesContent":["/**\n * `defineRegistry` wrapper for @xmachines/play-vue.\n *\n * Wraps `defineRegistry` from `@json-render/vue` with automatic SFC support.\n *\n * ## Vue-specific — React and Solid do not need this\n *\n * In React, `useContext()` works anywhere inside the component call tree.\n * In Solid, `useContext()` works inside reactive computations and component renders.\n * Neither has the strict \"synchronous setup() only\" constraint that Vue's `inject()`\n * imposes — so their `defineRegistry` implementations call `componentFn(ctx)` directly\n * with no wrapping needed.\n *\n * For the DOM renderer, there is no component system at all — just render functions\n * returning `HTMLElement` — so injection context is not applicable.\n *\n * Only Vue requires this adapter.\n *\n * ## Why this wrapper exists\n *\n * `@json-render/vue`'s `defineRegistry` calls each registered component as a plain\n * function: `componentFn(ctx)`. A `.vue` SFC (output of `defineComponent` or\n * `<script setup>`) is an **object**, not a function — calling it throws.\n *\n * More fundamentally, `defineRegistry` calls components inside its own render\n * function (the return value of `setup()`). Vue's `inject()` — and composables built\n * on it: `useStateBinding`, `useStateStore` — only work during synchronous `setup()`\n * execution, not inside render functions. Plain `.ts` `ComponentFn` files cannot\n * call any Vue composable for this reason.\n *\n * This wrapper auto-detects Vue SFCs in the `components` map and wraps them via\n * `h(SFC, ctx)`. The SFC renders as a child component with its own `setup()`,\n * giving full access to composables inside `<script setup>`.\n *\n * ## Usage\n *\n * Import `defineRegistry` from `@xmachines/play-vue` instead of `@json-render/vue`:\n *\n * ```ts\n * import { defineRegistry } from \"@xmachines/play-vue\";\n * // not: import { defineRegistry } from \"@json-render/vue\";\n *\n * import LoginSFC from \"./views/Login.vue\";\n * import DashboardSFC from \"./views/Dashboard.vue\";\n *\n * const { registry } = defineRegistry(catalog, {\n * components: {\n * Login: LoginSFC, // .vue SFC — auto-wrapped\n * Dashboard: DashboardSFC, // .vue SFC — auto-wrapped\n * },\n * });\n * ```\n *\n * Plain `ComponentFn` functions still work and are passed through unchanged.\n * Mixing SFCs and plain functions in the same registry is supported.\n */\n\nimport { h, type Component } from \"vue\";\nimport {\n\tdefineRegistry as defineRegistryBase,\n\ttype ComponentContext,\n\ttype ComponentFn,\n\ttype Components,\n} from \"@json-render/vue\";\nimport type { Catalog, InferCatalogComponents } from \"@json-render/core\";\n\n/**\n * Detect whether a value is a Vue component object (SFC) rather than a plain\n * `ComponentFn` function.\n *\n * Vue SFCs produced by `defineComponent` or `<script setup>` compilation are\n * plain objects (not callable). A `ComponentFn` is always a plain function.\n */\nfunction isVueSFC(value: unknown): value is Component {\n\
|
|
1
|
+
{"version":3,"file":"define-registry.js","names":[],"sources":["../src/define-registry.ts"],"sourcesContent":["/**\n * `defineRegistry` wrapper for @xmachines/play-vue.\n *\n * Wraps `defineRegistry` from `@json-render/vue` with automatic SFC support.\n *\n * ## Vue-specific — React and Solid do not need this\n *\n * In React, `useContext()` works anywhere inside the component call tree.\n * In Solid, `useContext()` works inside reactive computations and component renders.\n * Neither has the strict \"synchronous setup() only\" constraint that Vue's `inject()`\n * imposes — so their `defineRegistry` implementations call `componentFn(ctx)` directly\n * with no wrapping needed.\n *\n * For the DOM renderer, there is no component system at all — just render functions\n * returning `HTMLElement` — so injection context is not applicable.\n *\n * Only Vue requires this adapter.\n *\n * ## Why this wrapper exists\n *\n * `@json-render/vue`'s `defineRegistry` calls each registered component as a plain\n * function: `componentFn(ctx)`. A `.vue` SFC (output of `defineComponent` or\n * `<script setup>`) is an **object**, not a function — calling it throws.\n *\n * More fundamentally, `defineRegistry` calls components inside its own render\n * function (the return value of `setup()`). Vue's `inject()` — and composables built\n * on it: `useStateBinding`, `useStateStore` — only work during synchronous `setup()`\n * execution, not inside render functions. Plain `.ts` `ComponentFn` files cannot\n * call any Vue composable for this reason.\n *\n * This wrapper auto-detects Vue SFCs in the `components` map and wraps them via\n * `h(SFC, ctx)`. The SFC renders as a child component with its own `setup()`,\n * giving full access to composables inside `<script setup>`.\n *\n * ## Usage\n *\n * Import `defineRegistry` from `@xmachines/play-vue` instead of `@json-render/vue`:\n *\n * ```ts\n * import { defineRegistry } from \"@xmachines/play-vue\";\n * // not: import { defineRegistry } from \"@json-render/vue\";\n *\n * import LoginSFC from \"./views/Login.vue\";\n * import DashboardSFC from \"./views/Dashboard.vue\";\n *\n * const { registry } = defineRegistry(catalog, {\n * components: {\n * Login: LoginSFC, // .vue SFC — auto-wrapped\n * Dashboard: DashboardSFC, // .vue SFC — auto-wrapped\n * },\n * });\n * ```\n *\n * Plain `ComponentFn` functions still work and are passed through unchanged.\n * Mixing SFCs and plain functions in the same registry is supported.\n */\n\nimport { h, type Component } from \"vue\";\nimport {\n\tdefineRegistry as defineRegistryBase,\n\ttype ComponentContext,\n\ttype ComponentFn,\n\ttype Components,\n} from \"@json-render/vue\";\nimport type { Catalog, InferCatalogComponents } from \"@json-render/core\";\n\n/**\n * Detect whether a value is a Vue component object (SFC) rather than a plain\n * `ComponentFn` function.\n *\n * Vue SFCs produced by `defineComponent` or `<script setup>` compilation are\n * plain objects (not callable). A `ComponentFn` is always a plain function.\n */\nfunction isVueSFC(value: unknown): value is Component {\n\tif (typeof value !== \"object\" || value === null) return false;\n\t// __vccOpts is set by vite-plugin-vue / vue-loader on every <script setup> SFC.\n\tif (\"__vccOpts\" in value) return true;\n\t// defineComponent() output has setup or render, but plain POJOs with those\n\t// keys should not be treated as components. Require the value to not be a function\n\t// (ComponentFn is a function, Vue SFCs are objects).\n\treturn typeof value !== \"function\" && (\"setup\" in value || \"render\" in value);\n}\n\n/**\n * Wrap a Vue SFC as a `ComponentFn` by rendering it via `h()`.\n *\n * The SFC receives the full `ComponentContext` as its props and renders in its\n * own child component `setup()`, where Vue composables work correctly.\n */\nfunction wrapSFC<C extends Catalog, K extends keyof InferCatalogComponents<C>>(\n\tcomponent: Component,\n): ComponentFn<C, K> {\n\treturn (ctx: ComponentContext<C, K>) => h(component, ctx);\n}\n\nexport type ComponentEntry<C extends Catalog, K extends keyof InferCatalogComponents<C>> =\n\t| ComponentFn<C, K>\n\t| Component;\n\nexport type ComponentsMap<C extends Catalog> = {\n\t[K in keyof InferCatalogComponents<C>]?: ComponentEntry<C, K>;\n};\n\nexport type DefineRegistryOptions<C extends Catalog> = Omit<\n\tParameters<typeof defineRegistryBase<C>>[1],\n\t\"components\"\n> & {\n\tcomponents?: ComponentsMap<C>;\n};\n\n/**\n * Create a component registry, automatically wrapping `.vue` SFCs so they work\n * correctly with `@json-render/vue`'s rendering pipeline.\n *\n * Drop-in replacement for `defineRegistry` from `@json-render/vue`. Import from\n * `@xmachines/play-vue` to get SFC support for free.\n *\n * @param catalog - The json-render catalog defining component prop shapes.\n * @param options - Registry options. `components` entries may be `.vue` SFCs\n * (objects) or plain `ComponentFn` functions — both are handled automatically.\n */\nexport function defineRegistry<C extends Catalog>(\n\tcatalog: C,\n\toptions: DefineRegistryOptions<C>,\n): ReturnType<typeof defineRegistryBase<C>> {\n\tconst wrappedComponents = {} as Components<C>;\n\n\tfor (const [key, component] of Object.entries(options.components ?? {})) {\n\t\tif (component === undefined) continue;\n\t\tconst k = key as keyof InferCatalogComponents<C>;\n\t\twrappedComponents[k] = isVueSFC(component)\n\t\t\t? wrapSFC(component as Component)\n\t\t\t: (component as ComponentFn<C, typeof k>);\n\t}\n\n\tconst baseOptions = options as Parameters<typeof defineRegistryBase<C>>[1];\n\treturn defineRegistryBase(catalog, { ...baseOptions, components: wrappedComponents });\n}\n"],"mappings":";;;AAyEA,SAAS,EAAS,GAAoC;AAOrD,QANI,OAAO,KAAU,aAAY,IAAuB,KAEpD,eAAe,IAAc,KAI1B,OAAO,KAAU,eAAe,WAAW,KAAS,YAAY;;AASxE,SAAS,EACR,GACoB;AACpB,SAAQ,MAAgC,EAAE,GAAW,EAAI;;AA6B1D,SAAgB,EACf,GACA,GAC2C;CAC3C,IAAM,IAAoB,EAAE;AAE5B,MAAK,IAAM,CAAC,GAAK,MAAc,OAAO,QAAQ,EAAQ,cAAc,EAAE,CAAC,EAAE;AACxE,MAAI,MAAc,KAAA,EAAW;EAC7B,IAAM,IAAI;AACV,IAAkB,KAAK,EAAS,EAAU,GACvC,EAAQ,EAAuB,GAC9B;;AAIL,QAAO,EAAmB,GAAS;EAAE,GADjB;EACiC,YAAY;EAAmB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* to trigger re-renders — signals are the source of truth.
|
|
7
7
|
*
|
|
8
8
|
* Re-exports `defineRegistry` (SFC-aware — auto-wraps `.vue` SFCs via `h()`),
|
|
9
|
-
* `
|
|
9
|
+
* `useBoundProp`, `ComponentFn`, and `ComponentContext` so consumers import
|
|
10
10
|
* everything from `@xmachines/play-vue` rather than `@json-render/vue` directly.
|
|
11
11
|
*
|
|
12
12
|
* @packageDocumentation
|
|
@@ -15,7 +15,7 @@ export { default as PlayRenderer } from "./PlayRenderer.vue";
|
|
|
15
15
|
export { useActor } from "./useActor.js";
|
|
16
16
|
export { defineRegistry } from "./define-registry.js";
|
|
17
17
|
export type { DefineRegistryOptions, ComponentsMap, ComponentEntry } from "./define-registry.js";
|
|
18
|
-
export {
|
|
18
|
+
export { useBoundProp } from "@json-render/vue";
|
|
19
19
|
export type { ComponentFn, ComponentContext } from "@json-render/vue";
|
|
20
20
|
export type { PlayRendererProps } from "./types.js";
|
|
21
21
|
export type { PlayActor } from "./useActor.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEjG,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEjG,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useBoundProp as e } from "./node_modules/@json-render/vue/dist/index.js";
|
|
2
2
|
import { useActor as t } from "./useActor.js";
|
|
3
3
|
import n from "./PlayRenderer.js";
|
|
4
4
|
import { defineRegistry as r } from "./define-registry.js";
|
|
5
|
-
export { n as PlayRenderer, r as defineRegistry, t as useActor, e as
|
|
5
|
+
export { n as PlayRenderer, r as defineRegistry, t as useActor, e as useBoundProp };
|