@xmachines/play-vue 1.1.0 → 2.0.0

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,8 +4,7 @@
4
4
 
5
5
  Part of the [XMachines Play monorepo](../../README.md).
6
6
 
7
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
- [![Version](https://img.shields.io/badge/version-1.1.0-blue)](https://www.npmjs.com/package/@xmachines/play-vue)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Version](https://img.shields.io/badge/version-2.0.0-blue)](https://www.npmjs.com/package/@xmachines/play-vue)
9
8
 
10
9
  ---
11
10
 
@@ -30,7 +29,7 @@ pnpm add @xmachines/play-vue
30
29
  **Peer dependencies** (install alongside):
31
30
 
32
31
  ```bash
33
- pnpm add vue@^3.5.0 xstate@^5.31.0 @xstate/store@^3.17.0 @xmachines/json-render-vue@^0.18.0 @xmachines/json-render-core@^0.18.0 @xmachines/json-render-xstate@^0.18.0
32
+ pnpm add vue@^3.5.0 xstate@^5.31.0 @xstate/store@^3.17.0 @xmachines/json-render-vue@^0.20.0-xm.2 @xmachines/json-render-core@^0.20.0-xm.2 @xmachines/json-render-xstate@^0.20.0-xm.2
34
33
  ```
35
34
 
36
35
  ---
@@ -0,0 +1,15 @@
1
+ import "./actor-provider-context.js";
2
+ import ActorProvider_vue_vue_type_script_lang_default from "./ActorProvider.vue_vue_type_script_lang.js";
3
+ import { useSSRContext } from "vue";
4
+ //#region packages/play-vue/src/ActorProvider.vue
5
+ var _sfc_setup = ActorProvider_vue_vue_type_script_lang_default.setup;
6
+ ActorProvider_vue_vue_type_script_lang_default.setup = (props, ctx) => {
7
+ const ssrContext = useSSRContext();
8
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("packages/play-vue/src/ActorProvider.vue");
9
+ return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
10
+ };
11
+ var ActorProvider_default = ActorProvider_vue_vue_type_script_lang_default;
12
+ //#endregion
13
+ export { ActorProvider_default as default };
14
+
15
+ //# sourceMappingURL=ActorProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActorProvider.js","names":[],"sources":["../src/ActorProvider.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * ActorProvider — escape-hatch primitive for the XMachines Vue render architecture.\n *\n * Owns the full actor lifecycle:\n * - Signal subscription (watchSignal) bridging TC39 Signals to Vue reactivity\n * - Per-view StateStore lifecycle (controlled/uncontrolled)\n * - Handler resolution via ActorProviderInner (must be inside StateProvider)\n * - ViewContextValue provision via ViewKey injection key\n * - ActionProvider + VisibilityProvider wrapping for downstream Renderer\n * - onRenderError injection into registry\n *\n * Library authors who need fine-grained control use this directly.\n * End users should use <PlayUIProvider> instead.\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 {\n\tdefineComponent,\n\tref,\n\tcomputed,\n\ttoRaw,\n\tmarkRaw,\n\tonUnmounted,\n\th,\n\tprovide,\n\tshallowRef,\n\twatch,\n} from \"vue\";\nimport type { PropType } from \"vue\";\nimport { watchSignal } from \"@xmachines/play-signals\";\nimport { attachRenderErrorHandler, createViewStoreLifecycle } from \"@xmachines/play-actor\";\nimport type { AbstractActor, Viewable, PlaySpec } from \"@xmachines/play-actor\";\nimport type { AnyActorLogic } from \"xstate\";\nimport type {\n\tDefineRegistryResult,\n\tSetState,\n\tRenderErrorHandler,\n} from \"@xmachines/json-render-vue\";\n\nimport {\n\tStateProvider,\n\tuseStateStore,\n\tActionProvider,\n\tVisibilityProvider,\n} from \"@xmachines/json-render-vue\";\nimport type { StateStore } from \"@xmachines/json-render-core\";\nimport { createAtom } from \"@xstate/store\";\nimport { xstateStoreStateStore } from \"@xmachines/json-render-xstate\";\nimport { provideActor, type AnyPlayActor } from \"./useActor.js\";\nimport { ViewKey, type ViewContextValue } from \"./actor-provider-context.js\";\nimport type { ActorProviderProps } from \"./types.js\";\n\n// Re-export props type and context accessors for consumers who import from this file\nexport type { ActorProviderProps } from \"./types.js\";\nexport { getPlayViewContext } from \"./actor-provider-context.js\";\nexport type { ViewContextValue } from \"./actor-provider-context.js\";\n\n// ---------------------------------------------------------------------------\n// ActorProviderInner — renders inside StateProvider to call useStateStore()\n// Provides ViewContextValue + ActionProvider + VisibilityProvider for downstream Renderer.\n// ---------------------------------------------------------------------------\n\nconst ActorProviderInner = defineComponent({\n\tname: \"ActorProviderInner\",\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<PlaySpec | null>,\n\t\t\tdefault: null,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<StateStore>,\n\t\t\trequired: true,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\t// Use shallowRef for the view context value to avoid deep reactivity overhead.\n\t\t// The Proxy below allows inject() to always read the latest value.\n\t\tconst viewRef = shallowRef<ViewContextValue | null>(null);\n\n\t\t// Provide the ViewContextValue via Vue's inject/provide system.\n\t\t// Called synchronously in setup() so Vue registers it on the component instance.\n\t\t// Uses Proxy so descendants always receive the latest viewRef.value.\n\t\tprovide(\n\t\t\tViewKey,\n\t\t\tnew Proxy({} as ViewContextValue, {\n\t\t\t\tget(_target, prop: string) {\n\t\t\t\t\treturn viewRef.value?.[prop as keyof ViewContextValue];\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\n\t\t// Call useStateStore() at setup() time (synchronous, before return).\n\t\t// Vue composables that use inject() must be called during setup(), not in a render function.\n\t\tconst stateStore = useStateStore();\n\n\t\t// Build a SetState adapter: handlers factory expects updater-function pattern.\n\t\t// Defined once in setup() — reads stateStore.getSnapshot/update at invocation\n\t\t// time so it always operates on the live store state without needing to be\n\t\t// recreated when stateStore identity changes across renders.\n\t\tconst setStateAdapter: SetState = (updater) => {\n\t\t\tconst prev = stateStore.getSnapshot();\n\t\t\tstateStore.update(updater(prev));\n\t\t};\n\n\t\t// Memoize handlers keyed to registryResult prop identity. The getter functions\n\t\t// are stable closures capturing stateStore from setup(), so they do not\n\t\t// contribute to invalidation. Handlers are only recomputed when the registry\n\t\t// definition itself changes — not on every render triggered by view updates.\n\t\tconst handlers = computed(() =>\n\t\t\tprops.registryResult.handlers(\n\t\t\t\t() => setStateAdapter,\n\t\t\t\t() => stateStore.getSnapshot(),\n\t\t\t),\n\t\t);\n\n\t\treturn () => {\n\t\t\tif (!props.spec) {\n\t\t\t\tviewRef.value = null;\n\t\t\t\treturn slots.default?.() ?? null;\n\t\t\t}\n\n\t\t\tviewRef.value = {\n\t\t\t\tspec: props.spec,\n\t\t\t\thandlers: handlers.value,\n\t\t\t\tregistry: props.registryResult.registry,\n\t\t\t\tstore: props.store,\n\t\t\t};\n\n\t\t\t// Wrap with ActionProvider + VisibilityProvider so PlayRenderer's Renderer works\n\t\t\t// even when ActorProvider is used directly (without PlayUIProvider / JSONUIProvider)\n\t\t\treturn h(ActionProvider, { handlers: handlers.value }, () =>\n\t\t\t\th(VisibilityProvider, {}, () => slots.default?.() ?? null),\n\t\t\t);\n\t\t};\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// ActorProvider — main export\n// ---------------------------------------------------------------------------\n\nexport default defineComponent({\n\tname: \"ActorProvider\",\n\tprops: {\n\t\tactor: {\n\t\t\ttype: Object as PropType<ActorProviderProps[\"actor\"]>,\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\tonRenderError: {\n\t\t\ttype: Function as PropType<RenderErrorHandler>,\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\t// Held in a shallowRef so the provided injection and the signal watcher\n\t\t// can follow `props.actor` when the prop swaps after mount.\n\t\tconst actorRef = shallowRef(toRaw(props.actor as AbstractActor<AnyActorLogic> & Viewable));\n\n\t\t// Unwrap the registryResult and mark components as raw to avoid Vue reactivity overhead\n\t\tconst rawRegistry = Object.fromEntries(\n\t\t\tObject.entries(toRaw(props.registryResult).registry).map(([k, v]) => [\n\t\t\t\tk,\n\t\t\t\tmarkRaw(v as object),\n\t\t\t]),\n\t\t) as DefineRegistryResult[\"registry\"];\n\n\t\t// Inject onRenderError prop into registry (non-enumerable, overrides defineRegistry-level\n\t\t// handler). attachRenderErrorHandler clones — the caller's registry is never mutated.\n\t\t// The clone must be re-markRaw'd: markRaw's non-enumerable flag is not carried by the clone.\n\t\tconst rawRegistryResult: DefineRegistryResult = {\n\t\t\t...toRaw(props.registryResult),\n\t\t\tregistry: markRaw(\n\t\t\t\tprops.onRenderError\n\t\t\t\t\t? attachRenderErrorHandler(rawRegistry, props.onRenderError)\n\t\t\t\t\t: rawRegistry,\n\t\t\t),\n\t\t};\n\n\t\t// Provide the actor to all descendants via Vue's provide/inject mechanism.\n\t\t//\n\t\t// A stable Proxy (same pattern as ActorProviderInner's ViewKey proxy) is\n\t\t// provided instead of the raw actor so the injection tracks the CURRENT\n\t\t// `props.actor`: injectors keep the reference obtained at setup() time,\n\t\t// yet every trap resolves against the latest actor (actorRef.value) after a\n\t\t// prop swap. All relevant traps are forwarded so the proxy behaves like the\n\t\t// underlying actor for reads, writes, membership (`in`), enumeration\n\t\t// (Object.keys / spread), and prototype checks (`instanceof`). Methods are\n\t\t// bound to the current raw actor so `this` (including private fields) works\n\t\t// exactly as with a direct call.\n\t\t//\n\t\t// IMPORTANT: this proxy is NOT identity-equal to `props.actor` — it is a\n\t\t// distinct object, hence a distinct WeakMap key. Identity-keyed consumers —\n\t\t// notably RouterBridgeBase's one-bridge-per-actor guard, which keys a\n\t\t// module-level WeakMap on actor identity — must be handed the `props.actor`\n\t\t// value itself, never this injected proxy.\n\t\t//\n\t\t// Method identity: bound methods are cached per underlying method so repeated\n\t\t// reads return the SAME function (actor.send === actor.send — allocation-free\n\t\t// hot path). A read rebinds only when the underlying method changes; the cache\n\t\t// is CLEARED on actor swap (see the watch handler below) so prototype methods\n\t\t// rebind to the new actor.\n\t\tconst boundMethodCache = new Map<PropertyKey, { source: unknown; bound: unknown }>();\n\t\tprovideActor(\n\t\t\tnew Proxy({} as AnyPlayActor, {\n\t\t\t\tget(_target, prop) {\n\t\t\t\t\tconst current = actorRef.value;\n\t\t\t\t\tconst value = Reflect.get(current, prop, current) as unknown;\n\t\t\t\t\tif (typeof value !== \"function\") return value;\n\t\t\t\t\tconst cached = boundMethodCache.get(prop);\n\t\t\t\t\tif (cached && cached.source === value) return cached.bound;\n\t\t\t\t\tconst bound = (value as (...args: unknown[]) => unknown).bind(current);\n\t\t\t\t\tboundMethodCache.set(prop, { source: value, bound });\n\t\t\t\t\treturn bound;\n\t\t\t\t},\n\t\t\t\thas(_target, prop) {\n\t\t\t\t\treturn prop in actorRef.value;\n\t\t\t\t},\n\t\t\t\tset(_target, prop, value) {\n\t\t\t\t\treturn Reflect.set(actorRef.value, prop, value, actorRef.value);\n\t\t\t\t},\n\t\t\t\tdeleteProperty(_target, prop) {\n\t\t\t\t\treturn Reflect.deleteProperty(actorRef.value, prop);\n\t\t\t\t},\n\t\t\t\townKeys() {\n\t\t\t\t\treturn Reflect.ownKeys(actorRef.value);\n\t\t\t\t},\n\t\t\t\tgetOwnPropertyDescriptor(_target, prop) {\n\t\t\t\t\tconst desc = Reflect.getOwnPropertyDescriptor(actorRef.value, prop);\n\t\t\t\t\tif (!desc) return undefined;\n\t\t\t\t\t// Proxy invariant: the proxy target is an empty {}, so every key\n\t\t\t\t\t// reported via ownKeys must resolve to a configurable descriptor here\n\t\t\t\t\t// — otherwise the [[GetOwnProperty]] invariant throws (a non-existent\n\t\t\t\t\t// target property may not be reported as non-configurable). The actor's\n\t\t\t\t\t// own props are runtime-mutable anyway, so reporting configurable:true\n\t\t\t\t\t// is faithful enough for Object.keys / spread enumeration.\n\t\t\t\t\tdesc.configurable = true;\n\t\t\t\t\treturn desc;\n\t\t\t\t},\n\t\t\t\tgetPrototypeOf() {\n\t\t\t\t\treturn Reflect.getPrototypeOf(actorRef.value);\n\t\t\t\t},\n\t\t\t}) as AnyPlayActor,\n\t\t);\n\n\t\t// Seed initial value then subscribe — both synchronous, no scheduler gap.\n\t\t// This mirrors the atomic seed+watch pattern used in Solid (createEffect)\n\t\t// and Svelte ($effect) for cross-framework consistency.\n\t\tconst view = ref<PlaySpec | null>(actorRef.value.currentView.get());\n\n\t\t// Store lifecycle (reseed on viewKey change, refresh /context in place\n\t\t// otherwise, actor-swap reset, guard identity cache) — the shared\n\t\t// coordinator from @xmachines/play-actor; only the reactivity wiring\n\t\t// below is Vue's.\n\t\tconst storeLifecycle = createViewStoreLifecycle((seed) =>\n\t\t\txstateStoreStateStore({ atom: createAtom(seed) }),\n\t\t);\n\t\t// storeKey is a SUBTREE REMOUNT key — it must bump only when the store is\n\t\t// actually reseeded, never on an in-place /context refresh, or every\n\t\t// projection update would wipe the rendered subtree.\n\t\t// (Controlled mode never reseeds, so it never bumps.)\n\t\tlet storeKey = 0;\n\n\t\t// Signal watcher for bridging TC39 Signals to Vue reactivity.\n\t\t// Re-assigned on actor swap so cleanup always releases the live watcher.\n\t\tlet unwatch = watchSignal(actorRef.value.currentView, (nextView) => {\n\t\t\tview.value = nextView;\n\t\t});\n\n\t\t// React to `props.actor` swaps: unsubscribe the OLD actor's currentView,\n\t\t// re-seed the view from the NEW actor synchronously (flush: \"sync\" — no\n\t\t// scheduler gap, matching the mount-time seed+watch pattern above), and\n\t\t// subscribe the new signal. The re-seeded view is a new object identity,\n\t\t// so the internal-store branch below rebuilds the store and bumps\n\t\t// storeKey exactly like a regular view transition.\n\t\twatch(\n\t\t\t() => toRaw(props.actor as AbstractActor<AnyActorLogic> & Viewable),\n\t\t\t(nextActor) => {\n\t\t\t\tif (nextActor === actorRef.value) return;\n\t\t\t\tunwatch();\n\t\t\t\tactorRef.value = nextActor;\n\t\t\t\t// (The store lifecycle resets itself on the actor swap — the kept\n\t\t\t\t// store must not outlive its actor.)\n\t\t\t\t// Invalidate cached bound methods so prototype methods rebind to the\n\t\t\t\t// new actor on the next read (see the injected proxy's get trap).\n\t\t\t\tboundMethodCache.clear();\n\t\t\t\tview.value = nextActor.currentView.get();\n\t\t\t\tunwatch = watchSignal(nextActor.currentView, (nextView) => {\n\t\t\t\t\tview.value = nextView;\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ flush: \"sync\" },\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 or nothing\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;\n\n\t\t\t// Resolve the store (external/controlled or internal per-viewKey) via\n\t\t\t// the shared lifecycle; children get the guarded store — /context is\n\t\t\t// read-only to the spec, and the machinery refreshes through the\n\t\t\t// unguarded reference inside the coordinator.\n\t\t\tconst resolution = storeLifecycle.resolve(actorRef.value, spec, props.store);\n\t\t\tif (resolution.reseeded) storeKey++;\n\t\t\tconst store: StateStore = resolution.guardedStore;\n\n\t\t\t// ActorProviderInner renders inside StateProvider so useStateStore() works\n\t\t\treturn h(StateProvider, { store, key: storeKey }, () =>\n\t\t\t\th(ActorProviderInner, { registryResult: rawRegistryResult, spec, store }, slots),\n\t\t\t);\n\t\t};\n\t},\n});\n</script>\n"],"mappings":""}
@@ -0,0 +1,173 @@
1
+ import { ViewKey } from "./actor-provider-context.js";
2
+ import { provideActor } from "./useActor.js";
3
+ import { computed, defineComponent, h, markRaw, onUnmounted, provide, ref, shallowRef, toRaw, watch } from "vue";
4
+ import { ActionProvider, StateProvider, VisibilityProvider, useStateStore } from "@xmachines/json-render-vue";
5
+ import { watchSignal } from "@xmachines/play-signals";
6
+ import { attachRenderErrorHandler, createViewStoreLifecycle } from "@xmachines/play-actor";
7
+ import { createAtom } from "@xstate/store";
8
+ import { xstateStoreStateStore } from "@xmachines/json-render-xstate";
9
+ //#region packages/play-vue/src/ActorProvider.vue?vue&type=script&lang.ts
10
+ /**
11
+ * ActorProvider — escape-hatch primitive for the XMachines Vue render architecture.
12
+ *
13
+ * Owns the full actor lifecycle:
14
+ * - Signal subscription (watchSignal) bridging TC39 Signals to Vue reactivity
15
+ * - Per-view StateStore lifecycle (controlled/uncontrolled)
16
+ * - Handler resolution via ActorProviderInner (must be inside StateProvider)
17
+ * - ViewContextValue provision via ViewKey injection key
18
+ * - ActionProvider + VisibilityProvider wrapping for downstream Renderer
19
+ * - onRenderError injection into registry
20
+ *
21
+ * Library authors who need fine-grained control use this directly.
22
+ * End users should use <PlayUIProvider> instead.
23
+ *
24
+ * @invariant Actor Authority - Actor decides all state transitions via guards
25
+ * @invariant Passive Infrastructure - Component observes signals, sends events
26
+ * @invariant Signal-Only Reactivity - Business logic state lives in actor signals
27
+ */
28
+ var ActorProviderInner = defineComponent({
29
+ name: "ActorProviderInner",
30
+ props: {
31
+ registryResult: {
32
+ type: Object,
33
+ required: true
34
+ },
35
+ spec: {
36
+ type: Object,
37
+ default: null
38
+ },
39
+ store: {
40
+ type: Object,
41
+ required: true
42
+ }
43
+ },
44
+ setup(props, { slots }) {
45
+ const viewRef = shallowRef(null);
46
+ provide(ViewKey, new Proxy({}, { get(_target, prop) {
47
+ return viewRef.value?.[prop];
48
+ } }));
49
+ const stateStore = useStateStore();
50
+ const setStateAdapter = (updater) => {
51
+ const prev = stateStore.getSnapshot();
52
+ stateStore.update(updater(prev));
53
+ };
54
+ const handlers = computed(() => props.registryResult.handlers(() => setStateAdapter, () => stateStore.getSnapshot()));
55
+ return () => {
56
+ if (!props.spec) {
57
+ viewRef.value = null;
58
+ return slots.default?.() ?? null;
59
+ }
60
+ viewRef.value = {
61
+ spec: props.spec,
62
+ handlers: handlers.value,
63
+ registry: props.registryResult.registry,
64
+ store: props.store
65
+ };
66
+ return h(ActionProvider, { handlers: handlers.value }, () => h(VisibilityProvider, {}, () => slots.default?.() ?? null));
67
+ };
68
+ }
69
+ });
70
+ var ActorProvider_vue_vue_type_script_lang_default = defineComponent({
71
+ name: "ActorProvider",
72
+ props: {
73
+ actor: {
74
+ type: Object,
75
+ required: true
76
+ },
77
+ registryResult: {
78
+ type: Object,
79
+ required: true
80
+ },
81
+ store: {
82
+ type: Object,
83
+ default: void 0
84
+ },
85
+ onRenderError: {
86
+ type: Function,
87
+ default: void 0
88
+ }
89
+ },
90
+ setup(props, { slots }) {
91
+ const actorRef = shallowRef(toRaw(props.actor));
92
+ const rawRegistry = Object.fromEntries(Object.entries(toRaw(props.registryResult).registry).map(([k, v]) => [k, markRaw(v)]));
93
+ const rawRegistryResult = {
94
+ ...toRaw(props.registryResult),
95
+ registry: markRaw(props.onRenderError ? attachRenderErrorHandler(rawRegistry, props.onRenderError) : rawRegistry)
96
+ };
97
+ const boundMethodCache = /* @__PURE__ */ new Map();
98
+ provideActor(new Proxy({}, {
99
+ get(_target, prop) {
100
+ const current = actorRef.value;
101
+ const value = Reflect.get(current, prop, current);
102
+ if (typeof value !== "function") return value;
103
+ const cached = boundMethodCache.get(prop);
104
+ if (cached && cached.source === value) return cached.bound;
105
+ const bound = value.bind(current);
106
+ boundMethodCache.set(prop, {
107
+ source: value,
108
+ bound
109
+ });
110
+ return bound;
111
+ },
112
+ has(_target, prop) {
113
+ return prop in actorRef.value;
114
+ },
115
+ set(_target, prop, value) {
116
+ return Reflect.set(actorRef.value, prop, value, actorRef.value);
117
+ },
118
+ deleteProperty(_target, prop) {
119
+ return Reflect.deleteProperty(actorRef.value, prop);
120
+ },
121
+ ownKeys() {
122
+ return Reflect.ownKeys(actorRef.value);
123
+ },
124
+ getOwnPropertyDescriptor(_target, prop) {
125
+ const desc = Reflect.getOwnPropertyDescriptor(actorRef.value, prop);
126
+ if (!desc) return void 0;
127
+ desc.configurable = true;
128
+ return desc;
129
+ },
130
+ getPrototypeOf() {
131
+ return Reflect.getPrototypeOf(actorRef.value);
132
+ }
133
+ }));
134
+ const view = ref(actorRef.value.currentView.get());
135
+ const storeLifecycle = createViewStoreLifecycle((seed) => xstateStoreStateStore({ atom: createAtom(seed) }));
136
+ let storeKey = 0;
137
+ let unwatch = watchSignal(actorRef.value.currentView, (nextView) => {
138
+ view.value = nextView;
139
+ });
140
+ watch(() => toRaw(props.actor), (nextActor) => {
141
+ if (nextActor === actorRef.value) return;
142
+ unwatch();
143
+ actorRef.value = nextActor;
144
+ boundMethodCache.clear();
145
+ view.value = nextActor.currentView.get();
146
+ unwatch = watchSignal(nextActor.currentView, (nextView) => {
147
+ view.value = nextView;
148
+ });
149
+ }, { flush: "sync" });
150
+ onUnmounted(() => {
151
+ unwatch();
152
+ });
153
+ return () => {
154
+ if (!view.value) return slots.fallback ? slots.fallback() : null;
155
+ const spec = view.value;
156
+ const resolution = storeLifecycle.resolve(actorRef.value, spec, props.store);
157
+ if (resolution.reseeded) storeKey++;
158
+ const store = resolution.guardedStore;
159
+ return h(StateProvider, {
160
+ store,
161
+ key: storeKey
162
+ }, () => h(ActorProviderInner, {
163
+ registryResult: rawRegistryResult,
164
+ spec,
165
+ store
166
+ }, slots));
167
+ };
168
+ }
169
+ });
170
+ //#endregion
171
+ export { ActorProvider_vue_vue_type_script_lang_default as default };
172
+
173
+ //# sourceMappingURL=ActorProvider.vue_vue_type_script_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActorProvider.vue_vue_type_script_lang.js","names":[],"sources":["../src/ActorProvider.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * ActorProvider — escape-hatch primitive for the XMachines Vue render architecture.\n *\n * Owns the full actor lifecycle:\n * - Signal subscription (watchSignal) bridging TC39 Signals to Vue reactivity\n * - Per-view StateStore lifecycle (controlled/uncontrolled)\n * - Handler resolution via ActorProviderInner (must be inside StateProvider)\n * - ViewContextValue provision via ViewKey injection key\n * - ActionProvider + VisibilityProvider wrapping for downstream Renderer\n * - onRenderError injection into registry\n *\n * Library authors who need fine-grained control use this directly.\n * End users should use <PlayUIProvider> instead.\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 {\n\tdefineComponent,\n\tref,\n\tcomputed,\n\ttoRaw,\n\tmarkRaw,\n\tonUnmounted,\n\th,\n\tprovide,\n\tshallowRef,\n\twatch,\n} from \"vue\";\nimport type { PropType } from \"vue\";\nimport { watchSignal } from \"@xmachines/play-signals\";\nimport { attachRenderErrorHandler, createViewStoreLifecycle } from \"@xmachines/play-actor\";\nimport type { AbstractActor, Viewable, PlaySpec } from \"@xmachines/play-actor\";\nimport type { AnyActorLogic } from \"xstate\";\nimport type {\n\tDefineRegistryResult,\n\tSetState,\n\tRenderErrorHandler,\n} from \"@xmachines/json-render-vue\";\n\nimport {\n\tStateProvider,\n\tuseStateStore,\n\tActionProvider,\n\tVisibilityProvider,\n} from \"@xmachines/json-render-vue\";\nimport type { StateStore } from \"@xmachines/json-render-core\";\nimport { createAtom } from \"@xstate/store\";\nimport { xstateStoreStateStore } from \"@xmachines/json-render-xstate\";\nimport { provideActor, type AnyPlayActor } from \"./useActor.js\";\nimport { ViewKey, type ViewContextValue } from \"./actor-provider-context.js\";\nimport type { ActorProviderProps } from \"./types.js\";\n\n// Re-export props type and context accessors for consumers who import from this file\nexport type { ActorProviderProps } from \"./types.js\";\nexport { getPlayViewContext } from \"./actor-provider-context.js\";\nexport type { ViewContextValue } from \"./actor-provider-context.js\";\n\n// ---------------------------------------------------------------------------\n// ActorProviderInner — renders inside StateProvider to call useStateStore()\n// Provides ViewContextValue + ActionProvider + VisibilityProvider for downstream Renderer.\n// ---------------------------------------------------------------------------\n\nconst ActorProviderInner = defineComponent({\n\tname: \"ActorProviderInner\",\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<PlaySpec | null>,\n\t\t\tdefault: null,\n\t\t},\n\t\tstore: {\n\t\t\ttype: Object as PropType<StateStore>,\n\t\t\trequired: true,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\t// Use shallowRef for the view context value to avoid deep reactivity overhead.\n\t\t// The Proxy below allows inject() to always read the latest value.\n\t\tconst viewRef = shallowRef<ViewContextValue | null>(null);\n\n\t\t// Provide the ViewContextValue via Vue's inject/provide system.\n\t\t// Called synchronously in setup() so Vue registers it on the component instance.\n\t\t// Uses Proxy so descendants always receive the latest viewRef.value.\n\t\tprovide(\n\t\t\tViewKey,\n\t\t\tnew Proxy({} as ViewContextValue, {\n\t\t\t\tget(_target, prop: string) {\n\t\t\t\t\treturn viewRef.value?.[prop as keyof ViewContextValue];\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\n\t\t// Call useStateStore() at setup() time (synchronous, before return).\n\t\t// Vue composables that use inject() must be called during setup(), not in a render function.\n\t\tconst stateStore = useStateStore();\n\n\t\t// Build a SetState adapter: handlers factory expects updater-function pattern.\n\t\t// Defined once in setup() — reads stateStore.getSnapshot/update at invocation\n\t\t// time so it always operates on the live store state without needing to be\n\t\t// recreated when stateStore identity changes across renders.\n\t\tconst setStateAdapter: SetState = (updater) => {\n\t\t\tconst prev = stateStore.getSnapshot();\n\t\t\tstateStore.update(updater(prev));\n\t\t};\n\n\t\t// Memoize handlers keyed to registryResult prop identity. The getter functions\n\t\t// are stable closures capturing stateStore from setup(), so they do not\n\t\t// contribute to invalidation. Handlers are only recomputed when the registry\n\t\t// definition itself changes — not on every render triggered by view updates.\n\t\tconst handlers = computed(() =>\n\t\t\tprops.registryResult.handlers(\n\t\t\t\t() => setStateAdapter,\n\t\t\t\t() => stateStore.getSnapshot(),\n\t\t\t),\n\t\t);\n\n\t\treturn () => {\n\t\t\tif (!props.spec) {\n\t\t\t\tviewRef.value = null;\n\t\t\t\treturn slots.default?.() ?? null;\n\t\t\t}\n\n\t\t\tviewRef.value = {\n\t\t\t\tspec: props.spec,\n\t\t\t\thandlers: handlers.value,\n\t\t\t\tregistry: props.registryResult.registry,\n\t\t\t\tstore: props.store,\n\t\t\t};\n\n\t\t\t// Wrap with ActionProvider + VisibilityProvider so PlayRenderer's Renderer works\n\t\t\t// even when ActorProvider is used directly (without PlayUIProvider / JSONUIProvider)\n\t\t\treturn h(ActionProvider, { handlers: handlers.value }, () =>\n\t\t\t\th(VisibilityProvider, {}, () => slots.default?.() ?? null),\n\t\t\t);\n\t\t};\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// ActorProvider — main export\n// ---------------------------------------------------------------------------\n\nexport default defineComponent({\n\tname: \"ActorProvider\",\n\tprops: {\n\t\tactor: {\n\t\t\ttype: Object as PropType<ActorProviderProps[\"actor\"]>,\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\tonRenderError: {\n\t\t\ttype: Function as PropType<RenderErrorHandler>,\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\t// Held in a shallowRef so the provided injection and the signal watcher\n\t\t// can follow `props.actor` when the prop swaps after mount.\n\t\tconst actorRef = shallowRef(toRaw(props.actor as AbstractActor<AnyActorLogic> & Viewable));\n\n\t\t// Unwrap the registryResult and mark components as raw to avoid Vue reactivity overhead\n\t\tconst rawRegistry = Object.fromEntries(\n\t\t\tObject.entries(toRaw(props.registryResult).registry).map(([k, v]) => [\n\t\t\t\tk,\n\t\t\t\tmarkRaw(v as object),\n\t\t\t]),\n\t\t) as DefineRegistryResult[\"registry\"];\n\n\t\t// Inject onRenderError prop into registry (non-enumerable, overrides defineRegistry-level\n\t\t// handler). attachRenderErrorHandler clones — the caller's registry is never mutated.\n\t\t// The clone must be re-markRaw'd: markRaw's non-enumerable flag is not carried by the clone.\n\t\tconst rawRegistryResult: DefineRegistryResult = {\n\t\t\t...toRaw(props.registryResult),\n\t\t\tregistry: markRaw(\n\t\t\t\tprops.onRenderError\n\t\t\t\t\t? attachRenderErrorHandler(rawRegistry, props.onRenderError)\n\t\t\t\t\t: rawRegistry,\n\t\t\t),\n\t\t};\n\n\t\t// Provide the actor to all descendants via Vue's provide/inject mechanism.\n\t\t//\n\t\t// A stable Proxy (same pattern as ActorProviderInner's ViewKey proxy) is\n\t\t// provided instead of the raw actor so the injection tracks the CURRENT\n\t\t// `props.actor`: injectors keep the reference obtained at setup() time,\n\t\t// yet every trap resolves against the latest actor (actorRef.value) after a\n\t\t// prop swap. All relevant traps are forwarded so the proxy behaves like the\n\t\t// underlying actor for reads, writes, membership (`in`), enumeration\n\t\t// (Object.keys / spread), and prototype checks (`instanceof`). Methods are\n\t\t// bound to the current raw actor so `this` (including private fields) works\n\t\t// exactly as with a direct call.\n\t\t//\n\t\t// IMPORTANT: this proxy is NOT identity-equal to `props.actor` — it is a\n\t\t// distinct object, hence a distinct WeakMap key. Identity-keyed consumers —\n\t\t// notably RouterBridgeBase's one-bridge-per-actor guard, which keys a\n\t\t// module-level WeakMap on actor identity — must be handed the `props.actor`\n\t\t// value itself, never this injected proxy.\n\t\t//\n\t\t// Method identity: bound methods are cached per underlying method so repeated\n\t\t// reads return the SAME function (actor.send === actor.send — allocation-free\n\t\t// hot path). A read rebinds only when the underlying method changes; the cache\n\t\t// is CLEARED on actor swap (see the watch handler below) so prototype methods\n\t\t// rebind to the new actor.\n\t\tconst boundMethodCache = new Map<PropertyKey, { source: unknown; bound: unknown }>();\n\t\tprovideActor(\n\t\t\tnew Proxy({} as AnyPlayActor, {\n\t\t\t\tget(_target, prop) {\n\t\t\t\t\tconst current = actorRef.value;\n\t\t\t\t\tconst value = Reflect.get(current, prop, current) as unknown;\n\t\t\t\t\tif (typeof value !== \"function\") return value;\n\t\t\t\t\tconst cached = boundMethodCache.get(prop);\n\t\t\t\t\tif (cached && cached.source === value) return cached.bound;\n\t\t\t\t\tconst bound = (value as (...args: unknown[]) => unknown).bind(current);\n\t\t\t\t\tboundMethodCache.set(prop, { source: value, bound });\n\t\t\t\t\treturn bound;\n\t\t\t\t},\n\t\t\t\thas(_target, prop) {\n\t\t\t\t\treturn prop in actorRef.value;\n\t\t\t\t},\n\t\t\t\tset(_target, prop, value) {\n\t\t\t\t\treturn Reflect.set(actorRef.value, prop, value, actorRef.value);\n\t\t\t\t},\n\t\t\t\tdeleteProperty(_target, prop) {\n\t\t\t\t\treturn Reflect.deleteProperty(actorRef.value, prop);\n\t\t\t\t},\n\t\t\t\townKeys() {\n\t\t\t\t\treturn Reflect.ownKeys(actorRef.value);\n\t\t\t\t},\n\t\t\t\tgetOwnPropertyDescriptor(_target, prop) {\n\t\t\t\t\tconst desc = Reflect.getOwnPropertyDescriptor(actorRef.value, prop);\n\t\t\t\t\tif (!desc) return undefined;\n\t\t\t\t\t// Proxy invariant: the proxy target is an empty {}, so every key\n\t\t\t\t\t// reported via ownKeys must resolve to a configurable descriptor here\n\t\t\t\t\t// — otherwise the [[GetOwnProperty]] invariant throws (a non-existent\n\t\t\t\t\t// target property may not be reported as non-configurable). The actor's\n\t\t\t\t\t// own props are runtime-mutable anyway, so reporting configurable:true\n\t\t\t\t\t// is faithful enough for Object.keys / spread enumeration.\n\t\t\t\t\tdesc.configurable = true;\n\t\t\t\t\treturn desc;\n\t\t\t\t},\n\t\t\t\tgetPrototypeOf() {\n\t\t\t\t\treturn Reflect.getPrototypeOf(actorRef.value);\n\t\t\t\t},\n\t\t\t}) as AnyPlayActor,\n\t\t);\n\n\t\t// Seed initial value then subscribe — both synchronous, no scheduler gap.\n\t\t// This mirrors the atomic seed+watch pattern used in Solid (createEffect)\n\t\t// and Svelte ($effect) for cross-framework consistency.\n\t\tconst view = ref<PlaySpec | null>(actorRef.value.currentView.get());\n\n\t\t// Store lifecycle (reseed on viewKey change, refresh /context in place\n\t\t// otherwise, actor-swap reset, guard identity cache) — the shared\n\t\t// coordinator from @xmachines/play-actor; only the reactivity wiring\n\t\t// below is Vue's.\n\t\tconst storeLifecycle = createViewStoreLifecycle((seed) =>\n\t\t\txstateStoreStateStore({ atom: createAtom(seed) }),\n\t\t);\n\t\t// storeKey is a SUBTREE REMOUNT key — it must bump only when the store is\n\t\t// actually reseeded, never on an in-place /context refresh, or every\n\t\t// projection update would wipe the rendered subtree.\n\t\t// (Controlled mode never reseeds, so it never bumps.)\n\t\tlet storeKey = 0;\n\n\t\t// Signal watcher for bridging TC39 Signals to Vue reactivity.\n\t\t// Re-assigned on actor swap so cleanup always releases the live watcher.\n\t\tlet unwatch = watchSignal(actorRef.value.currentView, (nextView) => {\n\t\t\tview.value = nextView;\n\t\t});\n\n\t\t// React to `props.actor` swaps: unsubscribe the OLD actor's currentView,\n\t\t// re-seed the view from the NEW actor synchronously (flush: \"sync\" — no\n\t\t// scheduler gap, matching the mount-time seed+watch pattern above), and\n\t\t// subscribe the new signal. The re-seeded view is a new object identity,\n\t\t// so the internal-store branch below rebuilds the store and bumps\n\t\t// storeKey exactly like a regular view transition.\n\t\twatch(\n\t\t\t() => toRaw(props.actor as AbstractActor<AnyActorLogic> & Viewable),\n\t\t\t(nextActor) => {\n\t\t\t\tif (nextActor === actorRef.value) return;\n\t\t\t\tunwatch();\n\t\t\t\tactorRef.value = nextActor;\n\t\t\t\t// (The store lifecycle resets itself on the actor swap — the kept\n\t\t\t\t// store must not outlive its actor.)\n\t\t\t\t// Invalidate cached bound methods so prototype methods rebind to the\n\t\t\t\t// new actor on the next read (see the injected proxy's get trap).\n\t\t\t\tboundMethodCache.clear();\n\t\t\t\tview.value = nextActor.currentView.get();\n\t\t\t\tunwatch = watchSignal(nextActor.currentView, (nextView) => {\n\t\t\t\t\tview.value = nextView;\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ flush: \"sync\" },\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 or nothing\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;\n\n\t\t\t// Resolve the store (external/controlled or internal per-viewKey) via\n\t\t\t// the shared lifecycle; children get the guarded store — /context is\n\t\t\t// read-only to the spec, and the machinery refreshes through the\n\t\t\t// unguarded reference inside the coordinator.\n\t\t\tconst resolution = storeLifecycle.resolve(actorRef.value, spec, props.store);\n\t\t\tif (resolution.reseeded) storeKey++;\n\t\t\tconst store: StateStore = resolution.guardedStore;\n\n\t\t\t// ActorProviderInner renders inside StateProvider so useStateStore() works\n\t\t\treturn h(StateProvider, { store, key: storeKey }, () =>\n\t\t\t\th(ActorProviderInner, { registryResult: rawRegistryResult, spec, store }, slots),\n\t\t\t);\n\t\t};\n\t},\n});\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,IAAM,qBAAqB,gBAAgB;CAC1C,MAAM;CACN,OAAO;EACN,gBAAgB;GACf,MAAM;GACN,UAAU;EACX;EACA,MAAM;GACL,MAAM;GACN,SAAS;EACV;EACA,OAAO;GACN,MAAM;GACN,UAAU;EACX;CACD;CACA,MAAM,OAAO,EAAE,SAAS;EAGvB,MAAM,UAAU,WAAoC,IAAI;EAKxD,QACC,SACA,IAAI,MAAM,CAAC,GAAuB,EACjC,IAAI,SAAS,MAAc;GAC1B,OAAO,QAAQ,QAAQ;EACxB,EACD,CAAC,CACF;EAIA,MAAM,aAAa,cAAc;EAMjC,MAAM,mBAA6B,YAAY;GAC9C,MAAM,OAAO,WAAW,YAAY;GACpC,WAAW,OAAO,QAAQ,IAAI,CAAC;EAChC;EAMA,MAAM,WAAW,eAChB,MAAM,eAAe,eACd,uBACA,WAAW,YAAY,CAC9B,CACD;EAEA,aAAa;GACZ,IAAI,CAAC,MAAM,MAAM;IAChB,QAAQ,QAAQ;IAChB,OAAO,MAAM,UAAU,KAAK;GAC7B;GAEA,QAAQ,QAAQ;IACf,MAAM,MAAM;IACZ,UAAU,SAAS;IACnB,UAAU,MAAM,eAAe;IAC/B,OAAO,MAAM;GACd;GAIA,OAAO,EAAE,gBAAgB,EAAE,UAAU,SAAS,MAAM,SACnD,EAAE,oBAAoB,CAAC,SAAS,MAAM,UAAU,KAAK,IAAI,CAC1D;EACD;CACD;AACD,CAAC;AAMD,IAAA,iDAAe,gBAAgB;CAC9B,MAAM;CACN,OAAO;EACN,OAAO;GACN,MAAM;GACN,UAAU;EACX;EACA,gBAAgB;GACf,MAAM;GACN,UAAU;EACX;EACA,OAAO;GACN,MAAM;GACN,SAAS,KAAA;EACV;EACA,eAAe;GACd,MAAM;GACN,SAAS,KAAA;EACV;CACD;CACA,MAAM,OAAO,EAAE,SAAS;EAIvB,MAAM,WAAW,WAAW,MAAM,MAAM,KAAgD,CAAC;EAGzF,MAAM,cAAc,OAAO,YAC1B,OAAO,QAAQ,MAAM,MAAM,cAAc,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CACpE,GACA,QAAQ,CAAW,CACpB,CAAC,CACF;EAKA,MAAM,oBAA0C;GAC/C,GAAG,MAAM,MAAM,cAAc;GAC7B,UAAU,QACT,MAAM,gBACH,yBAAyB,aAAa,MAAM,aAAa,IACzD,WACJ;EACD;EAyBA,MAAM,mCAAmB,IAAI,IAAsD;EACnF,aACC,IAAI,MAAM,CAAC,GAAmB;GAC7B,IAAI,SAAS,MAAM;IAClB,MAAM,UAAU,SAAS;IACzB,MAAM,QAAQ,QAAQ,IAAI,SAAS,MAAM,OAAO;IAChD,IAAI,OAAO,UAAU,YAAY,OAAO;IACxC,MAAM,SAAS,iBAAiB,IAAI,IAAI;IACxC,IAAI,UAAU,OAAO,WAAW,OAAO,OAAO,OAAO;IACrD,MAAM,QAAS,MAA0C,KAAK,OAAO;IACrE,iBAAiB,IAAI,MAAM;KAAE,QAAQ;KAAO;IAAM,CAAC;IACnD,OAAO;GACR;GACA,IAAI,SAAS,MAAM;IAClB,OAAO,QAAQ,SAAS;GACzB;GACA,IAAI,SAAS,MAAM,OAAO;IACzB,OAAO,QAAQ,IAAI,SAAS,OAAO,MAAM,OAAO,SAAS,KAAK;GAC/D;GACA,eAAe,SAAS,MAAM;IAC7B,OAAO,QAAQ,eAAe,SAAS,OAAO,IAAI;GACnD;GACA,UAAU;IACT,OAAO,QAAQ,QAAQ,SAAS,KAAK;GACtC;GACA,yBAAyB,SAAS,MAAM;IACvC,MAAM,OAAO,QAAQ,yBAAyB,SAAS,OAAO,IAAI;IAClE,IAAI,CAAC,MAAM,OAAO,KAAA;IAOlB,KAAK,eAAe;IACpB,OAAO;GACR;GACA,iBAAiB;IAChB,OAAO,QAAQ,eAAe,SAAS,KAAK;GAC7C;EACD,CAAC,CACF;EAKA,MAAM,OAAO,IAAqB,SAAS,MAAM,YAAY,IAAI,CAAC;EAMlE,MAAM,iBAAiB,0BAA0B,SAChD,sBAAsB,EAAE,MAAM,WAAW,IAAI,EAAE,CAAC,CACjD;EAKA,IAAI,WAAW;EAIf,IAAI,UAAU,YAAY,SAAS,MAAM,cAAc,aAAa;GACnE,KAAK,QAAQ;EACd,CAAC;EAQD,YACO,MAAM,MAAM,KAAgD,IACjE,cAAc;GACd,IAAI,cAAc,SAAS,OAAO;GAClC,QAAQ;GACR,SAAS,QAAQ;GAKjB,iBAAiB,MAAM;GACvB,KAAK,QAAQ,UAAU,YAAY,IAAI;GACvC,UAAU,YAAY,UAAU,cAAc,aAAa;IAC1D,KAAK,QAAQ;GACd,CAAC;EACF,GACA,EAAE,OAAO,OAAO,CACjB;EAEA,kBAAkB;GACjB,QAAQ;EACT,CAAC;EAED,aAAa;GAEZ,IAAI,CAAC,KAAK,OACT,OAAO,MAAM,WAAW,MAAM,SAAS,IAAI;GAG5C,MAAM,OAAO,KAAK;GAMlB,MAAM,aAAa,eAAe,QAAQ,SAAS,OAAO,MAAM,MAAM,KAAK;GAC3E,IAAI,WAAW,UAAU;GACzB,MAAM,QAAoB,WAAW;GAGrC,OAAO,EAAE,eAAe;IAAE;IAAO,KAAK;GAAS,SAC9C,EAAE,oBAAoB;IAAE,gBAAgB;IAAmB;IAAM;GAAM,GAAG,KAAK,CAChF;EACD;CACD;AACD,CAAC"}
@@ -0,0 +1,14 @@
1
+ import PlayRenderer_vue_vue_type_script_lang_default from "./PlayRenderer.vue_vue_type_script_lang.js";
2
+ import { useSSRContext } from "vue";
3
+ //#region packages/play-vue/src/PlayRenderer.vue
4
+ var _sfc_setup = PlayRenderer_vue_vue_type_script_lang_default.setup;
5
+ PlayRenderer_vue_vue_type_script_lang_default.setup = (props, ctx) => {
6
+ const ssrContext = useSSRContext();
7
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("packages/play-vue/src/PlayRenderer.vue");
8
+ return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
9
+ };
10
+ var PlayRenderer_default = PlayRenderer_vue_vue_type_script_lang_default;
11
+ //#endregion
12
+ export { PlayRenderer_default as default };
13
+
14
+ //# sourceMappingURL=PlayRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlayRenderer.js","names":[],"sources":["../src/PlayRenderer.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayRenderer — zero-prop leaf component for the XMachines Vue render architecture.\n *\n * Reads the current view context from the nearest ActorProvider (or PlayUIProvider)\n * and renders <Renderer spec={view.spec} registry={view.registry} />.\n *\n * Must be used inside <ActorProvider> or <PlayUIProvider>.\n *\n * @example\n * ```ts\n * <PlayUIProvider :actor=\"actor\" :registryResult=\"registryResult\">\n * <PlayRenderer />\n * </PlayUIProvider>\n * ```\n *\n * @invariant Passive Infrastructure - Component observes context, never decides\n */\n\nimport { defineComponent, h } from \"vue\";\nimport { Renderer } from \"@xmachines/json-render-vue\";\nimport { getPlayViewContext } from \"./actor-provider-context.js\";\n\nexport default defineComponent({\n\tname: \"PlayRenderer\",\n\tsetup() {\n\t\t// Call inject at setup() time — valid Vue composition API.\n\t\t// getPlayViewContext() uses inject() which must run synchronously during setup().\n\t\t// The Proxy returned by ActorProviderInner ensures view.spec and view.registry\n\t\t// always reflect the latest values when accessed during the render function.\n\t\tconst view = getPlayViewContext();\n\t\treturn () => {\n\t\t\treturn h(Renderer, { spec: view.spec, registry: view.registry });\n\t\t};\n\t},\n});\n</script>\n"],"mappings":""}
@@ -0,0 +1,37 @@
1
+ import { getPlayViewContext } from "./actor-provider-context.js";
2
+ import { defineComponent, h } from "vue";
3
+ import { Renderer } from "@xmachines/json-render-vue";
4
+ //#region packages/play-vue/src/PlayRenderer.vue?vue&type=script&lang.ts
5
+ /**
6
+ * PlayRenderer — zero-prop leaf component for the XMachines Vue render architecture.
7
+ *
8
+ * Reads the current view context from the nearest ActorProvider (or PlayUIProvider)
9
+ * and renders <Renderer spec={view.spec} registry={view.registry} />.
10
+ *
11
+ * Must be used inside <ActorProvider> or <PlayUIProvider>.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * <PlayUIProvider :actor="actor" :registryResult="registryResult">
16
+ * <PlayRenderer />
17
+ * </PlayUIProvider>
18
+ * ```
19
+ *
20
+ * @invariant Passive Infrastructure - Component observes context, never decides
21
+ */
22
+ var PlayRenderer_vue_vue_type_script_lang_default = defineComponent({
23
+ name: "PlayRenderer",
24
+ setup() {
25
+ const view = getPlayViewContext();
26
+ return () => {
27
+ return h(Renderer, {
28
+ spec: view.spec,
29
+ registry: view.registry
30
+ });
31
+ };
32
+ }
33
+ });
34
+ //#endregion
35
+ export { PlayRenderer_vue_vue_type_script_lang_default as default };
36
+
37
+ //# sourceMappingURL=PlayRenderer.vue_vue_type_script_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlayRenderer.vue_vue_type_script_lang.js","names":[],"sources":["../src/PlayRenderer.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayRenderer — zero-prop leaf component for the XMachines Vue render architecture.\n *\n * Reads the current view context from the nearest ActorProvider (or PlayUIProvider)\n * and renders <Renderer spec={view.spec} registry={view.registry} />.\n *\n * Must be used inside <ActorProvider> or <PlayUIProvider>.\n *\n * @example\n * ```ts\n * <PlayUIProvider :actor=\"actor\" :registryResult=\"registryResult\">\n * <PlayRenderer />\n * </PlayUIProvider>\n * ```\n *\n * @invariant Passive Infrastructure - Component observes context, never decides\n */\n\nimport { defineComponent, h } from \"vue\";\nimport { Renderer } from \"@xmachines/json-render-vue\";\nimport { getPlayViewContext } from \"./actor-provider-context.js\";\n\nexport default defineComponent({\n\tname: \"PlayRenderer\",\n\tsetup() {\n\t\t// Call inject at setup() time — valid Vue composition API.\n\t\t// getPlayViewContext() uses inject() which must run synchronously during setup().\n\t\t// The Proxy returned by ActorProviderInner ensures view.spec and view.registry\n\t\t// always reflect the latest values when accessed during the render function.\n\t\tconst view = getPlayViewContext();\n\t\treturn () => {\n\t\t\treturn h(Renderer, { spec: view.spec, registry: view.registry });\n\t\t};\n\t},\n});\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAuBA,IAAA,gDAAe,gBAAgB;CAC9B,MAAM;CACN,QAAQ;EAKP,MAAM,OAAO,mBAAmB;EAChC,aAAa;GACZ,OAAO,EAAE,UAAU;IAAE,MAAM,KAAK;IAAM,UAAU,KAAK;GAAS,CAAC;EAChE;CACD;AACD,CAAC"}
@@ -0,0 +1,14 @@
1
+ import PlayUIProvider_vue_vue_type_script_lang_default from "./PlayUIProvider.vue_vue_type_script_lang.js";
2
+ import { useSSRContext } from "vue";
3
+ //#region packages/play-vue/src/PlayUIProvider.vue
4
+ var _sfc_setup = PlayUIProvider_vue_vue_type_script_lang_default.setup;
5
+ PlayUIProvider_vue_vue_type_script_lang_default.setup = (props, ctx) => {
6
+ const ssrContext = useSSRContext();
7
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("packages/play-vue/src/PlayUIProvider.vue");
8
+ return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
9
+ };
10
+ var PlayUIProvider_default = PlayUIProvider_vue_vue_type_script_lang_default;
11
+ //#endregion
12
+ export { PlayUIProvider_default as default };
13
+
14
+ //# sourceMappingURL=PlayUIProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlayUIProvider.js","names":[],"sources":["../src/PlayUIProvider.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayUIProvider — batteries-included composite provider for actor-driven UI rendering.\n *\n * Wraps ActorProvider + JSONUIProvider (from @xmachines/json-render-vue) to provide a single\n * entry point for all actor lifecycle and UI rendering concerns.\n *\n * Standard usage:\n * ```ts\n * <PlayUIProvider :actor=\"actor\" :registryResult=\"registryResult\">\n * <PlayRenderer />\n * </PlayUIProvider>\n * ```\n *\n * For custom provider composition (escape hatch), use <ActorProvider> directly.\n *\n * @packageDocumentation\n */\n\nimport { defineComponent, h } from \"vue\";\nimport type { PropType } from \"vue\";\nimport { JSONUIProvider } from \"@xmachines/json-render-vue\";\nimport type { DefineRegistryResult, RenderErrorHandler } from \"@xmachines/json-render-vue\";\n\nimport type { StateStore } from \"@xmachines/json-render-core\";\nimport type { AbstractActor, Viewable } from \"@xmachines/play-actor\";\nimport type { AnyActorLogic } from \"xstate\";\nimport ActorProvider from \"./ActorProvider.vue\";\nimport { getPlayViewContext } from \"./actor-provider-context.js\";\nimport type { PlayUIProviderProps } from \"./types.js\";\n\n// Re-export props type for consumers who import from this file\nexport type { PlayUIProviderProps } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// JSONUIBridge — inner component inside ActorProvider's tree\n// Reads ViewContextValue via getPlayViewContext() and passes handlers + registry\n// to JSONUIProvider so both ActorProvider and JSONUIProvider share the same state.\n// ---------------------------------------------------------------------------\n\nconst JSONUIBridge = defineComponent({\n\tname: \"JSONUIBridge\",\n\tprops: {\n\t\tnavigate: {\n\t\t\ttype: Function as PropType<(path: string) => void>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tvalidationFunctions: {\n\t\t\ttype: Object as PropType<\n\t\t\t\tRecord<string, (value: unknown, args?: Record<string, unknown>) => boolean>\n\t\t\t>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfunctions: {\n\t\t\ttype: Object as PropType<\n\t\t\t\tRecord<\n\t\t\t\t\tstring,\n\t\t\t\t\t(args?: Record<string, unknown>, state?: Record<string, unknown>) => unknown\n\t\t\t\t>\n\t\t\t>,\n\t\t\tdefault: undefined,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\treturn () => {\n\t\t\tconst view = getPlayViewContext();\n\t\t\treturn h(\n\t\t\t\tJSONUIProvider,\n\t\t\t\t{\n\t\t\t\t\tregistry: view.registry,\n\t\t\t\t\thandlers: view.handlers,\n\t\t\t\t\tstore: view.store,\n\t\t\t\t\t...(props.navigate ? { navigate: props.navigate } : {}),\n\t\t\t\t\t...(props.validationFunctions\n\t\t\t\t\t\t? { validationFunctions: props.validationFunctions }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(props.functions ? { functions: props.functions } : {}),\n\t\t\t\t},\n\t\t\t\tslots,\n\t\t\t);\n\t\t};\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// PlayUIProvider — main export\n// ---------------------------------------------------------------------------\n\nexport default defineComponent({\n\tname: \"PlayUIProvider\",\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\tonRenderError: {\n\t\t\ttype: Function as PropType<RenderErrorHandler>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tnavigate: {\n\t\t\ttype: Function as PropType<PlayUIProviderProps[\"navigate\"]>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tvalidationFunctions: {\n\t\t\ttype: Object as PropType<PlayUIProviderProps[\"validationFunctions\"]>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfunctions: {\n\t\t\ttype: Object as PropType<PlayUIProviderProps[\"functions\"]>,\n\t\t\tdefault: undefined,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\treturn () =>\n\t\t\th(\n\t\t\t\tActorProvider,\n\t\t\t\t{\n\t\t\t\t\tactor: props.actor,\n\t\t\t\t\tregistryResult: props.registryResult,\n\t\t\t\t\t...(props.store ? { store: props.store } : {}),\n\t\t\t\t\t...(props.onRenderError ? { onRenderError: props.onRenderError } : {}),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdefault: () =>\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\tJSONUIBridge,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t...(props.navigate ? { navigate: props.navigate } : {}),\n\t\t\t\t\t\t\t\t...(props.validationFunctions\n\t\t\t\t\t\t\t\t\t? { validationFunctions: props.validationFunctions }\n\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t\t...(props.functions ? { functions: props.functions } : {}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tslots,\n\t\t\t\t\t\t),\n\t\t\t\t\tfallback: slots.fallback,\n\t\t\t\t},\n\t\t\t);\n\t},\n});\n</script>\n"],"mappings":""}
@@ -0,0 +1,104 @@
1
+ import { getPlayViewContext } from "./actor-provider-context.js";
2
+ import ActorProvider_default from "./ActorProvider.js";
3
+ import { defineComponent, h } from "vue";
4
+ import { JSONUIProvider } from "@xmachines/json-render-vue";
5
+ //#region packages/play-vue/src/PlayUIProvider.vue?vue&type=script&lang.ts
6
+ /**
7
+ * PlayUIProvider — batteries-included composite provider for actor-driven UI rendering.
8
+ *
9
+ * Wraps ActorProvider + JSONUIProvider (from @xmachines/json-render-vue) to provide a single
10
+ * entry point for all actor lifecycle and UI rendering concerns.
11
+ *
12
+ * Standard usage:
13
+ * ```ts
14
+ * <PlayUIProvider :actor="actor" :registryResult="registryResult">
15
+ * <PlayRenderer />
16
+ * </PlayUIProvider>
17
+ * ```
18
+ *
19
+ * For custom provider composition (escape hatch), use <ActorProvider> directly.
20
+ *
21
+ * @packageDocumentation
22
+ */
23
+ var JSONUIBridge = defineComponent({
24
+ name: "JSONUIBridge",
25
+ props: {
26
+ navigate: {
27
+ type: Function,
28
+ default: void 0
29
+ },
30
+ validationFunctions: {
31
+ type: Object,
32
+ default: void 0
33
+ },
34
+ functions: {
35
+ type: Object,
36
+ default: void 0
37
+ }
38
+ },
39
+ setup(props, { slots }) {
40
+ return () => {
41
+ const view = getPlayViewContext();
42
+ return h(JSONUIProvider, {
43
+ registry: view.registry,
44
+ handlers: view.handlers,
45
+ store: view.store,
46
+ ...props.navigate ? { navigate: props.navigate } : {},
47
+ ...props.validationFunctions ? { validationFunctions: props.validationFunctions } : {},
48
+ ...props.functions ? { functions: props.functions } : {}
49
+ }, slots);
50
+ };
51
+ }
52
+ });
53
+ var PlayUIProvider_vue_vue_type_script_lang_default = defineComponent({
54
+ name: "PlayUIProvider",
55
+ props: {
56
+ actor: {
57
+ type: Object,
58
+ required: true
59
+ },
60
+ registryResult: {
61
+ type: Object,
62
+ required: true
63
+ },
64
+ store: {
65
+ type: Object,
66
+ default: void 0
67
+ },
68
+ onRenderError: {
69
+ type: Function,
70
+ default: void 0
71
+ },
72
+ navigate: {
73
+ type: Function,
74
+ default: void 0
75
+ },
76
+ validationFunctions: {
77
+ type: Object,
78
+ default: void 0
79
+ },
80
+ functions: {
81
+ type: Object,
82
+ default: void 0
83
+ }
84
+ },
85
+ setup(props, { slots }) {
86
+ return () => h(ActorProvider_default, {
87
+ actor: props.actor,
88
+ registryResult: props.registryResult,
89
+ ...props.store ? { store: props.store } : {},
90
+ ...props.onRenderError ? { onRenderError: props.onRenderError } : {}
91
+ }, {
92
+ default: () => h(JSONUIBridge, {
93
+ ...props.navigate ? { navigate: props.navigate } : {},
94
+ ...props.validationFunctions ? { validationFunctions: props.validationFunctions } : {},
95
+ ...props.functions ? { functions: props.functions } : {}
96
+ }, slots),
97
+ fallback: slots.fallback
98
+ });
99
+ }
100
+ });
101
+ //#endregion
102
+ export { PlayUIProvider_vue_vue_type_script_lang_default as default };
103
+
104
+ //# sourceMappingURL=PlayUIProvider.vue_vue_type_script_lang.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlayUIProvider.vue_vue_type_script_lang.js","names":[],"sources":["../src/PlayUIProvider.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * PlayUIProvider — batteries-included composite provider for actor-driven UI rendering.\n *\n * Wraps ActorProvider + JSONUIProvider (from @xmachines/json-render-vue) to provide a single\n * entry point for all actor lifecycle and UI rendering concerns.\n *\n * Standard usage:\n * ```ts\n * <PlayUIProvider :actor=\"actor\" :registryResult=\"registryResult\">\n * <PlayRenderer />\n * </PlayUIProvider>\n * ```\n *\n * For custom provider composition (escape hatch), use <ActorProvider> directly.\n *\n * @packageDocumentation\n */\n\nimport { defineComponent, h } from \"vue\";\nimport type { PropType } from \"vue\";\nimport { JSONUIProvider } from \"@xmachines/json-render-vue\";\nimport type { DefineRegistryResult, RenderErrorHandler } from \"@xmachines/json-render-vue\";\n\nimport type { StateStore } from \"@xmachines/json-render-core\";\nimport type { AbstractActor, Viewable } from \"@xmachines/play-actor\";\nimport type { AnyActorLogic } from \"xstate\";\nimport ActorProvider from \"./ActorProvider.vue\";\nimport { getPlayViewContext } from \"./actor-provider-context.js\";\nimport type { PlayUIProviderProps } from \"./types.js\";\n\n// Re-export props type for consumers who import from this file\nexport type { PlayUIProviderProps } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// JSONUIBridge — inner component inside ActorProvider's tree\n// Reads ViewContextValue via getPlayViewContext() and passes handlers + registry\n// to JSONUIProvider so both ActorProvider and JSONUIProvider share the same state.\n// ---------------------------------------------------------------------------\n\nconst JSONUIBridge = defineComponent({\n\tname: \"JSONUIBridge\",\n\tprops: {\n\t\tnavigate: {\n\t\t\ttype: Function as PropType<(path: string) => void>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tvalidationFunctions: {\n\t\t\ttype: Object as PropType<\n\t\t\t\tRecord<string, (value: unknown, args?: Record<string, unknown>) => boolean>\n\t\t\t>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfunctions: {\n\t\t\ttype: Object as PropType<\n\t\t\t\tRecord<\n\t\t\t\t\tstring,\n\t\t\t\t\t(args?: Record<string, unknown>, state?: Record<string, unknown>) => unknown\n\t\t\t\t>\n\t\t\t>,\n\t\t\tdefault: undefined,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\treturn () => {\n\t\t\tconst view = getPlayViewContext();\n\t\t\treturn h(\n\t\t\t\tJSONUIProvider,\n\t\t\t\t{\n\t\t\t\t\tregistry: view.registry,\n\t\t\t\t\thandlers: view.handlers,\n\t\t\t\t\tstore: view.store,\n\t\t\t\t\t...(props.navigate ? { navigate: props.navigate } : {}),\n\t\t\t\t\t...(props.validationFunctions\n\t\t\t\t\t\t? { validationFunctions: props.validationFunctions }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(props.functions ? { functions: props.functions } : {}),\n\t\t\t\t},\n\t\t\t\tslots,\n\t\t\t);\n\t\t};\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// PlayUIProvider — main export\n// ---------------------------------------------------------------------------\n\nexport default defineComponent({\n\tname: \"PlayUIProvider\",\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\tonRenderError: {\n\t\t\ttype: Function as PropType<RenderErrorHandler>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tnavigate: {\n\t\t\ttype: Function as PropType<PlayUIProviderProps[\"navigate\"]>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tvalidationFunctions: {\n\t\t\ttype: Object as PropType<PlayUIProviderProps[\"validationFunctions\"]>,\n\t\t\tdefault: undefined,\n\t\t},\n\t\tfunctions: {\n\t\t\ttype: Object as PropType<PlayUIProviderProps[\"functions\"]>,\n\t\t\tdefault: undefined,\n\t\t},\n\t},\n\tsetup(props, { slots }) {\n\t\treturn () =>\n\t\t\th(\n\t\t\t\tActorProvider,\n\t\t\t\t{\n\t\t\t\t\tactor: props.actor,\n\t\t\t\t\tregistryResult: props.registryResult,\n\t\t\t\t\t...(props.store ? { store: props.store } : {}),\n\t\t\t\t\t...(props.onRenderError ? { onRenderError: props.onRenderError } : {}),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdefault: () =>\n\t\t\t\t\t\th(\n\t\t\t\t\t\t\tJSONUIBridge,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t...(props.navigate ? { navigate: props.navigate } : {}),\n\t\t\t\t\t\t\t\t...(props.validationFunctions\n\t\t\t\t\t\t\t\t\t? { validationFunctions: props.validationFunctions }\n\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t\t...(props.functions ? { functions: props.functions } : {}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tslots,\n\t\t\t\t\t\t),\n\t\t\t\t\tfallback: slots.fallback,\n\t\t\t\t},\n\t\t\t);\n\t},\n});\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwCA,IAAM,eAAe,gBAAgB;CACpC,MAAM;CACN,OAAO;EACN,UAAU;GACT,MAAM;GACN,SAAS,KAAA;EACV;EACA,qBAAqB;GACpB,MAAM;GAGN,SAAS,KAAA;EACV;EACA,WAAW;GACV,MAAM;GAMN,SAAS,KAAA;EACV;CACD;CACA,MAAM,OAAO,EAAE,SAAS;EACvB,aAAa;GACZ,MAAM,OAAO,mBAAmB;GAChC,OAAO,EACN,gBACA;IACC,UAAU,KAAK;IACf,UAAU,KAAK;IACf,OAAO,KAAK;IACZ,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;IACrD,GAAI,MAAM,sBACP,EAAE,qBAAqB,MAAM,oBAAoB,IACjD,CAAC;IACJ,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;GACzD,GACA,KACD;EACD;CACD;AACD,CAAC;AAMD,IAAA,kDAAe,gBAAgB;CAC9B,MAAM;CACN,OAAO;EACN,OAAO;GACN,MAAM;GACN,UAAU;EACX;EACA,gBAAgB;GACf,MAAM;GACN,UAAU;EACX;EACA,OAAO;GACN,MAAM;GACN,SAAS,KAAA;EACV;EACA,eAAe;GACd,MAAM;GACN,SAAS,KAAA;EACV;EACA,UAAU;GACT,MAAM;GACN,SAAS,KAAA;EACV;EACA,qBAAqB;GACpB,MAAM;GACN,SAAS,KAAA;EACV;EACA,WAAW;GACV,MAAM;GACN,SAAS,KAAA;EACV;CACD;CACA,MAAM,OAAO,EAAE,SAAS;EACvB,aACC,EACC,uBACA;GACC,OAAO,MAAM;GACb,gBAAgB,MAAM;GACtB,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;GAC5C,GAAI,MAAM,gBAAgB,EAAE,eAAe,MAAM,cAAc,IAAI,CAAC;EACrE,GACA;GACC,eACC,EACC,cACA;IACC,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;IACrD,GAAI,MAAM,sBACP,EAAE,qBAAqB,MAAM,oBAAoB,IACjD,CAAC;IACJ,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;GACzD,GACA,KACD;GACD,UAAU,MAAM;EACjB,CACD;CACF;AACD,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { inject } from "vue";
2
+ import { assertNonNullable } from "@xmachines/play";
3
+ //#region packages/play-vue/src/actor-provider-context.ts
4
+ /**
5
+ * ViewContextValue and getPlayViewContext — shared context types for Vue provider architecture.
6
+ *
7
+ * Extracted from ActorProvider.vue so TypeScript can re-export these types from index.ts.
8
+ * (The vue-shim.d.ts only declares a default export from *.vue files, so named exports
9
+ * from .vue SFCs are not visible to TypeScript's re-export resolution.)
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ /**
14
+ * Injection key for the ViewContextValue. Exported so ActorProvider.vue can use it
15
+ * as the canonical key without re-declaring.
16
+ *
17
+ * @internal Use getPlayViewContext() as the public API; do not inject ViewKey directly.
18
+ */
19
+ var ViewKey = Symbol("xmachines.view");
20
+ /**
21
+ * Access the current ViewContextValue from inside an ActorProvider tree.
22
+ *
23
+ * @throws {Error} If called outside an <ActorProvider> (or <PlayUIProvider>) tree
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * import { getPlayViewContext } from "@xmachines/play-vue";
28
+ *
29
+ * const view = getPlayViewContext();
30
+ * // view.spec, view.handlers, view.registry
31
+ * ```
32
+ */
33
+ function getPlayViewContext() {
34
+ return assertNonNullable(inject(ViewKey), "ViewKey");
35
+ }
36
+ //#endregion
37
+ export { ViewKey, getPlayViewContext };
38
+
39
+ //# sourceMappingURL=actor-provider-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actor-provider-context.js","names":[],"sources":["../src/actor-provider-context.ts"],"sourcesContent":["/**\n * ViewContextValue and getPlayViewContext — shared context types for Vue provider architecture.\n *\n * Extracted from ActorProvider.vue so TypeScript can re-export these types from index.ts.\n * (The vue-shim.d.ts only declares a default export from *.vue files, so named exports\n * from .vue SFCs are not visible to TypeScript's re-export resolution.)\n *\n * @packageDocumentation\n */\n\nimport { inject } from \"vue\";\nimport type { InjectionKey } from \"vue\";\nimport { assertNonNullable } from \"@xmachines/play\";\nimport type { ComponentRegistry } from \"@xmachines/json-render-vue\";\nimport type { BaseViewContextValue } from \"@xmachines/play-actor\";\n\n/**\n * Context value provided by ActorProvider and consumed by PlayRenderer (zero-prop leaf).\n * Accessible via getPlayViewContext() inside any ActorProvider/PlayUIProvider tree.\n */\nexport interface ViewContextValue extends BaseViewContextValue<ComponentRegistry> {}\n\n/**\n * Injection key for the ViewContextValue. Exported so ActorProvider.vue can use it\n * as the canonical key without re-declaring.\n *\n * @internal Use getPlayViewContext() as the public API; do not inject ViewKey directly.\n */\nexport const ViewKey: InjectionKey<ViewContextValue> = Symbol(\"xmachines.view\");\n\n/**\n * Access the current ViewContextValue from inside an ActorProvider tree.\n *\n * @throws {Error} If called outside an <ActorProvider> (or <PlayUIProvider>) tree\n *\n * @example\n * ```typescript\n * import { getPlayViewContext } from \"@xmachines/play-vue\";\n *\n * const view = getPlayViewContext();\n * // view.spec, view.handlers, view.registry\n * ```\n */\nexport function getPlayViewContext(): ViewContextValue {\n\treturn assertNonNullable(inject(ViewKey), \"ViewKey\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4BA,IAAa,UAA0C,OAAO,gBAAgB;;;;;;;;;;;;;;AAe9E,SAAgB,qBAAuC;CACtD,OAAO,kBAAkB,OAAO,OAAO,GAAG,SAAS;AACpD"}
@@ -0,0 +1,118 @@
1
+ import { h } from "vue";
2
+ import { defineRegistry } from "@xmachines/json-render-vue";
3
+ //#region packages/play-vue/src/define-registry.ts
4
+ /**
5
+ * `defineRegistry` wrapper for @xmachines/play-vue.
6
+ *
7
+ * Wraps `defineRegistry` from `@xmachines/json-render-vue` with automatic SFC support.
8
+ *
9
+ * ## Vue-specific — React and Solid do not need this
10
+ *
11
+ * In React, `useContext()` works anywhere inside the component call tree.
12
+ * In Solid, `useContext()` works inside reactive computations and component renders.
13
+ * Neither has the strict "synchronous setup() only" constraint that Vue's `inject()`
14
+ * imposes — so their `defineRegistry` implementations call `componentFn(ctx)` directly
15
+ * with no wrapping needed.
16
+ *
17
+ * For the DOM renderer, there is no component system at all — just render functions
18
+ * returning `HTMLElement` — so injection context is not applicable.
19
+ *
20
+ * Only Vue requires this adapter.
21
+ *
22
+ * ## Why this wrapper exists
23
+ *
24
+ * `@xmachines/json-render-vue`'s `defineRegistry` calls each registered component as a plain
25
+ * function: `componentFn(ctx)`. A `.vue` SFC (output of `defineComponent` or
26
+ * `<script setup>`) is an **object**, not a function — calling it throws.
27
+ *
28
+ * More fundamentally, `defineRegistry` calls components inside its own render
29
+ * function (the return value of `setup()`). Vue's `inject()` — and composables built
30
+ * on it: `useStateBinding`, `useStateStore` — only work during synchronous `setup()`
31
+ * execution, not inside render functions. Plain `.ts` `ComponentFn` files cannot
32
+ * call any Vue composable for this reason.
33
+ *
34
+ * This wrapper auto-detects Vue SFCs in the `components` map and wraps them via
35
+ * `h(SFC, ctx)`. The SFC renders as a child component with its own `setup()`,
36
+ * giving full access to composables inside `<script setup>`.
37
+ *
38
+ * ## Usage
39
+ *
40
+ * Import `defineRegistry` from `@xmachines/play-vue` instead of `@xmachines/json-render-vue`:
41
+ *
42
+ * ```ts
43
+ * import { defineRegistry } from "@xmachines/play-vue";
44
+ * // not: import { defineRegistry } from "@xmachines/json-render-vue";
45
+ *
46
+ * import LoginSFC from "./views/Login.vue";
47
+ * import DashboardSFC from "./views/Dashboard.vue";
48
+ *
49
+ * const { registry } = defineRegistry(catalog, {
50
+ * components: {
51
+ * Login: LoginSFC, // .vue SFC — auto-wrapped
52
+ * Dashboard: DashboardSFC, // .vue SFC — auto-wrapped
53
+ * },
54
+ * });
55
+ * ```
56
+ *
57
+ * Plain `ComponentFn` functions still work and are passed through unchanged.
58
+ * Mixing SFCs and plain functions in the same registry is supported.
59
+ */
60
+ /**
61
+ * Detect whether a value is a Vue component object (SFC) rather than a plain
62
+ * `ComponentFn` function.
63
+ *
64
+ * Vue SFCs produced by `defineComponent` or `<script setup>` compilation are
65
+ * plain objects (not callable). A `ComponentFn` is always a plain function.
66
+ *
67
+ * Detection strategy (checked in order):
68
+ * 1. `__vccOpts` — set by vite-plugin-vue / vue-loader on every `<script setup>` SFC.
69
+ * 2. `__name` — set by Vite on named SFCs (present alongside `__vccOpts` but also
70
+ * on `defineComponent({ name: "..." })` output without `<script setup>`).
71
+ * 3. `setup` is a function — the `defineComponent({ setup() {} })` signature.
72
+ * 4. `render` is a function — the `defineComponent({ render() {} })` signature.
73
+ *
74
+ * Requiring `setup` / `render` to be **functions** prevents plain POJOs that
75
+ * happen to have a `setup` or `render` key from being misidentified as components.
76
+ */
77
+ function isVueSFC(value) {
78
+ if (typeof value !== "object" || value === null) return false;
79
+ const v = value;
80
+ if ("__vccOpts" in v || "__name" in v) return true;
81
+ return typeof v["setup"] === "function" || typeof v["render"] === "function";
82
+ }
83
+ /**
84
+ * Wrap a Vue SFC as a `ComponentFn` by rendering it via `h()`.
85
+ *
86
+ * The SFC receives the full `ComponentContext` as its props and renders in its
87
+ * own child component `setup()`, where Vue composables work correctly.
88
+ */
89
+ function wrapSFC(component) {
90
+ return (ctx) => h(component, ctx);
91
+ }
92
+ /**
93
+ * Create a component registry, automatically wrapping `.vue` SFCs so they work
94
+ * correctly with `@xmachines/json-render-vue`'s rendering pipeline.
95
+ *
96
+ * Drop-in replacement for `defineRegistry` from `@xmachines/json-render-vue`. Import from
97
+ * `@xmachines/play-vue` to get SFC support for free.
98
+ *
99
+ * @param catalog - The json-render catalog defining component prop shapes.
100
+ * @param options - Registry options. `components` entries may be `.vue` SFCs
101
+ * (objects) or plain `ComponentFn` functions — both are handled automatically.
102
+ */
103
+ function defineRegistry$1(catalog, options) {
104
+ const wrappedComponents = {};
105
+ for (const [key, component] of Object.entries(options.components ?? {})) {
106
+ if (component === void 0) continue;
107
+ const k = key;
108
+ wrappedComponents[k] = isVueSFC(component) ? wrapSFC(component) : component;
109
+ }
110
+ return defineRegistry(catalog, {
111
+ ...options,
112
+ components: wrappedComponents
113
+ });
114
+ }
115
+ //#endregion
116
+ export { defineRegistry$1 as defineRegistry };
117
+
118
+ //# sourceMappingURL=define-registry.js.map
@@ -0,0 +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 `@xmachines/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 * `@xmachines/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 `@xmachines/json-render-vue`:\n *\n * ```ts\n * import { defineRegistry } from \"@xmachines/play-vue\";\n * // not: import { defineRegistry } from \"@xmachines/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 \"@xmachines/json-render-vue\";\nimport type { Catalog, InferCatalogComponents } from \"@xmachines/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 *\n * Detection strategy (checked in order):\n * 1. `__vccOpts` — set by vite-plugin-vue / vue-loader on every `<script setup>` SFC.\n * 2. `__name` — set by Vite on named SFCs (present alongside `__vccOpts` but also\n * on `defineComponent({ name: \"...\" })` output without `<script setup>`).\n * 3. `setup` is a function — the `defineComponent({ setup() {} })` signature.\n * 4. `render` is a function — the `defineComponent({ render() {} })` signature.\n *\n * Requiring `setup` / `render` to be **functions** prevents plain POJOs that\n * happen to have a `setup` or `render` key from being misidentified as components.\n */\nfunction isVueSFC(value: unknown): value is Component {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst v = value as Record<string, unknown>;\n\t// Compiler-injected markers — unambiguous Vue component identifiers.\n\tif (\"__vccOpts\" in v || \"__name\" in v) return true;\n\t// defineComponent() output: setup or render must be callable, not just present.\n\treturn typeof v[\"setup\"] === \"function\" || typeof v[\"render\"] === \"function\";\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 `@xmachines/json-render-vue`'s rendering pipeline.\n *\n * Drop-in replacement for `defineRegistry` from `@xmachines/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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFA,SAAS,SAAS,OAAoC;CACrD,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,IAAI;CAEV,IAAI,eAAe,KAAK,YAAY,GAAG,OAAO;CAE9C,OAAO,OAAO,EAAE,aAAa,cAAc,OAAO,EAAE,cAAc;AACnE;;;;;;;AAQA,SAAS,QACR,WACoB;CACpB,QAAQ,QAAgC,EAAE,WAAW,GAAG;AACzD;;;;;;;;;;;;AA4BA,SAAgB,iBACf,SACA,SAC2C;CAC3C,MAAM,oBAAoB,CAAC;CAE3B,KAAK,MAAM,CAAC,KAAK,cAAc,OAAO,QAAQ,QAAQ,cAAc,CAAC,CAAC,GAAG;EACxE,IAAI,cAAc,KAAA,GAAW;EAC7B,MAAM,IAAI;EACV,kBAAkB,KAAK,SAAS,SAAS,IACtC,QAAQ,SAAsB,IAC7B;CACL;CAGA,OAAO,eAAmB,SAAS;EAAE,GAAG;EAAa,YAAY;CAAkB,CAAC;AACrF"}
package/dist/index.d.ts CHANGED
@@ -22,6 +22,6 @@ export { useActor } from "./useActor.js";
22
22
  export type { AnyPlayActor } from "./useActor.js";
23
23
  export { defineRegistry } from "./define-registry.js";
24
24
  export type { DefineRegistryOptions, ComponentsMap, ComponentEntry } from "./define-registry.js";
25
- export { JSONUIProvider, StateProvider, ActionProvider, VisibilityProvider, ValidationProvider, Renderer, useBoundProp, } from "@xmachines/json-render-vue";
25
+ export { JSONUIProvider, StateProvider, ActionProvider, VisibilityProvider, ValidationProvider, Renderer, useBoundProp, useFieldValidation, } from "@xmachines/json-render-vue";
26
26
  export type { JSONUIProviderProps, StateProviderProps, ActionProviderProps, ValidationProviderProps, RendererProps, ComponentFn, ComponentContext, DefineRegistryResult, } from "@xmachines/json-render-vue";
27
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGjE,YAAY,EACX,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAGpE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGjG,OAAO,EACN,cAAc,EACd,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,YAAY,GACZ,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACX,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,oBAAoB,GACpB,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGjE,YAAY,EACX,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAGpE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGjG,OAAO,EACN,cAAc,EACd,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,kBAAkB,GAClB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACX,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,oBAAoB,GACpB,MAAM,4BAA4B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import { getPlayViewContext } from "./actor-provider-context.js";
2
+ import PlayRenderer_default from "./PlayRenderer.js";
3
+ import { useActor } from "./useActor.js";
4
+ import ActorProvider_default from "./ActorProvider.js";
5
+ import PlayUIProvider_default from "./PlayUIProvider.js";
6
+ import { defineRegistry } from "./define-registry.js";
7
+ import { ActionProvider, JSONUIProvider, Renderer, StateProvider, ValidationProvider, VisibilityProvider, useBoundProp, useFieldValidation } from "@xmachines/json-render-vue";
8
+ export { ActionProvider, ActorProvider_default as ActorProvider, JSONUIProvider, PlayRenderer_default as PlayRenderer, PlayUIProvider_default as PlayUIProvider, Renderer, StateProvider, ValidationProvider, VisibilityProvider, defineRegistry, getPlayViewContext, useActor, useBoundProp, useFieldValidation };
@@ -0,0 +1,55 @@
1
+ import { inject, provide } from "vue";
2
+ import { assertNonNullable } from "@xmachines/play";
3
+ //#region packages/play-vue/src/useActor.ts
4
+ /**
5
+ * useActor — Vue composable for accessing the provided actor inside a PlayRenderer tree.
6
+ *
7
+ * Components rendered inside PlayRenderer can call useActor() to reach the actor
8
+ * instance without prop drilling.
9
+ *
10
+ * What is returned is a **swap-following proxy**, not the raw actor object:
11
+ * - It is a stable reference for the lifetime of the injection, yet forwards every
12
+ * operation (property reads/writes, `in`, `Object.keys` / spread, `instanceof`)
13
+ * to whichever actor is CURRENTLY provided — so it transparently follows a
14
+ * `props.actor` swap on `<ActorProvider>` without consumers re-injecting.
15
+ * - Method identity is stable per underlying method: `actor.send === actor.send`
16
+ * across repeated reads (allocation-free), and rebinds only when the underlying
17
+ * method changes or the actor is swapped.
18
+ * - It is NOT `===` the `actor` prop passed to `<ActorProvider>` (it is a distinct
19
+ * Proxy object). Any consumer keyed on actor identity — most notably a router
20
+ * bridge extending `RouterBridgeBase`, whose one-bridge-per-actor guard keys a
21
+ * WeakMap on the actor instance — must be given the actor prop itself, not the
22
+ * value returned by `useActor()`.
23
+ *
24
+ * @throws {Error} If called outside a PlayRenderer tree
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { useActor } from "@xmachines/play-vue";
29
+ *
30
+ * const actor = useActor();
31
+ * actor.send({ type: "SUBMIT" });
32
+ * ```
33
+ *
34
+ * @packageDocumentation
35
+ */
36
+ var ActorKey = Symbol("xmachines.actor");
37
+ /**
38
+ * Provide the actor to all descendant components via Vue's inject/provide mechanism.
39
+ *
40
+ * Called inside `PlayRenderer.vue`'s `setup()` to make the actor available to any
41
+ * child component that calls `useActor()`. Not typically needed outside framework
42
+ * internals unless building a custom renderer wrapper.
43
+ *
44
+ * @param actor - The actor instance to inject into the component tree.
45
+ */
46
+ function provideActor(actor) {
47
+ provide(ActorKey, actor);
48
+ }
49
+ function useActor() {
50
+ return assertNonNullable(inject(ActorKey), "ActorKey");
51
+ }
52
+ //#endregion
53
+ export { ActorKey, provideActor, useActor };
54
+
55
+ //# sourceMappingURL=useActor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useActor.js","names":[],"sources":["../src/useActor.ts"],"sourcesContent":["/**\n * useActor — Vue composable for accessing the provided actor inside a PlayRenderer tree.\n *\n * Components rendered inside PlayRenderer can call useActor() to reach the actor\n * instance without prop drilling.\n *\n * What is returned is a **swap-following proxy**, not the raw actor object:\n * - It is a stable reference for the lifetime of the injection, yet forwards every\n * operation (property reads/writes, `in`, `Object.keys` / spread, `instanceof`)\n * to whichever actor is CURRENTLY provided — so it transparently follows a\n * `props.actor` swap on `<ActorProvider>` without consumers re-injecting.\n * - Method identity is stable per underlying method: `actor.send === actor.send`\n * across repeated reads (allocation-free), and rebinds only when the underlying\n * method changes or the actor is swapped.\n * - It is NOT `===` the `actor` prop passed to `<ActorProvider>` (it is a distinct\n * Proxy object). Any consumer keyed on actor identity — most notably a router\n * bridge extending `RouterBridgeBase`, whose one-bridge-per-actor guard keys a\n * WeakMap on the actor instance — must be given the actor prop itself, not the\n * value returned by `useActor()`.\n *\n * @throws {Error} If called outside a PlayRenderer tree\n *\n * @example\n * ```typescript\n * import { useActor } from \"@xmachines/play-vue\";\n *\n * const actor = useActor();\n * actor.send({ type: \"SUBMIT\" });\n * ```\n *\n * @packageDocumentation\n */\n\nimport { inject, provide } from \"vue\";\nimport type { InjectionKey } from \"vue\";\nimport { assertNonNullable } from \"@xmachines/play\";\nimport type { AbstractActor } from \"@xmachines/play-actor\";\nimport type { AnyActorLogic } from \"xstate\";\n\n/** Bare actor type accepted by Vue context providers. For the full routing + view shape, use `PlayActor` from `@xmachines/play-router`. */\nexport type AnyPlayActor = AbstractActor<AnyActorLogic>;\n\nexport const ActorKey: InjectionKey<AnyPlayActor> = Symbol(\"xmachines.actor\");\n\n/**\n * Provide the actor to all descendant components via Vue's inject/provide mechanism.\n *\n * Called inside `PlayRenderer.vue`'s `setup()` to make the actor available to any\n * child component that calls `useActor()`. Not typically needed outside framework\n * internals unless building a custom renderer wrapper.\n *\n * @param actor - The actor instance to inject into the component tree.\n */\nexport function provideActor(actor: AnyPlayActor): void {\n\tprovide(ActorKey, actor);\n}\n\nexport function useActor(): AnyPlayActor {\n\treturn assertNonNullable(inject(ActorKey), \"ActorKey\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,IAAa,WAAuC,OAAO,iBAAiB;;;;;;;;;;AAW5E,SAAgB,aAAa,OAA2B;CACvD,QAAQ,UAAU,KAAK;AACxB;AAEA,SAAgB,WAAyB;CACxC,OAAO,kBAAkB,OAAO,QAAQ,GAAG,UAAU;AACtD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmachines/play-vue",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Vue renderer for XMachines Play architecture",
5
5
  "keywords": [
6
6
  "reactive",
@@ -13,7 +13,7 @@
13
13
  "author": "Mikael Karon <mikael@karon.se>",
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "git+ssh://git@gitlab.com/xmachin-es/xmachines-js.git",
16
+ "url": "git+https://gitlab.com/xmachin-es/xmachines-js.git",
17
17
  "directory": "packages/play-vue"
18
18
  },
19
19
  "files": [
@@ -29,13 +29,14 @@
29
29
  ".": {
30
30
  "types": "./dist/index.d.ts",
31
31
  "default": "./dist/index.js"
32
- }
32
+ },
33
+ "./package.json": "./package.json"
33
34
  },
34
35
  "publishConfig": {
35
36
  "access": "public"
36
37
  },
37
38
  "scripts": {
38
- "build": "vite build && tsc --build --force",
39
+ "build": "vite build && tsc --build",
39
40
  "clean": "rm -rf dist *.tsbuildinfo coverage .vitest-attachments test/browser/__screenshots__ node_modules/.svelte2tsx-* node_modules/.vite*",
40
41
  "lint": "oxlint .",
41
42
  "format": "oxfmt .",
@@ -43,19 +44,19 @@
43
44
  "test:watch": "vitest"
44
45
  },
45
46
  "dependencies": {
46
- "@xmachines/play": "1.1.0",
47
- "@xmachines/play-actor": "1.1.0",
48
- "@xmachines/play-signals": "1.1.0"
47
+ "@xmachines/play": "2.0.0",
48
+ "@xmachines/play-actor": "2.0.0",
49
+ "@xmachines/play-signals": "2.0.0"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@testing-library/jest-dom": "^6.9.1",
52
53
  "@types/node": "^26.2.0",
53
54
  "@vitejs/plugin-vue": "^6.0.5",
54
- "@vitest/browser-playwright": "^4.1.10",
55
+ "@vitest/browser-playwright": "^4.1.11",
55
56
  "@vue/test-utils": "^2.4.9",
56
- "@xmachines/json-render-core": "^0.19.0-xm.2",
57
- "@xmachines/json-render-vue": "^0.19.0-xm.2",
58
- "@xmachines/json-render-xstate": "^0.19.0-xm.2",
57
+ "@xmachines/json-render-core": "^0.20.0-xm.2",
58
+ "@xmachines/json-render-vue": "^0.20.0-xm.2",
59
+ "@xmachines/json-render-xstate": "^0.20.0-xm.2",
59
60
  "@xstate/store": "^3.17.0",
60
61
  "oxfmt": "^0.64.0",
61
62
  "oxlint": "^1.79.0",
@@ -68,9 +69,9 @@
68
69
  "zod": "^4.4.1"
69
70
  },
70
71
  "peerDependencies": {
71
- "@xmachines/json-render-core": "^0.19.0-xm.2",
72
- "@xmachines/json-render-vue": "^0.19.0-xm.2",
73
- "@xmachines/json-render-xstate": "^0.19.0-xm.2",
72
+ "@xmachines/json-render-core": "^0.20.0-xm.2",
73
+ "@xmachines/json-render-vue": "^0.20.0-xm.2",
74
+ "@xmachines/json-render-xstate": "^0.20.0-xm.2",
74
75
  "@xstate/store": "^3.17.0",
75
76
  "vue": "^3.5.0",
76
77
  "xstate": "^5.31.0"