@xmachines/play-vue 1.0.0-beta.3 → 1.0.0-beta.31
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/LICENSE +21 -0
- package/README.md +234 -84
- package/dist/PlayRenderer.js +2 -4
- package/dist/PlayRenderer.js.map +1 -1
- package/dist/PlayRenderer.vue.d.ts +40 -0
- package/dist/PlayRenderer.vue.d.ts.map +1 -0
- package/dist/PlayRenderer.vue_vue_type_script_lang.js +57 -18
- package/dist/PlayRenderer.vue_vue_type_script_lang.js.map +1 -1
- package/dist/define-registry.d.ts +79 -0
- package/dist/define-registry.d.ts.map +1 -0
- package/dist/define-registry.js +25 -0
- package/dist/define-registry.js.map +1 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/node_modules/@json-render/core/dist/chunk-AFLK3Q4T.js +111 -0
- package/dist/node_modules/@json-render/core/dist/chunk-AFLK3Q4T.js.map +1 -0
- package/dist/node_modules/@json-render/core/dist/index.js +956 -0
- package/dist/node_modules/@json-render/core/dist/index.js.map +1 -0
- package/dist/node_modules/@json-render/core/dist/store-utils.js +1 -0
- package/dist/node_modules/@json-render/vue/dist/chunk-WIPZLAF7.js +57 -0
- package/dist/node_modules/@json-render/vue/dist/chunk-WIPZLAF7.js.map +1 -0
- package/dist/node_modules/@json-render/vue/dist/index.js +798 -0
- package/dist/node_modules/@json-render/vue/dist/index.js.map +1 -0
- package/dist/node_modules/@json-render/xstate/dist/index.js +20 -0
- package/dist/node_modules/@json-render/xstate/dist/index.js.map +1 -0
- package/dist/node_modules/@xstate/store/dist/store-69e7e2d5.esm.js +227 -0
- package/dist/node_modules/@xstate/store/dist/store-69e7e2d5.esm.js.map +1 -0
- package/dist/node_modules/zod/v4/classic/errors.js +25 -0
- package/dist/node_modules/zod/v4/classic/errors.js.map +1 -0
- package/dist/node_modules/zod/v4/classic/iso.js +33 -0
- package/dist/node_modules/zod/v4/classic/iso.js.map +1 -0
- package/dist/node_modules/zod/v4/classic/parse.js +8 -0
- package/dist/node_modules/zod/v4/classic/parse.js.map +1 -0
- package/dist/node_modules/zod/v4/classic/schemas.js +362 -0
- package/dist/node_modules/zod/v4/classic/schemas.js.map +1 -0
- package/dist/node_modules/zod/v4/core/api.js +530 -0
- package/dist/node_modules/zod/v4/core/api.js.map +1 -0
- package/dist/node_modules/zod/v4/core/checks.js +285 -0
- package/dist/node_modules/zod/v4/core/checks.js.map +1 -0
- package/dist/node_modules/zod/v4/core/core.js +46 -0
- package/dist/node_modules/zod/v4/core/core.js.map +1 -0
- package/dist/node_modules/zod/v4/core/doc.js +25 -0
- package/dist/node_modules/zod/v4/core/doc.js.map +1 -0
- package/dist/node_modules/zod/v4/core/errors.js +43 -0
- package/dist/node_modules/zod/v4/core/errors.js.map +1 -0
- package/dist/node_modules/zod/v4/core/json-schema-processors.js +183 -0
- package/dist/node_modules/zod/v4/core/json-schema-processors.js.map +1 -0
- package/dist/node_modules/zod/v4/core/parse.js +70 -0
- package/dist/node_modules/zod/v4/core/parse.js.map +1 -0
- package/dist/node_modules/zod/v4/core/regexes.js +27 -0
- package/dist/node_modules/zod/v4/core/regexes.js.map +1 -0
- package/dist/node_modules/zod/v4/core/registries.js +42 -0
- package/dist/node_modules/zod/v4/core/registries.js.map +1 -0
- package/dist/node_modules/zod/v4/core/schemas.js +823 -0
- package/dist/node_modules/zod/v4/core/schemas.js.map +1 -0
- package/dist/node_modules/zod/v4/core/to-json-schema.js +224 -0
- package/dist/node_modules/zod/v4/core/to-json-schema.js.map +1 -0
- package/dist/node_modules/zod/v4/core/util.js +268 -0
- package/dist/node_modules/zod/v4/core/util.js.map +1 -0
- package/dist/node_modules/zod/v4/core/versions.js +10 -0
- package/dist/node_modules/zod/v4/core/versions.js.map +1 -0
- package/dist/types.d.ts +24 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/useActor.d.ts +35 -0
- package/dist/useActor.d.ts.map +1 -0
- package/dist/useActor.js +15 -0
- package/dist/useActor.js.map +1 -0
- package/package.json +27 -12
- package/dist/_virtual/_plugin-vue_export-helper.js +0 -8
- package/dist/index.css +0 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mikael Karon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,137 +1,287 @@
|
|
|
1
1
|
# @xmachines/play-vue
|
|
2
2
|
|
|
3
|
-
Vue renderer
|
|
3
|
+
**Vue 3 renderer for XMachines Play Architecture**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Bridges TC39 Signal-driven actors to Vue's reactivity. Business logic stays in the actor; Vue is purely a rendering target.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`@xmachines/play-vue` provides `PlayRenderer`, a Vue component that:
|
|
10
|
+
|
|
11
|
+
- Subscribes to `actor.currentView` (TC39 Signal) and re-renders on every state transition
|
|
12
|
+
- Renders the current view's JSON spec via `@json-render/vue`
|
|
13
|
+
- Routes action names from spec elements to `actor.send()` via the `actions` prop
|
|
14
|
+
- Manages per-view UI state in an `@xstate/store` atom (automatic or caller-supplied)
|
|
15
|
+
|
|
16
|
+
Per [Play RFC](../docs/rfc/play.md):
|
|
17
|
+
|
|
18
|
+
- **Actor Authority (INV-01):** Guards in the machine decide all state transitions
|
|
19
|
+
- **Passive Infrastructure (INV-04):** Vue observes signals and dispatches events — never decides
|
|
20
|
+
- **Signal-Only Reactivity (INV-05):** `actor.currentView` signal is the sole render trigger
|
|
6
21
|
|
|
7
22
|
## Installation
|
|
8
23
|
|
|
9
24
|
```bash
|
|
10
|
-
npm install @xmachines/play-vue
|
|
25
|
+
npm install @xmachines/play-vue
|
|
26
|
+
npm install @json-render/vue @json-render/core # peer deps
|
|
27
|
+
npm install @json-render/xstate @xstate/store # store integration
|
|
11
28
|
```
|
|
12
29
|
|
|
30
|
+
In this monorepo, the root install applies a `patch-package` patch to `@json-render/vue`
|
|
31
|
+
so `defineRegistry(..., { onRenderError })` can intercept inner element-boundary errors
|
|
32
|
+
without muting console output.
|
|
33
|
+
|
|
13
34
|
## Current Exports
|
|
14
35
|
|
|
15
|
-
- `PlayRenderer` (Vue
|
|
36
|
+
- `PlayRenderer` — main renderer component (Vue SFC)
|
|
37
|
+
- `useActor` — composable for accessing the actor inside a `PlayRenderer` tree
|
|
38
|
+
- `defineRegistry` — SFC-aware wrapper; auto-wraps `.vue` SFCs via `h(SFC, ctx)`
|
|
39
|
+
- `useBoundProp` — re-exported from `@json-render/vue`
|
|
40
|
+
- `ComponentFn` (type) — re-exported from `@json-render/vue`
|
|
41
|
+
- `ComponentContext` (type) — re-exported from `@json-render/vue`
|
|
16
42
|
- `PlayRendererProps` (type)
|
|
43
|
+
- `PlayActor` (type)
|
|
17
44
|
|
|
18
|
-
##
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
// catalog.ts — shared contract
|
|
49
|
+
import { defineCatalog } from "@json-render/core";
|
|
50
|
+
import { z } from "zod";
|
|
51
|
+
|
|
52
|
+
export const catalog = defineCatalog({
|
|
53
|
+
elements: {
|
|
54
|
+
Login: { props: z.object({ title: z.string() }), description: "Login form" },
|
|
55
|
+
Dashboard: { props: z.object({ username: z.string() }), description: "Dashboard" },
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export type Catalog = typeof catalog;
|
|
60
|
+
```
|
|
19
61
|
|
|
20
62
|
```vue
|
|
63
|
+
<!-- Login.vue — Vue SFC; useBoundProp works in <script setup> -->
|
|
21
64
|
<script setup lang="ts">
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
65
|
+
import { useBoundProp } from "@xmachines/play-vue";
|
|
66
|
+
import type { ComponentContext } from "@xmachines/play-vue";
|
|
67
|
+
import type { Catalog } from "./catalog.js";
|
|
68
|
+
|
|
69
|
+
const { props, emit, bindings } = defineProps<ComponentContext<Catalog, "Login">>();
|
|
70
|
+
const [username, setUsername] = useBoundProp<string>(bindings?.username ?? "/username");
|
|
71
|
+
</script>
|
|
25
72
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
73
|
+
<template>
|
|
74
|
+
<div class="view">
|
|
75
|
+
<h2>{{ props.title }}</h2>
|
|
76
|
+
<form @submit.prevent="emit('submit')">
|
|
77
|
+
<input id="username" v-model="username" @input="setUsername(username)" />
|
|
78
|
+
<button type="submit">Log In</button>
|
|
79
|
+
</form>
|
|
80
|
+
</div>
|
|
81
|
+
</template>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// registry.ts — pass SFCs directly; defineRegistry auto-wraps them
|
|
86
|
+
import { defineRegistry } from "@xmachines/play-vue";
|
|
87
|
+
import { catalog } from "./catalog.js";
|
|
88
|
+
import LoginSFC from "./Login.vue";
|
|
89
|
+
import DashboardSFC from "./Dashboard.vue";
|
|
90
|
+
|
|
91
|
+
export const registryResult = defineRegistry(catalog, {
|
|
92
|
+
components: { Login: LoginSFC, Dashboard: DashboardSFC },
|
|
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
|
+
},
|
|
31
102
|
});
|
|
103
|
+
```
|
|
32
104
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
105
|
+
```ts
|
|
106
|
+
// machine.ts
|
|
107
|
+
import { setup, assign } from "xstate";
|
|
108
|
+
import { formatPlayRouteTransitions } from "@xmachines/play-xstate";
|
|
109
|
+
|
|
110
|
+
export const machine = setup({
|
|
111
|
+
types: {
|
|
112
|
+
context: {} as {
|
|
113
|
+
isAuthenticated: boolean;
|
|
114
|
+
username: string | null;
|
|
115
|
+
params: Record<string, string>;
|
|
116
|
+
query: Record<string, string>;
|
|
117
|
+
},
|
|
118
|
+
events: {} as
|
|
119
|
+
| { type: "auth.login"; username: string }
|
|
120
|
+
| { type: "auth.logout" }
|
|
121
|
+
| { type: "play.route"; to: string; params?: Record<string, string> },
|
|
122
|
+
},
|
|
123
|
+
}).createMachine(
|
|
124
|
+
formatPlayRouteTransitions({
|
|
125
|
+
id: "app",
|
|
126
|
+
initial: "login",
|
|
127
|
+
context: { isAuthenticated: false, username: null, params: {}, query: {} },
|
|
128
|
+
states: {
|
|
129
|
+
login: {
|
|
130
|
+
id: "login",
|
|
131
|
+
meta: {
|
|
132
|
+
route: "/login",
|
|
133
|
+
view: {
|
|
134
|
+
component: "Login",
|
|
135
|
+
spec: {
|
|
136
|
+
root: "root",
|
|
137
|
+
elements: {
|
|
138
|
+
root: { type: "Login", props: { title: "Sign In" }, children: [] },
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
dashboard: {
|
|
145
|
+
id: "dashboard",
|
|
146
|
+
meta: {
|
|
147
|
+
route: "/dashboard",
|
|
148
|
+
view: {
|
|
149
|
+
component: "Dashboard",
|
|
150
|
+
spec: {
|
|
151
|
+
root: "root",
|
|
152
|
+
elements: {
|
|
153
|
+
root: { type: "Dashboard", props: { username: "" }, children: [] },
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
on: {
|
|
161
|
+
"auth.login": {
|
|
162
|
+
target: ".dashboard",
|
|
163
|
+
guard: ({ context }) => !context.isAuthenticated,
|
|
164
|
+
actions: assign({ isAuthenticated: true, username: ({ event }) => event.username }),
|
|
165
|
+
},
|
|
166
|
+
"auth.logout": {
|
|
167
|
+
target: ".login",
|
|
168
|
+
guard: ({ context }) => context.isAuthenticated,
|
|
169
|
+
actions: assign({ isAuthenticated: false, username: null }),
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
}),
|
|
173
|
+
);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
```vue
|
|
177
|
+
<!-- App.vue -->
|
|
178
|
+
<script setup lang="ts">
|
|
179
|
+
import { definePlayer } from "@xmachines/play-xstate";
|
|
180
|
+
import { PlayRenderer } from "@xmachines/play-vue";
|
|
181
|
+
import { machine } from "./machine.js";
|
|
182
|
+
import { registryResult } from "./registry.js";
|
|
36
183
|
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
Login: LoginComponent,
|
|
41
|
-
Dashboard: DashboardComponent,
|
|
42
|
-
};
|
|
184
|
+
const createPlayer = definePlayer({ machine });
|
|
185
|
+
const actor = createPlayer();
|
|
186
|
+
actor.start();
|
|
43
187
|
</script>
|
|
44
188
|
|
|
45
189
|
<template>
|
|
46
|
-
<PlayRenderer :actor="actor" :
|
|
47
|
-
<template #fallback>
|
|
48
|
-
<div>Loading...</div>
|
|
49
|
-
</template>
|
|
50
|
-
</PlayRenderer>
|
|
190
|
+
<PlayRenderer :actor="actor" :registryResult="registryResult" />
|
|
51
191
|
</template>
|
|
52
192
|
```
|
|
53
193
|
|
|
54
|
-
## API
|
|
55
|
-
|
|
56
|
-
### PlayRenderer
|
|
194
|
+
## API Reference
|
|
57
195
|
|
|
58
|
-
|
|
196
|
+
### `PlayRenderer`
|
|
59
197
|
|
|
60
|
-
|
|
198
|
+
Main Vue component. Subscribes to `actor.currentView` and renders the spec.
|
|
61
199
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
200
|
+
```vue
|
|
201
|
+
<PlayRenderer :actor="actor" :registryResult="registryResult" :store="myStore" />
|
|
202
|
+
```
|
|
65
203
|
|
|
66
|
-
|
|
204
|
+
**`actor`** — A `PlayerActor` (or any `AbstractActor & Viewable`). Provides the `currentView` signal.
|
|
67
205
|
|
|
68
|
-
|
|
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>`.
|
|
69
207
|
|
|
70
|
-
|
|
71
|
-
-
|
|
208
|
+
`defineRegistry` also accepts `onRenderError(error, elementType)`, which receives errors
|
|
209
|
+
caught by `@json-render/vue`'s inner element boundary before the default logger is used.
|
|
72
210
|
|
|
73
|
-
|
|
211
|
+
**`store`** (optional) — Controls per-view UI state (`$state` bindings, form values):
|
|
74
212
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
import type { AbstractActor } from "@xmachines/play-actor";
|
|
213
|
+
- **Omitted (uncontrolled, default):** A fresh `@xstate/store` atom is created per view transition, seeded from `view.spec.state`.
|
|
214
|
+
- **Provided (controlled):** The caller owns the store; `spec.state` is ignored.
|
|
78
215
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
216
|
+
```ts
|
|
217
|
+
import { createAtom } from "@xstate/store";
|
|
218
|
+
import { xstateStoreStateStore } from "@json-render/xstate";
|
|
219
|
+
import type { StateStore } from "@json-render/core";
|
|
83
220
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
</script>
|
|
221
|
+
const store: StateStore = xstateStoreStateStore({ atom: createAtom({ username: "" }) });
|
|
222
|
+
```
|
|
88
223
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
224
|
+
**Inner render errors** — You can intercept catalog component render failures without
|
|
225
|
+
overriding the outer Vue error boundary:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
export const registryResult = defineRegistry(catalog, {
|
|
229
|
+
components: { Login: LoginSFC, Dashboard: DashboardSFC },
|
|
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
|
+
},
|
|
239
|
+
onRenderError(error, elementType) {
|
|
240
|
+
reportExpectedRenderError(error, elementType);
|
|
241
|
+
},
|
|
242
|
+
});
|
|
95
243
|
```
|
|
96
244
|
|
|
97
|
-
|
|
245
|
+
```vue
|
|
246
|
+
<PlayRenderer :actor="actor" :registryResult="registryResult" :store="store" />
|
|
247
|
+
```
|
|
98
248
|
|
|
99
|
-
|
|
100
|
-
- **Dynamic Rendering:** Renders components based on `actor.currentView.component` string
|
|
101
|
-
- **Type Safe:** Full TypeScript support with generic type inference
|
|
102
|
-
- **Error Handling:** Gracefully handles missing components and null catalogs
|
|
103
|
-
- **One-Shot Re-Watch:** Implements proper signal watcher pattern with microtask batching
|
|
249
|
+
---
|
|
104
250
|
|
|
105
|
-
|
|
251
|
+
### `useActor`
|
|
106
252
|
|
|
107
|
-
|
|
253
|
+
Vue composable for accessing the actor from inside any component rendered by `PlayRenderer`.
|
|
108
254
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
3. `getPending()`
|
|
112
|
-
4. read actor signals and update framework-local state
|
|
113
|
-
5. re-arm with `watch(...)` or `watch()`
|
|
255
|
+
```ts
|
|
256
|
+
import { useActor } from "@xmachines/play-vue";
|
|
114
257
|
|
|
115
|
-
|
|
258
|
+
// Inside any component rendered inside PlayRenderer:
|
|
259
|
+
const actor = useActor();
|
|
260
|
+
actor.send({ type: "auth.logout" });
|
|
261
|
+
```
|
|
116
262
|
|
|
117
|
-
|
|
263
|
+
Throws `"useActor() must be called inside <PlayRenderer>"` if called outside the tree.
|
|
118
264
|
|
|
119
|
-
|
|
265
|
+
---
|
|
120
266
|
|
|
121
|
-
|
|
122
|
-
- Treat renderer/provider disposal as deterministic teardown, not GC-only cleanup.
|
|
123
|
-
- Keep actor-driven routing and view decisions in the actor layer.
|
|
267
|
+
## Route Parameters in Props
|
|
124
268
|
|
|
125
|
-
|
|
269
|
+
When using `formatPlayRouteTransitions`, URL path parameters flow automatically into component props. Declare an `undefined` slot in the spec to opt in:
|
|
126
270
|
|
|
127
|
-
|
|
271
|
+
```ts
|
|
272
|
+
// spec: { section: undefined, user: "alice" }
|
|
273
|
+
// After play.route to /settings/profile → context.params = { section: "profile" }
|
|
274
|
+
// Component receives: { section: "profile", user: "alice" }
|
|
275
|
+
```
|
|
128
276
|
|
|
129
|
-
|
|
130
|
-
2. **Passive Infrastructure:** Renderer observes signals, sends events
|
|
131
|
-
3. **Signal-Only Reactivity:** Business logic state lives in actor signals
|
|
277
|
+
Priority: **route param fills `undefined` slots; explicit non-`undefined` spec props always win.**
|
|
132
278
|
|
|
133
|
-
|
|
279
|
+
---
|
|
134
280
|
|
|
135
|
-
##
|
|
281
|
+
## Architecture Notes
|
|
136
282
|
|
|
137
|
-
|
|
283
|
+
- Vue reactivity is only used to trigger re-renders — not for business logic
|
|
284
|
+
- `actor.currentView` (TC39 Signal) is bridged to Vue's reactive system inside `PlayRenderer`
|
|
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 `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
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import e from "./PlayRenderer.vue_vue_type_script_lang.js";
|
|
2
|
-
/* empty css */
|
|
3
|
-
import t from "./_virtual/_plugin-vue_export-helper.js";
|
|
4
2
|
//#region src/PlayRenderer.vue
|
|
5
|
-
var
|
|
3
|
+
var t = e;
|
|
6
4
|
//#endregion
|
|
7
|
-
export {
|
|
5
|
+
export { t as default };
|
|
8
6
|
|
|
9
7
|
//# sourceMappingURL=PlayRenderer.js.map
|
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":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PropType } from 'vue';
|
|
2
|
+
import { AbstractActor, Viewable } from '@xmachines/play-actor';
|
|
3
|
+
import { AnyActorLogic } from 'xstate';
|
|
4
|
+
import { DefineRegistryResult } from '@json-render/vue';
|
|
5
|
+
import { StateStore } from '@json-render/core';
|
|
6
|
+
declare const _default: import('vue', { with: { "resolution-mode": "import" } }).DefineComponent<import('vue', { with: { "resolution-mode": "import" } }).ExtractPropTypes<{
|
|
7
|
+
actor: {
|
|
8
|
+
type: PropType<AbstractActor<AnyActorLogic> & Viewable>;
|
|
9
|
+
required: true;
|
|
10
|
+
};
|
|
11
|
+
registryResult: {
|
|
12
|
+
type: PropType<DefineRegistryResult>;
|
|
13
|
+
required: true;
|
|
14
|
+
};
|
|
15
|
+
store: {
|
|
16
|
+
type: PropType<StateStore>;
|
|
17
|
+
default: undefined;
|
|
18
|
+
};
|
|
19
|
+
}>, () => import('vue', { with: { "resolution-mode": "import" } }).VNode<import('vue', { with: { "resolution-mode": "import" } }).RendererNode, import('vue', { with: { "resolution-mode": "import" } }).RendererElement, {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
}> | import('vue', { with: { "resolution-mode": "import" } }).VNode<import('vue', { with: { "resolution-mode": "import" } }).RendererNode, import('vue', { with: { "resolution-mode": "import" } }).RendererElement, {
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}>[] | null, {}, {}, {}, import('vue', { with: { "resolution-mode": "import" } }).ComponentOptionsMixin, import('vue', { with: { "resolution-mode": "import" } }).ComponentOptionsMixin, {}, string, import('vue', { with: { "resolution-mode": "import" } }).PublicProps, Readonly<import('vue', { with: { "resolution-mode": "import" } }).ExtractPropTypes<{
|
|
24
|
+
actor: {
|
|
25
|
+
type: PropType<AbstractActor<AnyActorLogic> & Viewable>;
|
|
26
|
+
required: true;
|
|
27
|
+
};
|
|
28
|
+
registryResult: {
|
|
29
|
+
type: PropType<DefineRegistryResult>;
|
|
30
|
+
required: true;
|
|
31
|
+
};
|
|
32
|
+
store: {
|
|
33
|
+
type: PropType<StateStore>;
|
|
34
|
+
default: undefined;
|
|
35
|
+
};
|
|
36
|
+
}>> & Readonly<{}>, {
|
|
37
|
+
store: StateStore;
|
|
38
|
+
}, {}, {}, {}, string, import('vue', { with: { "resolution-mode": "import" } }).ComponentProvideOptions, true, {}, any>;
|
|
39
|
+
export default _default;
|
|
40
|
+
//# sourceMappingURL=PlayRenderer.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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,35 +1,74 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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";
|
|
3
7
|
//#region src/PlayRenderer.vue?vue&type=script&lang.ts
|
|
4
|
-
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({
|
|
5
32
|
name: "PlayRenderer",
|
|
6
33
|
props: {
|
|
7
34
|
actor: {
|
|
8
35
|
type: Object,
|
|
9
36
|
required: !0
|
|
10
37
|
},
|
|
11
|
-
|
|
38
|
+
registryResult: {
|
|
12
39
|
type: Object,
|
|
13
40
|
required: !0
|
|
41
|
+
},
|
|
42
|
+
store: {
|
|
43
|
+
type: Object,
|
|
44
|
+
default: void 0
|
|
14
45
|
}
|
|
15
46
|
},
|
|
16
|
-
setup(
|
|
17
|
-
let
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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;
|
|
24
55
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
56
|
+
return d(() => {
|
|
57
|
+
y();
|
|
58
|
+
}), () => {
|
|
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
|
+
}));
|
|
68
|
+
};
|
|
30
69
|
}
|
|
31
70
|
});
|
|
32
71
|
//#endregion
|
|
33
|
-
export {
|
|
72
|
+
export { g as default };
|
|
34
73
|
|
|
35
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"}
|