@xmachines/play-react 1.0.0-beta.4 → 1.0.0-beta.40
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 +300 -260
- package/dist/ActorProvider.d.ts +82 -0
- package/dist/ActorProvider.d.ts.map +1 -0
- package/dist/ActorProvider.js +167 -0
- package/dist/ActorProvider.js.map +1 -0
- package/dist/PlayErrorBoundary.d.ts +55 -0
- package/dist/PlayErrorBoundary.d.ts.map +1 -0
- package/dist/PlayErrorBoundary.js +45 -0
- package/dist/PlayErrorBoundary.js.map +1 -0
- package/dist/PlayRenderer.d.ts +26 -47
- package/dist/PlayRenderer.d.ts.map +1 -1
- package/dist/PlayRenderer.js +31 -76
- package/dist/PlayRenderer.js.map +1 -1
- package/dist/PlayUIProvider.d.ts +67 -0
- package/dist/PlayUIProvider.d.ts.map +1 -0
- package/dist/PlayUIProvider.js +73 -0
- package/dist/PlayUIProvider.js.map +1 -0
- package/dist/errors.d.ts +23 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +26 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +31 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +6 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -1
- package/dist/useActor.d.ts +26 -0
- package/dist/useActor.d.ts.map +1 -0
- package/dist/useActor.js +27 -0
- package/dist/useActor.js.map +1 -0
- package/dist/useSignalEffect.d.ts +6 -0
- package/dist/useSignalEffect.d.ts.map +1 -1
- package/dist/useSignalEffect.js +36 -19
- package/dist/useSignalEffect.js.map +1 -1
- package/package.json +32 -16
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ActorProvider — escape hatch primitive for actor lifecycle management.
|
|
3
|
+
*
|
|
4
|
+
* Owns: actor bridging, signal subscription (useSignalEffect), per-view StateStore
|
|
5
|
+
* lifecycle (controlled/uncontrolled), handler resolution via inner component pattern
|
|
6
|
+
* (uses useStateStore()), StateProvider wrap, PlayErrorBoundary wrap, onRenderError injection.
|
|
7
|
+
*
|
|
8
|
+
* Standard usage: prefer <PlayUIProvider> unless you need to compose providers manually.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
import React from "react";
|
|
13
|
+
import type { DefineRegistryResult, ComponentRegistry } from "@json-render/react";
|
|
14
|
+
import type { BaseActorProviderProps, BaseViewContextValue } from "@xmachines/play-actor";
|
|
15
|
+
/**
|
|
16
|
+
* Props for the ActorProvider component.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export interface ActorProviderProps extends BaseActorProviderProps<DefineRegistryResult> {
|
|
21
|
+
/** Optional component shown when currentView is null or a catalog component throws */
|
|
22
|
+
fallback?: React.ReactNode;
|
|
23
|
+
/** Optional error handler callback invoked when a catalog component throws during render */
|
|
24
|
+
onError?: (error: Error, info: React.ErrorInfo) => void;
|
|
25
|
+
/** Child components to render inside the provider tree */
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Value provided by ViewContext (accessible via usePlayView()).
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export interface ViewContextValue extends BaseViewContextValue<ComponentRegistry> {
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Hook to access the current view spec, handlers, and registry.
|
|
37
|
+
*
|
|
38
|
+
* Must be called inside <ActorProvider> or <PlayUIProvider>.
|
|
39
|
+
*
|
|
40
|
+
* @throws {Error} If called outside an ActorProvider/PlayUIProvider tree
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* import { usePlayView } from "@xmachines/play-react";
|
|
45
|
+
*
|
|
46
|
+
* function MyRenderer() {
|
|
47
|
+
* const view = usePlayView();
|
|
48
|
+
* return <Renderer spec={view.spec} registry={view.registry} />;
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
export declare function usePlayView(): ViewContextValue;
|
|
55
|
+
/**
|
|
56
|
+
* ActorProvider — escape hatch primitive for composing actor lifecycle with custom providers.
|
|
57
|
+
*
|
|
58
|
+
* Subscribes to actor.currentView signal, manages the per-view StateStore lifecycle,
|
|
59
|
+
* wraps children in StateProvider and PlayErrorBoundary, and injects onRenderError
|
|
60
|
+
* into the component registry.
|
|
61
|
+
*
|
|
62
|
+
* Standard usage: prefer <PlayUIProvider> unless you need to compose providers manually.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```tsx
|
|
66
|
+
* // Custom composition (escape hatch):
|
|
67
|
+
* <ActorProvider actor={actor} registryResult={registryResult}>
|
|
68
|
+
* <JSONUIProvider registry={registryResult.registry}>
|
|
69
|
+
* <PlayRenderer />
|
|
70
|
+
* </JSONUIProvider>
|
|
71
|
+
* </ActorProvider>
|
|
72
|
+
*
|
|
73
|
+
* // Standard usage: prefer PlayUIProvider
|
|
74
|
+
* <PlayUIProvider actor={actor} registryResult={registryResult}>
|
|
75
|
+
* <PlayRenderer />
|
|
76
|
+
* </PlayUIProvider>
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
export declare const ActorProvider: React.FC<ActorProviderProps>;
|
|
82
|
+
//# sourceMappingURL=ActorProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActorProvider.d.ts","sourceRoot":"","sources":["../src/ActorProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAsD,MAAM,OAAO,CAAC;AAE3E,OAAO,KAAK,EAAE,oBAAoB,EAAY,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAO5F,OAAO,KAAK,EAAY,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAIpG;;;;GAIG;AACH,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB,CAAC,oBAAoB,CAAC;IACvF,sFAAsF;IACtF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;IACxD,0DAA0D;IAC1D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;CAAG;AAQpF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,IAAI,gBAAgB,CAE9C;AAmDD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA0FtD,CAAC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* ActorProvider — escape hatch primitive for actor lifecycle management.
|
|
4
|
+
*
|
|
5
|
+
* Owns: actor bridging, signal subscription (useSignalEffect), per-view StateStore
|
|
6
|
+
* lifecycle (controlled/uncontrolled), handler resolution via inner component pattern
|
|
7
|
+
* (uses useStateStore()), StateProvider wrap, PlayErrorBoundary wrap, onRenderError injection.
|
|
8
|
+
*
|
|
9
|
+
* Standard usage: prefer <PlayUIProvider> unless you need to compose providers manually.
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
import React, { useState, useRef, createContext, useContext } from "react";
|
|
14
|
+
import { StateProvider, useStateStore } from "@json-render/react";
|
|
15
|
+
import { createAtom } from "@xstate/store";
|
|
16
|
+
import { xstateStoreStateStore } from "@json-render/xstate";
|
|
17
|
+
import { useSignalEffect } from "./useSignalEffect.js";
|
|
18
|
+
import { PlayErrorBoundary } from "./PlayErrorBoundary.js";
|
|
19
|
+
import { assertNonNullable } from "@xmachines/play";
|
|
20
|
+
import { ActorContext } from "./useActor.js";
|
|
21
|
+
/**
|
|
22
|
+
* Internal React context for ViewContextValue.
|
|
23
|
+
* Accessed via usePlayView() hook.
|
|
24
|
+
*/
|
|
25
|
+
const ViewContext = createContext(null);
|
|
26
|
+
/**
|
|
27
|
+
* Hook to access the current view spec, handlers, and registry.
|
|
28
|
+
*
|
|
29
|
+
* Must be called inside <ActorProvider> or <PlayUIProvider>.
|
|
30
|
+
*
|
|
31
|
+
* @throws {Error} If called outside an ActorProvider/PlayUIProvider tree
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* import { usePlayView } from "@xmachines/play-react";
|
|
36
|
+
*
|
|
37
|
+
* function MyRenderer() {
|
|
38
|
+
* const view = usePlayView();
|
|
39
|
+
* return <Renderer spec={view.spec} registry={view.registry} />;
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export function usePlayView() {
|
|
46
|
+
return assertNonNullable(useContext(ViewContext), "ViewContext");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create a StateStore backed by a fresh @xstate/store atom seeded from the given state.
|
|
50
|
+
* Called internally per view transition when no external store prop is provided.
|
|
51
|
+
*/
|
|
52
|
+
function createViewStore(initialState) {
|
|
53
|
+
return xstateStoreStateStore({ atom: createAtom(initialState) });
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Inner component that runs inside StateProvider so it can access StateStore context
|
|
57
|
+
* via useStateStore(). Resolves action handlers from registryResult.handlers() using
|
|
58
|
+
* the live StateProvider set/getSnapshot functions, then exposes them via ViewContext.
|
|
59
|
+
*/
|
|
60
|
+
function ActorProviderInner({ registryResult, spec, store, children, }) {
|
|
61
|
+
const stateCtx = useStateStore();
|
|
62
|
+
// Build a SetState adapter: the handlers factory expects an updater-function pattern
|
|
63
|
+
// ((prev) => next), while stateCtx provides path-based set/update. This adapter
|
|
64
|
+
// bridges the two so action functions can use setState if needed.
|
|
65
|
+
const setStateAdapter = (updater) => {
|
|
66
|
+
const prev = stateCtx.getSnapshot();
|
|
67
|
+
stateCtx.update(updater(prev));
|
|
68
|
+
};
|
|
69
|
+
const handlers = registryResult.handlers(() => setStateAdapter, () => stateCtx.getSnapshot());
|
|
70
|
+
const viewValue = {
|
|
71
|
+
spec,
|
|
72
|
+
handlers,
|
|
73
|
+
registry: registryResult.registry,
|
|
74
|
+
store,
|
|
75
|
+
};
|
|
76
|
+
return _jsx(ViewContext.Provider, { value: viewValue, children: children });
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* ActorProvider — escape hatch primitive for composing actor lifecycle with custom providers.
|
|
80
|
+
*
|
|
81
|
+
* Subscribes to actor.currentView signal, manages the per-view StateStore lifecycle,
|
|
82
|
+
* wraps children in StateProvider and PlayErrorBoundary, and injects onRenderError
|
|
83
|
+
* into the component registry.
|
|
84
|
+
*
|
|
85
|
+
* Standard usage: prefer <PlayUIProvider> unless you need to compose providers manually.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```tsx
|
|
89
|
+
* // Custom composition (escape hatch):
|
|
90
|
+
* <ActorProvider actor={actor} registryResult={registryResult}>
|
|
91
|
+
* <JSONUIProvider registry={registryResult.registry}>
|
|
92
|
+
* <PlayRenderer />
|
|
93
|
+
* </JSONUIProvider>
|
|
94
|
+
* </ActorProvider>
|
|
95
|
+
*
|
|
96
|
+
* // Standard usage: prefer PlayUIProvider
|
|
97
|
+
* <PlayUIProvider actor={actor} registryResult={registryResult}>
|
|
98
|
+
* <PlayRenderer />
|
|
99
|
+
* </PlayUIProvider>
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @public
|
|
103
|
+
*/
|
|
104
|
+
export const ActorProvider = ({ actor, registryResult, store: externalStore, fallback = null, onError, onRenderError, children, }) => {
|
|
105
|
+
// React state for triggering re-renders (NOT business logic state)
|
|
106
|
+
// Signal is source of truth, useState is just React's render trigger
|
|
107
|
+
const [view, setView] = useState(() => actor.currentView.get());
|
|
108
|
+
// Internal store ref — tracks the current per-view atom store.
|
|
109
|
+
// Keyed to view identity: recreated whenever the view changes (new spec.state seed).
|
|
110
|
+
// Ignored when externalStore is provided.
|
|
111
|
+
const internalStoreRef = useRef(null);
|
|
112
|
+
const lastViewRef = useRef(null);
|
|
113
|
+
// Subscribe to signal changes
|
|
114
|
+
useSignalEffect(() => {
|
|
115
|
+
const currentView = actor.currentView.get();
|
|
116
|
+
setView(currentView);
|
|
117
|
+
});
|
|
118
|
+
// Inject onRenderError prop into registry (non-enumerable, overrides defineRegistry-level handler)
|
|
119
|
+
// Centralised here per D-19 — one location for all framework renderers
|
|
120
|
+
const activeRegistryResult = onRenderError
|
|
121
|
+
? {
|
|
122
|
+
...registryResult,
|
|
123
|
+
registry: (() => {
|
|
124
|
+
const r = { ...registryResult.registry };
|
|
125
|
+
Object.defineProperty(r, "onRenderError", {
|
|
126
|
+
value: onRenderError,
|
|
127
|
+
enumerable: false,
|
|
128
|
+
configurable: true,
|
|
129
|
+
});
|
|
130
|
+
return r;
|
|
131
|
+
})(),
|
|
132
|
+
}
|
|
133
|
+
: registryResult;
|
|
134
|
+
// No view in current state — render fallback
|
|
135
|
+
if (!view) {
|
|
136
|
+
return _jsx(_Fragment, { children: fallback });
|
|
137
|
+
}
|
|
138
|
+
// Resolve the store to use for StateProvider:
|
|
139
|
+
// - External (controlled): use as-is, caller manages lifecycle
|
|
140
|
+
// - Internal: create a fresh atom when the view changes (new route/state)
|
|
141
|
+
let store;
|
|
142
|
+
if (externalStore) {
|
|
143
|
+
store = externalStore;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Recreate the internal store when the view identity changes
|
|
147
|
+
// (view is a new object on every transition per deriveCurrentView)
|
|
148
|
+
if (internalStoreRef.current === null || lastViewRef.current !== view) {
|
|
149
|
+
// Proto-safe guard (T-37-03-01): prevents Date/Array/class-instance from being
|
|
150
|
+
// passed to createAtom. Replaces the weak `?? {}` guard from old code_context.
|
|
151
|
+
const rawState = view.state;
|
|
152
|
+
const initialState = rawState !== null &&
|
|
153
|
+
rawState !== undefined &&
|
|
154
|
+
typeof rawState === "object" &&
|
|
155
|
+
!Array.isArray(rawState) &&
|
|
156
|
+
(Object.getPrototypeOf(rawState) === Object.prototype ||
|
|
157
|
+
Object.getPrototypeOf(rawState) === null)
|
|
158
|
+
? rawState
|
|
159
|
+
: {};
|
|
160
|
+
internalStoreRef.current = createViewStore(initialState);
|
|
161
|
+
lastViewRef.current = view;
|
|
162
|
+
}
|
|
163
|
+
store = internalStoreRef.current;
|
|
164
|
+
}
|
|
165
|
+
return (_jsx(ActorContext.Provider, { value: actor, children: _jsx(PlayErrorBoundary, { fallback: fallback, ...(onError && { onError }), children: _jsx(StateProvider, { store: store, children: _jsx(ActorProviderInner, { registryResult: activeRegistryResult, spec: view, store: store, children: children }) }) }) }));
|
|
166
|
+
};
|
|
167
|
+
//# sourceMappingURL=ActorProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActorProvider.js","sourceRoot":"","sources":["../src/ActorProvider.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGlE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD,OAAO,EAAE,YAAY,EAAkB,MAAM,eAAe,CAAC;AAuB7D;;;GAGG;AACH,MAAM,WAAW,GAAG,aAAa,CAA0B,IAAI,CAAC,CAAC;AAEjE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,WAAW;IAC1B,OAAO,iBAAiB,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,YAAqC;IAC7D,OAAO,qBAAqB,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,EAC3B,cAAc,EACd,IAAI,EACJ,KAAK,EACL,QAAQ,GAMR;IACA,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IAEjC,qFAAqF;IACrF,gFAAgF;IAChF,kEAAkE;IAClE,MAAM,eAAe,GAAa,CAAC,OAAO,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QACpC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAkC,cAAc,CAAC,QAAQ,CACtE,GAAG,EAAE,CAAC,eAAe,EACrB,GAAG,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,CAC5B,CAAC;IAEF,MAAM,SAAS,GAAqB;QACnC,IAAI;QACJ,QAAQ;QACR,QAAQ,EAAE,cAAc,CAAC,QAAQ;QACjC,KAAK;KACL,CAAC;IAEF,OAAO,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,SAAS,YAAG,QAAQ,GAAwB,CAAC;AAClF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAiC,CAAC,EAC3D,KAAK,EACL,cAAc,EACd,KAAK,EAAE,aAAa,EACpB,QAAQ,GAAG,IAAI,EACf,OAAO,EACP,aAAa,EACb,QAAQ,GACR,EAAE,EAAE;IACJ,mEAAmE;IACnE,qEAAqE;IACrE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAkB,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;IAEjF,+DAA+D;IAC/D,qFAAqF;IACrF,0CAA0C;IAC1C,MAAM,gBAAgB,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAC;IAElD,8BAA8B;IAC9B,eAAe,CAAC,GAAG,EAAE;QACpB,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;QAC5C,OAAO,CAAC,WAAW,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,mGAAmG;IACnG,uEAAuE;IACvE,MAAM,oBAAoB,GAAG,aAAa;QACzC,CAAC,CAAC;YACA,GAAG,cAAc;YACjB,QAAQ,EAAE,CAAC,GAAG,EAAE;gBACf,MAAM,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;gBACzC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,eAAe,EAAE;oBACzC,KAAK,EAAE,aAAa;oBACpB,UAAU,EAAE,KAAK;oBACjB,YAAY,EAAE,IAAI;iBAClB,CAAC,CAAC;gBACH,OAAO,CAAC,CAAC;YACV,CAAC,CAAC,EAAE;SACJ;QACF,CAAC,CAAC,cAAc,CAAC;IAElB,6CAA6C;IAC7C,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,OAAO,4BAAG,QAAQ,GAAI,CAAC;IACxB,CAAC;IAED,8CAA8C;IAC9C,+DAA+D;IAC/D,0EAA0E;IAC1E,IAAI,KAAiB,CAAC;IACtB,IAAI,aAAa,EAAE,CAAC;QACnB,KAAK,GAAG,aAAa,CAAC;IACvB,CAAC;SAAM,CAAC;QACP,6DAA6D;QAC7D,mEAAmE;QACnE,IAAI,gBAAgB,CAAC,OAAO,KAAK,IAAI,IAAI,WAAW,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YACvE,+EAA+E;YAC/E,+EAA+E;YAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;YAC5B,MAAM,YAAY,GACjB,QAAQ,KAAK,IAAI;gBACjB,QAAQ,KAAK,SAAS;gBACtB,OAAO,QAAQ,KAAK,QAAQ;gBAC5B,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACxB,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,MAAM,CAAC,SAAS;oBACpD,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;gBACzC,CAAC,CAAE,QAAoC;gBACvC,CAAC,CAAC,EAAE,CAAC;YACP,gBAAgB,CAAC,OAAO,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;YACzD,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC;QACD,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC;IAClC,CAAC;IAED,OAAO,CACN,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAkB,YAC/C,KAAC,iBAAiB,IAAC,QAAQ,EAAE,QAAQ,KAAM,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC,YAClE,KAAC,aAAa,IAAC,KAAK,EAAE,KAAK,YAC1B,KAAC,kBAAkB,IAClB,cAAc,EAAE,oBAAoB,EACpC,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,YAEX,QAAQ,GACW,GACN,GACG,GACG,CACxB,CAAC;AACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlayErrorBoundary - React error boundary for catching catalog component render errors
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import React from "react";
|
|
7
|
+
/**
|
|
8
|
+
* Props for PlayErrorBoundary
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export interface PlayErrorBoundaryProps {
|
|
13
|
+
/** Fallback UI to render when a child component throws. Defaults to null. */
|
|
14
|
+
fallback?: React.ReactNode;
|
|
15
|
+
/** Child components to render */
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
/** Optional error handler callback — forwards errors to observability tools (Sentry, etc.) */
|
|
18
|
+
onError?: (error: Error, info: React.ErrorInfo) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Internal state shape for PlayErrorBoundary
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export interface PlayErrorBoundaryState {
|
|
26
|
+
hasError: boolean;
|
|
27
|
+
error: Error | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* React class component error boundary for catching catalog component render errors.
|
|
31
|
+
*
|
|
32
|
+
* Wraps catalog component renders so failures are caught and forwarded to standard
|
|
33
|
+
* React error boundary protocol. Consumers can attach the `onError` prop to forward
|
|
34
|
+
* errors to production observability tools (Sentry, Datadog, etc.).
|
|
35
|
+
*
|
|
36
|
+
* **React 19 safety (Phase 29):** `componentDidCatch` calls `onError` for observability
|
|
37
|
+
* but does NOT re-throw. `getDerivedStateFromError` already sets the fallback state —
|
|
38
|
+
* re-throwing from `componentDidCatch` can unmount the entire React 19 root.
|
|
39
|
+
*
|
|
40
|
+
* Per CONS-14: Class component pattern works with all React versions (18 and 19).
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* <PlayErrorBoundary fallback={<div>Something went wrong</div>} onError={Sentry.captureException}>
|
|
45
|
+
* <CatalogComponent {...props} />
|
|
46
|
+
* </PlayErrorBoundary>
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare class PlayErrorBoundary extends React.Component<PlayErrorBoundaryProps, PlayErrorBoundaryState> {
|
|
50
|
+
constructor(props: PlayErrorBoundaryProps);
|
|
51
|
+
static getDerivedStateFromError(error: Error): PlayErrorBoundaryState;
|
|
52
|
+
componentDidCatch(error: Error, info: React.ErrorInfo): void;
|
|
53
|
+
render(): React.ReactNode;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=PlayErrorBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlayErrorBoundary.d.ts","sourceRoot":"","sources":["../src/PlayErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,iCAAiC;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,8FAA8F;IAC9F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,iBAAkB,SAAQ,KAAK,CAAC,SAAS,CACrD,sBAAsB,EACtB,sBAAsB,CACtB;gBACY,KAAK,EAAE,sBAAsB;IAKzC,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,sBAAsB;IAI5D,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI;IAI5D,MAAM,IAAI,KAAK,CAAC,SAAS;CAMlC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlayErrorBoundary - React error boundary for catching catalog component render errors
|
|
3
|
+
*
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
import React from "react";
|
|
7
|
+
/**
|
|
8
|
+
* React class component error boundary for catching catalog component render errors.
|
|
9
|
+
*
|
|
10
|
+
* Wraps catalog component renders so failures are caught and forwarded to standard
|
|
11
|
+
* React error boundary protocol. Consumers can attach the `onError` prop to forward
|
|
12
|
+
* errors to production observability tools (Sentry, Datadog, etc.).
|
|
13
|
+
*
|
|
14
|
+
* **React 19 safety (Phase 29):** `componentDidCatch` calls `onError` for observability
|
|
15
|
+
* but does NOT re-throw. `getDerivedStateFromError` already sets the fallback state —
|
|
16
|
+
* re-throwing from `componentDidCatch` can unmount the entire React 19 root.
|
|
17
|
+
*
|
|
18
|
+
* Per CONS-14: Class component pattern works with all React versions (18 and 19).
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* <PlayErrorBoundary fallback={<div>Something went wrong</div>} onError={Sentry.captureException}>
|
|
23
|
+
* <CatalogComponent {...props} />
|
|
24
|
+
* </PlayErrorBoundary>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class PlayErrorBoundary extends React.Component {
|
|
28
|
+
constructor(props) {
|
|
29
|
+
super(props);
|
|
30
|
+
this.state = { hasError: false, error: null };
|
|
31
|
+
}
|
|
32
|
+
static getDerivedStateFromError(error) {
|
|
33
|
+
return { hasError: true, error };
|
|
34
|
+
}
|
|
35
|
+
componentDidCatch(error, info) {
|
|
36
|
+
this.props.onError?.(error, info);
|
|
37
|
+
}
|
|
38
|
+
render() {
|
|
39
|
+
if (this.state.hasError) {
|
|
40
|
+
return this.props.fallback ?? null;
|
|
41
|
+
}
|
|
42
|
+
return this.props.children;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=PlayErrorBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlayErrorBoundary.js","sourceRoot":"","sources":["../src/PlayErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AA0B1B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,iBAAkB,SAAQ,KAAK,CAAC,SAG5C;IACA,YAAY,KAA6B;QACxC,KAAK,CAAC,KAAK,CAAC,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC3C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAClC,CAAC;IAEQ,iBAAiB,CAAC,KAAY,EAAE,IAAqB;QAC7D,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAEQ,MAAM;QACd,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAC;QACpC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC5B,CAAC;CACD"}
|
package/dist/PlayRenderer.d.ts
CHANGED
|
@@ -1,57 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PlayRenderer -
|
|
2
|
+
* PlayRenderer — zero-prop leaf component for rendering the current actor view.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import type { PlayRendererProps } from "./types.js";
|
|
8
|
-
/**
|
|
9
|
-
* Main renderer component that subscribes to actor signals and renders UI
|
|
10
|
-
*
|
|
11
|
-
* Architecture (per RESEARCH.md Pattern 1):
|
|
12
|
-
* - Subscribes to actor.currentView signal via useSignalEffect
|
|
13
|
-
* - Dynamically renders catalog components based on view.component string
|
|
14
|
-
* - Forwards user events to actor via actor.send()
|
|
15
|
-
* - React state only for triggering renders, NOT business logic
|
|
16
|
-
*
|
|
17
|
-
* Invariant: Actor Authority - Actor decides all state transitions via guards.
|
|
18
|
-
* Invariant: Passive Infrastructure - Component observes signals and sends events.
|
|
19
|
-
* Invariant: Signal-Only Reactivity - Business logic state lives in actor signals.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* import { PlayRenderer } from "@xmachines/play-react";
|
|
24
|
-
* import { definePlayer } from "@xmachines/play-xstate";
|
|
25
|
-
*
|
|
26
|
-
* const actor = definePlayer({ machine, catalog })();
|
|
27
|
-
* actor.start();
|
|
4
|
+
* Must be rendered inside <ActorProvider> or <PlayUIProvider>.
|
|
5
|
+
* Reads view spec, handlers, and registry from usePlayView() context,
|
|
6
|
+
* then delegates to @json-render/react Renderer.
|
|
28
7
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* }}>...</form>
|
|
35
|
-
* };
|
|
36
|
-
*
|
|
37
|
-
* <PlayRenderer actor={actor} components={components} />
|
|
8
|
+
* Standard usage:
|
|
9
|
+
* ```tsx
|
|
10
|
+
* <PlayUIProvider actor={actor} registryResult={registryResult}>
|
|
11
|
+
* <PlayRenderer />
|
|
12
|
+
* </PlayUIProvider>
|
|
38
13
|
* ```
|
|
39
14
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
15
|
+
* For custom provider composition, use <ActorProvider> (escape hatch):
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <ActorProvider actor={actor} registryResult={registryResult}>
|
|
18
|
+
* <JSONUIProvider registry={registryResult.registry}>
|
|
19
|
+
* <PlayRenderer />
|
|
20
|
+
* </JSONUIProvider>
|
|
21
|
+
* </ActorProvider>
|
|
22
|
+
* ```
|
|
46
23
|
*
|
|
47
|
-
*
|
|
48
|
-
|
|
24
|
+
* @packageDocumentation
|
|
25
|
+
*/
|
|
26
|
+
import React from "react";
|
|
27
|
+
/**
|
|
28
|
+
* Zero-prop leaf component that renders the current actor view.
|
|
49
29
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
30
|
+
* Reads the current PlaySpec, handlers, and registry from the ActorProvider
|
|
31
|
+
* context via usePlayView(), then renders via @json-render/react Renderer.
|
|
52
32
|
*
|
|
53
|
-
*
|
|
54
|
-
* Calling send during render causes infinite render loops.
|
|
33
|
+
* @public
|
|
55
34
|
*/
|
|
56
|
-
export declare const PlayRenderer: React.FC<
|
|
35
|
+
export declare const PlayRenderer: React.FC<Record<string, never>>;
|
|
57
36
|
//# sourceMappingURL=PlayRenderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlayRenderer.d.ts","sourceRoot":"","sources":["../src/PlayRenderer.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"PlayRenderer.d.ts","sourceRoot":"","sources":["../src/PlayRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAGxD,CAAC"}
|
package/dist/PlayRenderer.js
CHANGED
|
@@ -1,87 +1,42 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
|
-
* PlayRenderer -
|
|
3
|
+
* PlayRenderer — zero-prop leaf component for rendering the current actor view.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import { useSignalEffect } from "./useSignalEffect.js";
|
|
9
|
-
/**
|
|
10
|
-
* Main renderer component that subscribes to actor signals and renders UI
|
|
11
|
-
*
|
|
12
|
-
* Architecture (per RESEARCH.md Pattern 1):
|
|
13
|
-
* - Subscribes to actor.currentView signal via useSignalEffect
|
|
14
|
-
* - Dynamically renders catalog components based on view.component string
|
|
15
|
-
* - Forwards user events to actor via actor.send()
|
|
16
|
-
* - React state only for triggering renders, NOT business logic
|
|
17
|
-
*
|
|
18
|
-
* Invariant: Actor Authority - Actor decides all state transitions via guards.
|
|
19
|
-
* Invariant: Passive Infrastructure - Component observes signals and sends events.
|
|
20
|
-
* Invariant: Signal-Only Reactivity - Business logic state lives in actor signals.
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```typescript
|
|
24
|
-
* import { PlayRenderer } from "@xmachines/play-react";
|
|
25
|
-
* import { definePlayer } from "@xmachines/play-xstate";
|
|
26
|
-
*
|
|
27
|
-
* const actor = definePlayer({ machine, catalog })();
|
|
28
|
-
* actor.start();
|
|
5
|
+
* Must be rendered inside <ActorProvider> or <PlayUIProvider>.
|
|
6
|
+
* Reads view spec, handlers, and registry from usePlayView() context,
|
|
7
|
+
* then delegates to @json-render/react Renderer.
|
|
29
8
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* }}>...</form>
|
|
36
|
-
* };
|
|
37
|
-
*
|
|
38
|
-
* <PlayRenderer actor={actor} components={components} />
|
|
9
|
+
* Standard usage:
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <PlayUIProvider actor={actor} registryResult={registryResult}>
|
|
12
|
+
* <PlayRenderer />
|
|
13
|
+
* </PlayUIProvider>
|
|
39
14
|
* ```
|
|
40
15
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
16
|
+
* For custom provider composition, use <ActorProvider> (escape hatch):
|
|
17
|
+
* ```tsx
|
|
18
|
+
* <ActorProvider actor={actor} registryResult={registryResult}>
|
|
19
|
+
* <JSONUIProvider registry={registryResult.registry}>
|
|
20
|
+
* <PlayRenderer />
|
|
21
|
+
* </JSONUIProvider>
|
|
22
|
+
* </ActorProvider>
|
|
23
|
+
* ```
|
|
47
24
|
*
|
|
48
|
-
*
|
|
49
|
-
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
import React from "react";
|
|
28
|
+
import { Renderer } from "@json-render/react";
|
|
29
|
+
import { usePlayView } from "./ActorProvider.js";
|
|
30
|
+
/**
|
|
31
|
+
* Zero-prop leaf component that renders the current actor view.
|
|
50
32
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
33
|
+
* Reads the current PlaySpec, handlers, and registry from the ActorProvider
|
|
34
|
+
* context via usePlayView(), then renders via @json-render/react Renderer.
|
|
53
35
|
*
|
|
54
|
-
*
|
|
55
|
-
* Calling send during render causes infinite render loops.
|
|
36
|
+
* @public
|
|
56
37
|
*/
|
|
57
|
-
export const PlayRenderer = (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const [view, setView] = useState(() => actor.currentView.get());
|
|
61
|
-
// Subscribe to signal changes
|
|
62
|
-
useSignalEffect(() => {
|
|
63
|
-
const currentView = actor.currentView.get();
|
|
64
|
-
setView(currentView);
|
|
65
|
-
});
|
|
66
|
-
// No view in current state
|
|
67
|
-
if (!view) {
|
|
68
|
-
return _jsx(_Fragment, { children: fallback });
|
|
69
|
-
}
|
|
70
|
-
// Handle null/undefined components catalog gracefully
|
|
71
|
-
if (!components) {
|
|
72
|
-
console.error(`Components catalog is ${components === null ? "null" : "undefined"}. ` +
|
|
73
|
-
`Cannot render component "${view.component}".`);
|
|
74
|
-
return _jsx(_Fragment, { children: fallback });
|
|
75
|
-
}
|
|
76
|
-
// Look up component from catalog
|
|
77
|
-
const Component = components[view.component];
|
|
78
|
-
if (!Component) {
|
|
79
|
-
console.error(`Component "${view.component}" not found in catalog. ` +
|
|
80
|
-
`Available components: ${Object.keys(components).join(", ")}`);
|
|
81
|
-
return _jsx(_Fragment, { children: fallback });
|
|
82
|
-
}
|
|
83
|
-
// Render with props from actor + send function
|
|
84
|
-
// bind(actor) ensures 'this' context is correct when components call send()
|
|
85
|
-
return _jsx(Component, { ...view.props, send: actor.send.bind(actor) });
|
|
38
|
+
export const PlayRenderer = () => {
|
|
39
|
+
const view = usePlayView();
|
|
40
|
+
return _jsx(Renderer, { spec: view.spec, registry: view.registry });
|
|
86
41
|
};
|
|
87
42
|
//# sourceMappingURL=PlayRenderer.js.map
|
package/dist/PlayRenderer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlayRenderer.js","sourceRoot":"","sources":["../src/PlayRenderer.tsx"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"PlayRenderer.js","sourceRoot":"","sources":["../src/PlayRenderer.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAoC,GAAG,EAAE;IACjE,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,OAAO,KAAC,QAAQ,IAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAI,CAAC;AAC/D,CAAC,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlayUIProvider — batteries-included composite provider for actor-driven UI rendering.
|
|
3
|
+
*
|
|
4
|
+
* Wraps ActorProvider + JSONUIProvider (from @json-render/react) to provide a single
|
|
5
|
+
* entry point for all actor lifecycle and UI rendering concerns.
|
|
6
|
+
*
|
|
7
|
+
* Standard usage:
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <PlayUIProvider actor={actor} registryResult={registryResult}>
|
|
10
|
+
* <PlayRenderer />
|
|
11
|
+
* </PlayUIProvider>
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* For custom provider composition (escape hatch), use <ActorProvider> directly.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
import React from "react";
|
|
19
|
+
import { type JSONUIProviderProps } from "@json-render/react";
|
|
20
|
+
import { type ActorProviderProps } from "./ActorProvider.js";
|
|
21
|
+
type JSONUIForwardedProps = Pick<JSONUIProviderProps, "validationFunctions" | "navigate" | "functions">;
|
|
22
|
+
/**
|
|
23
|
+
* Props for PlayUIProvider — all ActorProvider props plus JSONUIProvider's own props.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export interface PlayUIProviderProps extends ActorProviderProps, Partial<JSONUIForwardedProps> {
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* PlayUIProvider — batteries-included entry point for actor-driven UI rendering.
|
|
31
|
+
*
|
|
32
|
+
* Combines actor lifecycle management (ActorProvider) with full UI provider setup
|
|
33
|
+
* (JSONUIProvider including ActionProvider, ValidationProvider, VisibilityProvider,
|
|
34
|
+
* StateProvider, and ConfirmDialogManager).
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* import { PlayUIProvider, PlayRenderer } from "@xmachines/play-react";
|
|
39
|
+
*
|
|
40
|
+
* const registryResult = defineRegistry(catalog, {
|
|
41
|
+
* components: { Login, Dashboard },
|
|
42
|
+
* actions: {
|
|
43
|
+
* login: async ({ username }) => actor.send({ type: 'auth.login', username }),
|
|
44
|
+
* logout: async () => actor.send({ type: 'auth.logout' }),
|
|
45
|
+
* },
|
|
46
|
+
* });
|
|
47
|
+
*
|
|
48
|
+
* <PlayUIProvider actor={actor} registryResult={registryResult}>
|
|
49
|
+
* <PlayRenderer />
|
|
50
|
+
* </PlayUIProvider>
|
|
51
|
+
*
|
|
52
|
+
* // With JSONUIProvider options:
|
|
53
|
+
* <PlayUIProvider
|
|
54
|
+
* actor={actor}
|
|
55
|
+
* registryResult={registryResult}
|
|
56
|
+
* navigate={(path) => router.push(path)}
|
|
57
|
+
* validationFunctions={{ isEmail: (v) => /^.+@.+$/.test(String(v)) }}
|
|
58
|
+
* >
|
|
59
|
+
* <PlayRenderer />
|
|
60
|
+
* </PlayUIProvider>
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
export declare const PlayUIProvider: React.FC<PlayUIProviderProps>;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=PlayUIProvider.d.ts.map
|