@xmachines/docs 1.0.0-beta.16 → 1.0.0-beta.18
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/api/@xmachines/play/README.md +56 -17
- package/api/@xmachines/play/classes/PlayError.md +240 -0
- package/api/@xmachines/play/type-aliases/PlayEvent.md +4 -4
- package/api/@xmachines/play-actor/README.md +32 -31
- package/api/@xmachines/play-actor/classes/AbstractActor.md +20 -19
- package/api/@xmachines/play-actor/interfaces/PlaySpec.md +37 -0
- package/api/@xmachines/play-actor/interfaces/Routable.md +5 -4
- package/api/@xmachines/play-actor/interfaces/ViewMetadata.md +6 -6
- package/api/@xmachines/play-actor/interfaces/Viewable.md +8 -8
- package/api/@xmachines/play-dom/README.md +36 -0
- package/api/@xmachines/play-dom/classes/PlayRenderer.md +83 -0
- package/api/@xmachines/play-dom/functions/connectRenderer.md +51 -0
- package/api/@xmachines/play-dom/functions/renderSpec.md +28 -0
- package/api/@xmachines/play-dom/interfaces/ConnectRendererOptions.md +18 -0
- package/api/@xmachines/play-dom/interfaces/DomRenderContext.md +18 -0
- package/api/@xmachines/play-dom/interfaces/PlayDomOptions.md +14 -0
- package/api/@xmachines/play-dom/type-aliases/DomComponentRenderer.md +23 -0
- package/api/@xmachines/play-dom/type-aliases/DomRegistry.md +11 -0
- package/api/@xmachines/play-react/README.md +227 -305
- package/api/@xmachines/play-react/classes/PlayErrorBoundary.md +5 -5
- package/api/@xmachines/play-react/functions/defineRegistry.md +47 -0
- package/api/@xmachines/play-react/functions/useActor.md +13 -0
- package/api/@xmachines/play-react/functions/useBoundProp.md +43 -0
- package/api/@xmachines/play-react/functions/useSignalEffect.md +1 -1
- package/api/@xmachines/play-react/functions/useStateBinding.md +32 -0
- package/api/@xmachines/play-react/interfaces/ComponentContext.md +35 -0
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryProps.md +4 -4
- package/api/@xmachines/play-react/interfaces/PlayErrorBoundaryState.md +3 -3
- package/api/@xmachines/play-react/interfaces/PlayRendererProps.md +15 -7
- package/api/@xmachines/play-react/type-aliases/ComponentFn.md +34 -0
- package/api/@xmachines/play-react/type-aliases/PlayActor.md +9 -0
- package/api/@xmachines/play-react/variables/PlayRenderer.md +18 -30
- package/api/@xmachines/play-react-router/classes/ReactRouterBridge.md +32 -32
- package/api/@xmachines/play-react-router/classes/RouteMap.md +5 -5
- package/api/@xmachines/play-react-router/functions/PlayRouterProvider.md +11 -5
- package/api/@xmachines/play-react-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-react-router/interfaces/PlayRouterProviderProps.md +14 -8
- package/api/@xmachines/play-react-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-router/README.md +51 -0
- package/api/@xmachines/play-router/classes/BaseRouteMap.md +6 -6
- package/api/@xmachines/play-router/classes/RouterBridgeBase.md +33 -35
- package/api/@xmachines/play-router/functions/buildRouteTree.md +1 -1
- package/api/@xmachines/play-router/functions/connectRouter.md +1 -1
- package/api/@xmachines/play-router/functions/crawlMachine.md +1 -1
- package/api/@xmachines/play-router/functions/createBrowserHistory.md +4 -1
- package/api/@xmachines/play-router/functions/createRouteMap.md +3 -3
- package/api/@xmachines/play-router/functions/createRouter.md +1 -1
- package/api/@xmachines/play-router/functions/detectDuplicateRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/extractMachineRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/extractRoute.md +1 -1
- package/api/@xmachines/play-router/functions/findRouteById.md +1 -1
- package/api/@xmachines/play-router/functions/findRouteByPath.md +1 -1
- package/api/@xmachines/play-router/functions/getNavigableRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/getRoutableRoutes.md +1 -1
- package/api/@xmachines/play-router/functions/routeExists.md +1 -1
- package/api/@xmachines/play-router/functions/validateRouteFormat.md +1 -1
- package/api/@xmachines/play-router/functions/validateStateExists.md +1 -1
- package/api/@xmachines/play-router/interfaces/BaseRouteMapping.md +3 -3
- package/api/@xmachines/play-router/interfaces/BrowserHistory.md +19 -15
- package/api/@xmachines/play-router/interfaces/BrowserWindow.md +14 -14
- package/api/@xmachines/play-router/interfaces/ConnectRouterOptions.md +6 -6
- package/api/@xmachines/play-router/interfaces/PlayRouteEvent.md +6 -6
- package/api/@xmachines/play-router/interfaces/RouteInfo.md +8 -8
- package/api/@xmachines/play-router/interfaces/RouteMap.md +4 -4
- package/api/@xmachines/play-router/interfaces/RouteNode.md +10 -10
- package/api/@xmachines/play-router/interfaces/RouteObject.md +2 -2
- package/api/@xmachines/play-router/interfaces/RouteTree.md +4 -4
- package/api/@xmachines/play-router/interfaces/RouteWatcherHandle.md +55 -0
- package/api/@xmachines/play-router/interfaces/RouterBridge.md +3 -3
- package/api/@xmachines/play-router/interfaces/StateVisit.md +4 -4
- package/api/@xmachines/play-router/interfaces/VanillaRouter.md +4 -4
- package/api/@xmachines/play-router/type-aliases/RouteMetadata.md +1 -1
- package/api/@xmachines/play-signals/README.md +22 -10
- package/api/@xmachines/play-signals/functions/watchSignal.md +35 -0
- package/api/@xmachines/play-signals/interfaces/ComputedOptions.md +2 -2
- package/api/@xmachines/play-signals/interfaces/SignalComputed.md +2 -2
- package/api/@xmachines/play-signals/interfaces/SignalOptions.md +2 -2
- package/api/@xmachines/play-signals/interfaces/SignalState.md +3 -3
- package/api/@xmachines/play-signals/interfaces/SignalWatcher.md +4 -4
- package/api/@xmachines/play-signals/type-aliases/WatcherNotify.md +1 -1
- package/api/@xmachines/play-solid/README.md +193 -219
- package/api/@xmachines/play-solid/functions/defineRegistry.md +47 -0
- package/api/@xmachines/play-solid/functions/useActor.md +13 -0
- package/api/@xmachines/play-solid/functions/useStateBinding.md +23 -0
- package/api/@xmachines/play-solid/interfaces/ComponentContext.md +35 -0
- package/api/@xmachines/play-solid/interfaces/PlayRendererProps.md +15 -7
- package/api/@xmachines/play-solid/type-aliases/ComponentFn.md +34 -0
- package/api/@xmachines/play-solid/type-aliases/PlayActor.md +9 -0
- package/api/@xmachines/play-solid/variables/PlayRenderer.md +15 -43
- package/api/@xmachines/play-solid-router/README.md +56 -30
- package/api/@xmachines/play-solid-router/classes/RouteMap.md +6 -6
- package/api/@xmachines/play-solid-router/classes/SolidRouterBridge.md +37 -37
- package/api/@xmachines/play-solid-router/functions/PlayRouterProvider.md +11 -5
- package/api/@xmachines/play-solid-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-solid-router/interfaces/AbstractActor.md +18 -17
- package/api/@xmachines/play-solid-router/interfaces/PlayRouterProviderProps.md +14 -8
- package/api/@xmachines/play-solid-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-solid-router/type-aliases/RoutableActor.md +3 -1
- package/api/@xmachines/play-solid-router/type-aliases/SolidRouterHooks.md +4 -4
- package/api/@xmachines/play-tanstack-react-router/README.md +1 -5
- package/api/@xmachines/play-tanstack-react-router/classes/RouteMap.md +5 -5
- package/api/@xmachines/play-tanstack-react-router/classes/TanStackReactRouterBridge.md +45 -33
- package/api/@xmachines/play-tanstack-react-router/functions/PlayRouterProvider.md +11 -5
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMap.md +2 -2
- package/api/@xmachines/play-tanstack-react-router/functions/createRouteMapFromTree.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/functions/extractParams.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/functions/extractQueryParams.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/interfaces/PlayRouterProviderProps.md +14 -8
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-tanstack-react-router/interfaces/RouteNavigateEvent.md +3 -3
- package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterInstance.md +1 -1
- package/api/@xmachines/play-tanstack-react-router/type-aliases/TanStackRouterLike.md +24 -4
- package/api/@xmachines/play-tanstack-solid-router/classes/RouteMap.md +6 -6
- package/api/@xmachines/play-tanstack-solid-router/classes/SolidRouterBridge.md +33 -33
- package/api/@xmachines/play-tanstack-solid-router/functions/PlayRouterProvider.md +11 -5
- package/api/@xmachines/play-tanstack-solid-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-tanstack-solid-router/interfaces/PlayRouterProviderProps.md +14 -8
- package/api/@xmachines/play-tanstack-solid-router/interfaces/RouteMapping.md +3 -3
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/RoutableActor.md +3 -1
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterInstance.md +1 -1
- package/api/@xmachines/play-tanstack-solid-router/type-aliases/TanStackRouterLike.md +4 -4
- package/api/@xmachines/play-vue/README.md +219 -209
- package/api/@xmachines/play-vue/functions/defineRegistry.md +32 -0
- package/api/@xmachines/play-vue/functions/useActor.md +13 -0
- package/api/@xmachines/play-vue/functions/useStateBinding.md +30 -0
- package/api/@xmachines/play-vue/interfaces/ComponentContext.md +35 -0
- package/api/@xmachines/play-vue/interfaces/PlayRendererProps.md +14 -6
- package/api/@xmachines/play-vue/type-aliases/ComponentEntry.md +16 -0
- package/api/@xmachines/play-vue/type-aliases/ComponentFn.md +33 -0
- package/api/@xmachines/play-vue/type-aliases/ComponentsMap.md +15 -0
- package/api/@xmachines/play-vue/type-aliases/DefineRegistryOptions.md +21 -0
- package/api/@xmachines/play-vue/type-aliases/PlayActor.md +9 -0
- package/api/@xmachines/play-vue/variables/PlayRenderer.md +1 -1
- package/api/@xmachines/play-vue-router/README.md +74 -29
- package/api/@xmachines/play-vue-router/classes/RouteMap.md +7 -7
- package/api/@xmachines/play-vue-router/classes/VueBaseRouteMap.md +7 -7
- package/api/@xmachines/play-vue-router/classes/VueRouterBridge.md +48 -51
- package/api/@xmachines/play-vue-router/functions/createRouteMap.md +1 -1
- package/api/@xmachines/play-vue-router/interfaces/RouteMapping.md +4 -4
- package/api/@xmachines/play-vue-router/type-aliases/RoutableActor.md +3 -1
- package/api/@xmachines/play-vue-router/variables/PlayRouterProvider.md +7 -1
- package/api/@xmachines/play-xstate/README.md +236 -111
- package/api/@xmachines/play-xstate/classes/PlayerActor.md +36 -33
- package/api/@xmachines/play-xstate/functions/buildRouteUrl.md +24 -18
- package/api/@xmachines/play-xstate/functions/composeGuards.md +1 -1
- package/api/@xmachines/play-xstate/functions/composeGuardsOr.md +1 -1
- package/api/@xmachines/play-xstate/functions/definePlayer.md +12 -61
- package/api/@xmachines/play-xstate/functions/deriveRoute.md +1 -1
- package/api/@xmachines/play-xstate/functions/eventMatches.md +1 -1
- package/api/@xmachines/play-xstate/functions/formatPlayRouteTransitions.md +1 -1
- package/api/@xmachines/play-xstate/functions/hasContext.md +1 -1
- package/api/@xmachines/play-xstate/functions/isAbsoluteRoute.md +1 -1
- package/api/@xmachines/play-xstate/functions/negateGuard.md +1 -1
- package/api/@xmachines/play-xstate/functions/stateMatches.md +1 -1
- package/api/@xmachines/play-xstate/interfaces/PlayerConfig.md +9 -13
- package/api/@xmachines/play-xstate/interfaces/PlayerFactoryResumeOptions.md +2 -2
- package/api/@xmachines/play-xstate/interfaces/PlayerOptions.md +8 -9
- package/api/@xmachines/play-xstate/interfaces/RouteContext.md +5 -5
- package/api/@xmachines/play-xstate/type-aliases/ComposedGuard.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/Guard.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/GuardArray.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/PlayerFactory.md +1 -1
- package/api/@xmachines/play-xstate/type-aliases/RouteMachineConfig.md +14 -4
- package/api/@xmachines/play-xstate/type-aliases/RouteStateNode.md +19 -4
- package/api/@xmachines/shared/functions/defineXmVitestConfig.md +2 -2
- package/api/@xmachines/shared/functions/xmAliases.md +1 -1
- package/api/README.md +2 -2
- package/api/llms.txt +12 -6
- package/examples/multi-router-integration.md +31 -19
- package/guides/README.md +2 -1
- package/guides/installation.md +1 -6
- package/package.json +2 -2
- package/api/@xmachines/play-catalog/README.md +0 -331
- package/api/@xmachines/play-catalog/functions/defineCatalog.md +0 -98
- package/api/@xmachines/play-catalog/functions/defineComponents.md +0 -134
- package/api/@xmachines/play-catalog/type-aliases/Catalog.md +0 -48
- package/api/@xmachines/play-catalog/type-aliases/ComponentsFor.md +0 -20
- package/api/@xmachines/play-catalog/type-aliases/InferComponentProps.md +0 -65
- package/api/@xmachines/play-catalog/type-aliases/NoExtraKeys.md +0 -17
- package/api/@xmachines/play-xstate/functions/mergeViewProps.md +0 -26
- package/api/@xmachines/play-xstate/functions/validateComponentBinding.md +0 -39
- package/api/@xmachines/play-xstate/functions/validateViewProps.md +0 -80
- package/api/@xmachines/play-xstate/interfaces/CatalogEntry.md +0 -16
- package/api/@xmachines/play-xstate/type-aliases/Catalog.md +0 -21
- package/api/@xmachines/play-xstate/type-aliases/ValidationResult.md +0 -17
- package/api/@xmachines/play-xstate/type-aliases/ViewMergeContext.md +0 -35
|
@@ -2,291 +2,301 @@
|
|
|
2
2
|
|
|
3
3
|
# @xmachines/play-vue
|
|
4
4
|
|
|
5
|
-
**Vue renderer
|
|
5
|
+
**Vue 3 renderer for XMachines Play Architecture**
|
|
6
6
|
|
|
7
|
-
Signal-driven Vue
|
|
7
|
+
Bridges TC39 Signal-driven actors to Vue's reactivity. Business logic stays in the actor; Vue is purely a rendering target.
|
|
8
8
|
|
|
9
9
|
## Overview
|
|
10
10
|
|
|
11
|
-
`@xmachines/play-vue` provides `PlayRenderer
|
|
11
|
+
`@xmachines/play-vue` provides `PlayRenderer`, a Vue component that:
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
- Subscribes to `actor.currentView` (TC39 Signal) and re-renders on every state transition
|
|
14
|
+
- Renders the current view's JSON spec via `@json-render/vue`
|
|
15
|
+
- Routes action names from spec elements to `actor.send()` via the `actions` prop
|
|
16
|
+
- Manages per-view UI state in an `@xstate/store` atom (automatic or caller-supplied)
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
- **Passive Infrastructure (INV-04):** Components observe signals, send events to actor
|
|
18
|
+
Per [RFC Play v1](https://gitlab.com/xmachin-es/rfc/-/blob/main/src/play-v1.md):
|
|
17
19
|
|
|
18
|
-
**
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
- **Actor Authority (INV-01):** Guards in the machine decide all state transitions
|
|
21
|
+
- **Passive Infrastructure (INV-04):** Vue observes signals and dispatches events — never decides
|
|
22
|
+
- **Signal-Only Reactivity (INV-05):** `actor.currentView` signal is the sole render trigger
|
|
21
23
|
|
|
22
24
|
## Installation
|
|
23
25
|
|
|
24
26
|
```bash
|
|
25
|
-
npm install vue@^3.5.0
|
|
26
27
|
npm install @xmachines/play-vue
|
|
28
|
+
npm install @json-render/vue @json-render/core # peer deps
|
|
29
|
+
npm install @json-render/xstate @xstate/store # store integration
|
|
27
30
|
```
|
|
28
31
|
|
|
29
32
|
## Current Exports
|
|
30
33
|
|
|
31
|
-
- `PlayRenderer` (Vue
|
|
32
|
-
- `
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- `
|
|
34
|
+
- `PlayRenderer` — main renderer component (Vue SFC)
|
|
35
|
+
- `useActor` — composable for accessing the actor inside a `PlayRenderer` tree
|
|
36
|
+
- `defineRegistry` — SFC-aware wrapper; auto-wraps `.vue` SFCs via `h(SFC, ctx)`
|
|
37
|
+
- `useStateBinding` — re-exported from `@json-render/vue`
|
|
38
|
+
- `ComponentFn` (type) — re-exported from `@json-render/vue`
|
|
39
|
+
- `ComponentContext` (type) — re-exported from `@json-render/vue`
|
|
40
|
+
- `PlayRendererProps` (type)
|
|
41
|
+
- `PlayActor` (type)
|
|
37
42
|
|
|
38
43
|
## Quick Start
|
|
39
44
|
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
import { definePlayer } from "@xmachines/play-xstate";
|
|
44
|
-
import { defineCatalog } from "@xmachines/play-catalog";
|
|
45
|
-
import { PlayRenderer } from "@xmachines/play-vue";
|
|
45
|
+
```ts
|
|
46
|
+
// catalog.ts — shared contract
|
|
47
|
+
import { defineCatalog } from "@json-render/core";
|
|
46
48
|
import { z } from "zod";
|
|
47
|
-
import LoginForm from "./components/LoginForm.vue";
|
|
48
|
-
import Dashboard from "./components/Dashboard.vue";
|
|
49
|
-
|
|
50
|
-
// 1. Define catalog (business logic layer)
|
|
51
|
-
const catalog = defineCatalog({
|
|
52
|
-
LoginForm: z.object({ error: z.string().optional() }),
|
|
53
|
-
Dashboard: z.object({
|
|
54
|
-
userId: z.string(),
|
|
55
|
-
username: z.string(),
|
|
56
|
-
}),
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// 2. Define component map (view layer)
|
|
60
|
-
const components = {
|
|
61
|
-
LoginForm,
|
|
62
|
-
Dashboard,
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// 3. Create player actor (business logic runtime)
|
|
66
|
-
const createPlayer = definePlayer({ machine: authMachine, catalog });
|
|
67
|
-
const actor = createPlayer();
|
|
68
|
-
actor.start();
|
|
69
|
-
</script>
|
|
70
49
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
</PlayRenderer>
|
|
78
|
-
</template>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## API Reference
|
|
82
|
-
|
|
83
|
-
### PlayRenderer
|
|
84
|
-
|
|
85
|
-
Main renderer component subscribing to actor signals and dynamically rendering catalog components:
|
|
50
|
+
export const catalog = defineCatalog({
|
|
51
|
+
elements: {
|
|
52
|
+
Login: { props: z.object({ title: z.string() }), description: "Login form" },
|
|
53
|
+
Dashboard: { props: z.object({ username: z.string() }), description: "Dashboard" },
|
|
54
|
+
},
|
|
55
|
+
});
|
|
86
56
|
|
|
87
|
-
|
|
88
|
-
interface PlayRendererProps {
|
|
89
|
-
actor: AbstractActor<any>;
|
|
90
|
-
components: Record<string, Component>;
|
|
91
|
-
}
|
|
57
|
+
export type Catalog = typeof catalog;
|
|
92
58
|
```
|
|
93
59
|
|
|
94
|
-
**Props:**
|
|
95
|
-
|
|
96
|
-
- `actor` - Actor instance with `currentView` signal
|
|
97
|
-
- `components` - Map of component names to Vue components
|
|
98
|
-
|
|
99
|
-
**Slots:**
|
|
100
|
-
|
|
101
|
-
- `fallback` - Slot shown when `currentView` is null
|
|
102
|
-
|
|
103
|
-
**Behavior:**
|
|
104
|
-
|
|
105
|
-
1. Subscribes to `actor.currentView` signal using a `Signal.subtle.Watcher` inside a Vue component
|
|
106
|
-
2. Looks up component from `components` map using `view.component` string
|
|
107
|
-
3. Renders component with props from `view.props` + `send` function via Vue's dynamic `<component :is="..."/>`
|
|
108
|
-
|
|
109
|
-
**Example Component (LoginForm.vue):**
|
|
110
|
-
|
|
111
60
|
```vue
|
|
61
|
+
<!-- Login.vue — Vue SFC; useStateBinding works in <script setup> -->
|
|
112
62
|
<script setup lang="ts">
|
|
113
|
-
import
|
|
114
|
-
import {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}>();
|
|
120
|
-
|
|
121
|
-
const username = ref("");
|
|
122
|
-
|
|
123
|
-
function handleSubmit() {
|
|
124
|
-
props.send({
|
|
125
|
-
type: "auth.login",
|
|
126
|
-
username: username.value,
|
|
127
|
-
});
|
|
128
|
-
}
|
|
63
|
+
import { useStateBinding } from "@xmachines/play-vue";
|
|
64
|
+
import type { ComponentContext } from "@xmachines/play-vue";
|
|
65
|
+
import type { Catalog } from "./catalog.js";
|
|
66
|
+
|
|
67
|
+
const { props, emit, bindings } = defineProps<ComponentContext<Catalog, "Login">>();
|
|
68
|
+
const [username, setUsername] = useStateBinding<string>(bindings?.username ?? "/username");
|
|
129
69
|
</script>
|
|
130
70
|
|
|
131
71
|
<template>
|
|
132
|
-
<
|
|
133
|
-
<
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
72
|
+
<div class="view">
|
|
73
|
+
<h2>{{ props.title }}</h2>
|
|
74
|
+
<form @submit.prevent="emit('submit')">
|
|
75
|
+
<input id="username" v-model="username" @input="setUsername(username)" />
|
|
76
|
+
<button type="submit">Log In</button>
|
|
77
|
+
</form>
|
|
78
|
+
</div>
|
|
137
79
|
</template>
|
|
138
80
|
```
|
|
139
81
|
|
|
140
|
-
|
|
82
|
+
```ts
|
|
83
|
+
// registry.ts — pass SFCs directly; defineRegistry auto-wraps them
|
|
84
|
+
import { defineRegistry } from "@xmachines/play-vue";
|
|
85
|
+
import { catalog } from "./catalog.js";
|
|
86
|
+
import LoginSFC from "./Login.vue";
|
|
87
|
+
import DashboardSFC from "./Dashboard.vue";
|
|
88
|
+
|
|
89
|
+
export const { registry } = defineRegistry(catalog, {
|
|
90
|
+
components: { Login: LoginSFC, Dashboard: DashboardSFC },
|
|
91
|
+
actions: { login: async () => {}, logout: async () => {} },
|
|
92
|
+
});
|
|
93
|
+
```
|
|
141
94
|
|
|
142
|
-
|
|
95
|
+
```ts
|
|
96
|
+
// machine.ts
|
|
97
|
+
import { setup, assign } from "xstate";
|
|
98
|
+
import { formatPlayRouteTransitions } from "@xmachines/play-xstate";
|
|
99
|
+
|
|
100
|
+
export const machine = setup({
|
|
101
|
+
types: {
|
|
102
|
+
context: {} as {
|
|
103
|
+
isAuthenticated: boolean;
|
|
104
|
+
username: string | null;
|
|
105
|
+
routeParams: Record<string, string>;
|
|
106
|
+
queryParams: Record<string, string>;
|
|
107
|
+
},
|
|
108
|
+
events: {} as
|
|
109
|
+
| { type: "auth.login"; username: string }
|
|
110
|
+
| { type: "auth.logout" }
|
|
111
|
+
| { type: "play.route"; to: string; params?: Record<string, string> },
|
|
112
|
+
},
|
|
113
|
+
}).createMachine(
|
|
114
|
+
formatPlayRouteTransitions({
|
|
115
|
+
id: "app",
|
|
116
|
+
initial: "login",
|
|
117
|
+
context: { isAuthenticated: false, username: null, routeParams: {}, queryParams: {} },
|
|
118
|
+
states: {
|
|
119
|
+
login: {
|
|
120
|
+
id: "login",
|
|
121
|
+
meta: {
|
|
122
|
+
route: "/login",
|
|
123
|
+
view: {
|
|
124
|
+
component: "Login",
|
|
125
|
+
spec: {
|
|
126
|
+
root: "root",
|
|
127
|
+
elements: {
|
|
128
|
+
root: { type: "Login", props: { title: "Sign In" }, children: [] },
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
dashboard: {
|
|
135
|
+
id: "dashboard",
|
|
136
|
+
meta: {
|
|
137
|
+
route: "/dashboard",
|
|
138
|
+
view: {
|
|
139
|
+
component: "Dashboard",
|
|
140
|
+
spec: {
|
|
141
|
+
root: "root",
|
|
142
|
+
elements: {
|
|
143
|
+
root: { type: "Dashboard", props: { username: "" }, children: [] },
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
on: {
|
|
151
|
+
"auth.login": {
|
|
152
|
+
target: ".dashboard",
|
|
153
|
+
guard: ({ context }) => !context.isAuthenticated,
|
|
154
|
+
actions: assign({ isAuthenticated: true, username: ({ event }) => event.username }),
|
|
155
|
+
},
|
|
156
|
+
"auth.logout": {
|
|
157
|
+
target: ".login",
|
|
158
|
+
guard: ({ context }) => context.isAuthenticated,
|
|
159
|
+
actions: assign({ isAuthenticated: false, username: null }),
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
}),
|
|
163
|
+
);
|
|
164
|
+
```
|
|
143
165
|
|
|
144
166
|
```vue
|
|
145
167
|
<!-- App.vue -->
|
|
146
168
|
<script setup lang="ts">
|
|
147
|
-
import {
|
|
169
|
+
import { definePlayer } from "@xmachines/play-xstate";
|
|
148
170
|
import { PlayRenderer } from "@xmachines/play-vue";
|
|
149
|
-
import {
|
|
150
|
-
import
|
|
151
|
-
import Footer from "./components/Footer.vue";
|
|
171
|
+
import { machine } from "./machine.js";
|
|
172
|
+
import { registry } from "./registry.js";
|
|
152
173
|
|
|
153
|
-
|
|
154
|
-
|
|
174
|
+
const createPlayer = definePlayer({ machine });
|
|
175
|
+
const actor = createPlayer();
|
|
176
|
+
actor.start();
|
|
155
177
|
</script>
|
|
156
178
|
|
|
157
179
|
<template>
|
|
158
|
-
<
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<Footer />
|
|
164
|
-
</div>
|
|
165
|
-
</template>
|
|
166
|
-
</PlayVueRouterProvider>
|
|
180
|
+
<PlayRenderer
|
|
181
|
+
:actor="actor"
|
|
182
|
+
:registry="registry"
|
|
183
|
+
:actions="{ login: 'auth.login', logout: 'auth.logout' }"
|
|
184
|
+
/>
|
|
167
185
|
</template>
|
|
168
186
|
```
|
|
169
187
|
|
|
170
|
-
|
|
171
|
-
<!-- Header.vue -->
|
|
172
|
-
<script setup lang="ts">
|
|
173
|
-
import { inject, ref, onMounted, onUnmounted } from "vue";
|
|
174
|
-
import type { AbstractActor } from "@xmachines/play-actor";
|
|
175
|
-
|
|
176
|
-
const actor = inject<AbstractActor<any>>("actor")!;
|
|
177
|
-
const route = ref<string | null>(null);
|
|
178
|
-
|
|
179
|
-
let watcher: any;
|
|
180
|
-
|
|
181
|
-
onMounted(() => {
|
|
182
|
-
let pending = false;
|
|
183
|
-
watcher = new Signal.subtle.Watcher(() => {
|
|
184
|
-
if (!pending) {
|
|
185
|
-
pending = true;
|
|
186
|
-
queueMicrotask(() => {
|
|
187
|
-
pending = false;
|
|
188
|
-
for (const s of watcher.getPending()) s.get();
|
|
189
|
-
route.value = actor.currentRoute.get();
|
|
190
|
-
watcher.watch(actor.currentRoute);
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
route.value = actor.currentRoute.get();
|
|
195
|
-
watcher.watch(actor.currentRoute);
|
|
196
|
-
});
|
|
188
|
+
## API Reference
|
|
197
189
|
|
|
198
|
-
|
|
199
|
-
if (watcher) watcher.unwatch(actor.currentRoute);
|
|
200
|
-
});
|
|
201
|
-
</script>
|
|
190
|
+
### `PlayRenderer`
|
|
202
191
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
192
|
+
Main Vue component. Subscribes to `actor.currentView` and renders the spec.
|
|
193
|
+
|
|
194
|
+
```vue
|
|
195
|
+
<PlayRenderer
|
|
196
|
+
:actor="actor"
|
|
197
|
+
:registry="registry"
|
|
198
|
+
:actions="{ login: 'auth.login' }"
|
|
199
|
+
:store="myStore"
|
|
200
|
+
/>
|
|
208
201
|
```
|
|
209
202
|
|
|
210
|
-
|
|
203
|
+
**`actor`** — A `PlayerActor` (or any `AbstractActor & Viewable`). Provides the `currentView` signal.
|
|
211
204
|
|
|
212
|
-
|
|
205
|
+
**`registry`** — Built with `defineRegistry(catalog, { components, actions })` from `@xmachines/play-vue`. Pass `.vue` SFCs directly — they are auto-wrapped via `h(SFC, ctx)` so `useStateBinding` and other composables work inside `<script setup>`.
|
|
213
206
|
|
|
214
|
-
|
|
215
|
-
- No ref/reactive for business state
|
|
216
|
-
- No watch/watchEffect for business side effects
|
|
217
|
-
- Vue only triggers renders, doesn't control state
|
|
207
|
+
**`actions`** — Maps json-render action names (from spec `on` bindings) to XState event type strings. Type-checked against `EventFromLogic<TLogic>["type"]` when `TLogic` is specified.
|
|
218
208
|
|
|
219
|
-
|
|
220
|
-
- `actor.currentView.get()` provides UI structure
|
|
221
|
-
- `actor.currentRoute.get()` provides navigation state
|
|
222
|
-
- Components observe signals via explicit watcher patterns
|
|
209
|
+
**`store`** (optional) — Controls per-view UI state (`$state` bindings, form values):
|
|
223
210
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
- User actions send events to actor (e.g., `{ type: "auth.login" }`)
|
|
227
|
-
- Actor guards validate and process events
|
|
211
|
+
- **Omitted (uncontrolled, default):** A fresh `@xstate/store` atom is created per view transition, seeded from `view.spec.state`.
|
|
212
|
+
- **Provided (controlled):** The caller owns the store; `spec.state` is ignored.
|
|
228
213
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
214
|
+
```ts
|
|
215
|
+
import { createAtom } from "@xstate/store";
|
|
216
|
+
import { xstateStoreStateStore } from "@json-render/xstate";
|
|
217
|
+
import type { StateStore } from "@json-render/core";
|
|
233
218
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
- Do not rely on GC-only cleanup
|
|
219
|
+
const store: StateStore = xstateStoreStateStore({ atom: createAtom({ username: "" }) });
|
|
220
|
+
```
|
|
237
221
|
|
|
238
|
-
|
|
222
|
+
```vue
|
|
223
|
+
<PlayRenderer
|
|
224
|
+
:actor="actor"
|
|
225
|
+
:registry="registry"
|
|
226
|
+
:store="store"
|
|
227
|
+
:actions="{ login: 'auth.login' }"
|
|
228
|
+
/>
|
|
229
|
+
```
|
|
239
230
|
|
|
240
|
-
|
|
241
|
-
- Enables composition with navigation, headers, footers
|
|
242
|
-
- Supports multiple renderers in same app
|
|
231
|
+
---
|
|
243
232
|
|
|
244
|
-
|
|
233
|
+
### `useActor`
|
|
245
234
|
|
|
246
|
-
|
|
247
|
-
- **Passive Infrastructure (INV-04):** Components reflect, never decide
|
|
235
|
+
Vue composable for accessing the actor from inside any component rendered by `PlayRenderer`.
|
|
248
236
|
|
|
249
|
-
|
|
237
|
+
```ts
|
|
238
|
+
import { useActor } from "@xmachines/play-vue";
|
|
250
239
|
|
|
251
|
-
|
|
240
|
+
// Inside any component rendered inside PlayRenderer:
|
|
241
|
+
const actor = useActor();
|
|
242
|
+
actor.send({ type: "auth.logout" });
|
|
243
|
+
```
|
|
252
244
|
|
|
253
|
-
|
|
254
|
-
2. Schedule work with `queueMicrotask`
|
|
255
|
-
3. Drain `watcher.getPending()`
|
|
256
|
-
4. Read actor signals and update Vue-local ref state
|
|
257
|
-
5. Re-arm with `watch(...)` or `watch()`
|
|
245
|
+
Throws `"useActor() must be called inside <PlayRenderer>"` if called outside the tree.
|
|
258
246
|
|
|
259
|
-
|
|
247
|
+
---
|
|
260
248
|
|
|
261
|
-
##
|
|
249
|
+
## Route Parameters in Props
|
|
262
250
|
|
|
263
|
-
|
|
264
|
-
- **Type Safety:** Props validated against catalog schemas
|
|
265
|
-
- **Simple Testing:** Test actors without Vue renderer
|
|
266
|
-
- **Performance:** Microtask batching reduces unnecessary renders
|
|
267
|
-
- **Composability:** Renderer prop enables complex layouts
|
|
251
|
+
When using `formatPlayRouteTransitions`, URL path parameters flow automatically into component props. Declare an `undefined` slot in the spec to opt in:
|
|
268
252
|
|
|
269
|
-
|
|
253
|
+
```ts
|
|
254
|
+
// spec: { section: undefined, user: "alice" }
|
|
255
|
+
// After play.route to /settings/profile → context.routeParams = { section: "profile" }
|
|
256
|
+
// Component receives: { section: "profile", user: "alice" }
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Priority: **route param fills `undefined` slots; explicit non-`undefined` spec props always win.**
|
|
270
260
|
|
|
271
|
-
|
|
272
|
-
- **[@xmachines/play-catalog](../play-catalog/README.md)** - UI schema validation
|
|
273
|
-
- **[@xmachines/play-vue-router](../play-vue-router/README.md)** - Vue Router integration
|
|
274
|
-
- **[@xmachines/play-actor](../play-actor/README.md)** - Actor base
|
|
275
|
-
- **[@xmachines/play-signals](../play-signals/README.md)** - TC39 Signals primitives
|
|
261
|
+
---
|
|
276
262
|
|
|
277
|
-
##
|
|
263
|
+
## Architecture Notes
|
|
278
264
|
|
|
279
|
-
|
|
265
|
+
- Vue reactivity is only used to trigger re-renders — not for business logic
|
|
266
|
+
- `actor.currentView` (TC39 Signal) is bridged to Vue's reactive system inside `PlayRenderer`
|
|
267
|
+
- Per-view UI state lives in an `@xstate/store` atom, not in Vue reactive state
|
|
268
|
+
- `@json-render/vue` drives rendering; `PlayRenderer` is the signal bridge — import `defineRegistry`, `ComponentFn`, `ComponentContext`, and `useStateBinding` from `@xmachines/play-vue`
|
|
269
|
+
- 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 `useStateBinding` and Vue composables work correctly
|
|
280
270
|
|
|
281
|
-
|
|
282
|
-
For a copy, see <https://opensource.org/licenses/MIT>.
|
|
271
|
+
@xmachines/play-vue - Vue 3 renderer for XMachines Play architecture
|
|
283
272
|
|
|
284
|
-
|
|
273
|
+
Provides a thin Vue rendering layer that passively observes actor signals
|
|
274
|
+
and renders UI components via @json-render/vue. Vue reactivity is only used
|
|
275
|
+
to trigger re-renders — signals are the source of truth.
|
|
276
|
+
|
|
277
|
+
Re-exports `defineRegistry` (SFC-aware — auto-wraps `.vue` SFCs via `h()`),
|
|
278
|
+
`useStateBinding`, `ComponentFn`, and `ComponentContext` so consumers import
|
|
279
|
+
everything from `@xmachines/play-vue` rather than `@json-render/vue` directly.
|
|
285
280
|
|
|
286
281
|
## Interfaces
|
|
287
282
|
|
|
283
|
+
- [ComponentContext](interfaces/ComponentContext.md)
|
|
288
284
|
- [PlayRendererProps](interfaces/PlayRendererProps.md)
|
|
289
285
|
|
|
286
|
+
## Type Aliases
|
|
287
|
+
|
|
288
|
+
- [ComponentEntry](type-aliases/ComponentEntry.md)
|
|
289
|
+
- [ComponentFn](type-aliases/ComponentFn.md)
|
|
290
|
+
- [ComponentsMap](type-aliases/ComponentsMap.md)
|
|
291
|
+
- [DefineRegistryOptions](type-aliases/DefineRegistryOptions.md)
|
|
292
|
+
- [PlayActor](type-aliases/PlayActor.md)
|
|
293
|
+
|
|
290
294
|
## Variables
|
|
291
295
|
|
|
292
296
|
- [PlayRenderer](variables/PlayRenderer.md)
|
|
297
|
+
|
|
298
|
+
## Functions
|
|
299
|
+
|
|
300
|
+
- [defineRegistry](functions/defineRegistry.md)
|
|
301
|
+
- [useActor](functions/useActor.md)
|
|
302
|
+
- [useStateBinding](functions/useStateBinding.md)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[Documentation](../../../README.md) / [@xmachines/play-vue](../README.md) / defineRegistry
|
|
2
|
+
|
|
3
|
+
# Function: defineRegistry()
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
function defineRegistry<C>(catalog, options): DefineRegistryResult;
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Defined in: [packages/play-vue/src/define-registry.ts:114](https://gitlab.com/xmachin-es/xmachines-js/-/blob/v1.0.0-beta.18/packages/play-vue/src/define-registry.ts#L114)
|
|
10
|
+
|
|
11
|
+
Create a component registry, automatically wrapping `.vue` SFCs so they work
|
|
12
|
+
correctly with `@json-render/vue`'s rendering pipeline.
|
|
13
|
+
|
|
14
|
+
Drop-in replacement for `defineRegistry` from `@json-render/vue`. Import from
|
|
15
|
+
`@xmachines/play-vue` to get SFC support for free.
|
|
16
|
+
|
|
17
|
+
## Type Parameters
|
|
18
|
+
|
|
19
|
+
| Type Parameter |
|
|
20
|
+
| ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
21
|
+
| `C` _extends_ `Catalog`\<`SchemaDefinition`\<`SchemaType`\<`string`, `unknown`\>, `SchemaType`\<`string`, `unknown`\>\>, `unknown`\> |
|
|
22
|
+
|
|
23
|
+
## Parameters
|
|
24
|
+
|
|
25
|
+
| Parameter | Type | Description |
|
|
26
|
+
| --------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
27
|
+
| `catalog` | `C` | The json-render catalog defining component prop shapes. |
|
|
28
|
+
| `options` | [`DefineRegistryOptions`](../type-aliases/DefineRegistryOptions.md)\<`C`\> | Registry options. `components` entries may be `.vue` SFCs (objects) or plain `ComponentFn` functions — both are handled automatically. |
|
|
29
|
+
|
|
30
|
+
## Returns
|
|
31
|
+
|
|
32
|
+
`DefineRegistryResult`
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[Documentation](../../../README.md) / [@xmachines/play-vue](../README.md) / useActor
|
|
2
|
+
|
|
3
|
+
# Function: useActor()
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
function useActor(): PlayActor;
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Defined in: [packages/play-vue/src/useActor.ts:42](https://gitlab.com/xmachin-es/xmachines-js/-/blob/v1.0.0-beta.18/packages/play-vue/src/useActor.ts#L42)
|
|
10
|
+
|
|
11
|
+
## Returns
|
|
12
|
+
|
|
13
|
+
[`PlayActor`](../type-aliases/PlayActor.md)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[Documentation](../../../README.md) / [@xmachines/play-vue](../README.md) / useStateBinding
|
|
2
|
+
|
|
3
|
+
# Function: useStateBinding()
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
function useStateBinding<T>(path): [ComputedRef<T | undefined>, (value) => void];
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Composable to get and set a value from the state model by path.
|
|
10
|
+
|
|
11
|
+
This is the path-based variant for use in arbitrary composables. For
|
|
12
|
+
registry components that receive `bindings` from the renderer, prefer
|
|
13
|
+
`useBoundProp` which reads the already-resolved prop value and writes back
|
|
14
|
+
to the bound path.
|
|
15
|
+
|
|
16
|
+
## Type Parameters
|
|
17
|
+
|
|
18
|
+
| Type Parameter |
|
|
19
|
+
| -------------- |
|
|
20
|
+
| `T` |
|
|
21
|
+
|
|
22
|
+
## Parameters
|
|
23
|
+
|
|
24
|
+
| Parameter | Type |
|
|
25
|
+
| --------- | -------- |
|
|
26
|
+
| `path` | `string` |
|
|
27
|
+
|
|
28
|
+
## Returns
|
|
29
|
+
|
|
30
|
+
\[`ComputedRef`\<`T` \| `undefined`\>, (`value`) => `void`\]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[Documentation](../../../README.md) / [@xmachines/play-vue](../README.md) / ComponentContext
|
|
2
|
+
|
|
3
|
+
# Interface: ComponentContext\<C, K\>
|
|
4
|
+
|
|
5
|
+
Context passed to component render functions
|
|
6
|
+
|
|
7
|
+
## Example
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
const Button: ComponentFn<typeof catalog, "Button"> = (ctx) => {
|
|
11
|
+
return h("button", { onClick: () => ctx.emit("press") }, ctx.props.label);
|
|
12
|
+
};
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Extends
|
|
16
|
+
|
|
17
|
+
- `BaseComponentProps`\<`InferComponentProps`\<`C`, `K`\>\>
|
|
18
|
+
|
|
19
|
+
## Type Parameters
|
|
20
|
+
|
|
21
|
+
| Type Parameter |
|
|
22
|
+
| --------------------------------------------------- |
|
|
23
|
+
| `C` _extends_ `Catalog` |
|
|
24
|
+
| `K` _extends_ keyof `InferCatalogComponents`\<`C`\> |
|
|
25
|
+
|
|
26
|
+
## Properties
|
|
27
|
+
|
|
28
|
+
| Property | Type | Description | Inherited from | Defined in |
|
|
29
|
+
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | ---------- |
|
|
30
|
+
| <a id="property-bindings"></a> `bindings?` | `Record`\<`string`, `string`\> | Two-way binding paths resolved from `$bindState` / `$bindItem` expressions. Maps prop name → absolute state path for write-back. | `BaseComponentProps.bindings` | - |
|
|
31
|
+
| <a id="property-children"></a> `children?` | \| `VNode`\<`RendererNode`, `RendererElement`, \{ \[`key`: `string`\]: `any`; \}\> \| `VNode`\<`RendererNode`, `RendererElement`, \{ \[`key`: `string`\]: `any`; \}\>[] | Rendered children (from the default slot) | `BaseComponentProps.children` | - |
|
|
32
|
+
| <a id="property-emit"></a> `emit` | (`event`) => `void` | Simple event emitter (shorthand). Fires the event and returns void. | `BaseComponentProps.emit` | - |
|
|
33
|
+
| <a id="property-loading"></a> `loading?` | `boolean` | - | `BaseComponentProps.loading` | - |
|
|
34
|
+
| <a id="property-on"></a> `on` | (`event`) => `EventHandle` | Get an event handle with metadata. Use when you need shouldPreventDefault or bound checks. | `BaseComponentProps.on` | - |
|
|
35
|
+
| <a id="property-props"></a> `props` | `InferComponentProps` | - | `BaseComponentProps.props` | - |
|