@koordinates/xstate-tree 4.0.1 → 4.1.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -61
- package/lib/builders.js +46 -2
- package/lib/routing/createRoute/createRoute.js +1 -1
- package/lib/xstate-tree.d.ts +88 -15
- package/lib/xstateTree.js +36 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,10 +23,7 @@ import { createRoot } from "react-dom/client";
|
|
|
23
23
|
import { createMachine } from "xstate";
|
|
24
24
|
import { assign } from "@xstate/immer";
|
|
25
25
|
import {
|
|
26
|
-
|
|
27
|
-
buildActions,
|
|
28
|
-
buildView,
|
|
29
|
-
buildXStateTreeMachine,
|
|
26
|
+
createXStateTreeMachine
|
|
30
27
|
buildRootComponent
|
|
31
28
|
} from "@koordinates/xstate-tree";
|
|
32
29
|
|
|
@@ -35,10 +32,6 @@ type Events =
|
|
|
35
32
|
| { type: "INCREMENT"; amount: number };
|
|
36
33
|
type Context = { incremented: number };
|
|
37
34
|
|
|
38
|
-
// If this tree had more than a single machine the slots to render child machines into would be defined here
|
|
39
|
-
// see the codesandbox example for an expanded demonstration that uses slots
|
|
40
|
-
const slots = [];
|
|
41
|
-
|
|
42
35
|
// A standard xstate machine, nothing extra is needed for xstate-tree
|
|
43
36
|
const machine = createMachine<Context, Events>(
|
|
44
37
|
{
|
|
@@ -74,39 +67,42 @@ const machine = createMachine<Context, Events>(
|
|
|
74
67
|
}
|
|
75
68
|
);
|
|
76
69
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
increment(amount: number) {
|
|
87
|
-
send({
|
|
88
|
-
type: "INCREMENT",
|
|
89
|
-
amount: selectors.count > 4 ? amount * 2 : amount
|
|
90
|
-
});
|
|
70
|
+
const RootMachine = createXStateTreeMachine(machine, {
|
|
71
|
+
// Selectors to transform the machines state into a representation useful for the view
|
|
72
|
+
selectors({ ctx, canHandleEvent, inState }) {
|
|
73
|
+
return {
|
|
74
|
+
canIncrement: canHandleEvent({ type: "INCREMENT", amount: 1 }),
|
|
75
|
+
showSecret: ctx.incremented > 10,
|
|
76
|
+
count: ctx.incremented,
|
|
77
|
+
active: inState("active")
|
|
78
|
+
}
|
|
91
79
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
80
|
+
// Actions to abstract away the details of sending events to the machine
|
|
81
|
+
actions({ send, selectors }) {
|
|
82
|
+
return {
|
|
83
|
+
increment(amount: number) {
|
|
84
|
+
send({
|
|
85
|
+
type: "INCREMENT",
|
|
86
|
+
amount: selectors.count > 4 ? amount * 2 : amount
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
switch() {
|
|
90
|
+
send({ type: "SWITCH_CLICKED" });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
// If this tree had more than a single machine the slots to render child machines into would be defined here
|
|
96
|
+
// see the codesandbox example for an expanded demonstration that uses slots
|
|
97
|
+
slots: [],
|
|
98
|
+
// A view to bring it all together
|
|
99
|
+
// the return value is a plain React view that can be rendered anywhere by passing in the needed props
|
|
100
|
+
// the view has no knowledge of the machine it's bound to
|
|
101
|
+
view({ actions, selectors }) {
|
|
106
102
|
return (
|
|
107
103
|
<div>
|
|
108
104
|
<button onClick={() => actions.switch()}>
|
|
109
|
-
{
|
|
105
|
+
{selectors.active ? "Deactivate" : "Activate"}
|
|
110
106
|
</button>
|
|
111
107
|
<p>Count: {selectors.count}</p>
|
|
112
108
|
<button
|
|
@@ -118,15 +114,7 @@ const view = buildView(
|
|
|
118
114
|
{selectors.showSecret && <p>The secret password is hunter2</p>}
|
|
119
115
|
</div>
|
|
120
116
|
);
|
|
121
|
-
}
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
// Stapling the machine, selectors, actions, view, and slots together
|
|
125
|
-
const RootMachine = buildXStateTreeMachine(machine, {
|
|
126
|
-
selectors,
|
|
127
|
-
actions,
|
|
128
|
-
view,
|
|
129
|
-
slots
|
|
117
|
+
},
|
|
130
118
|
});
|
|
131
119
|
|
|
132
120
|
// Build the React host for the tree
|
|
@@ -145,16 +133,16 @@ Each machine that forms the tree representing your UI has an associated set of s
|
|
|
145
133
|
- Selector functions are provided with the current context of the machine, a function to determine if it can handle a given event and a function to determine if it is in a given state, and expose the returned result to the view.
|
|
146
134
|
- Action functions are provided with the `send` method bound to the machines interpreter and the result of calling the selector function
|
|
147
135
|
- Slots are how children of the machine are exposed to the view. They can be either single slot for a single actor, or multi slot for when you have a list of actors.
|
|
148
|
-
- View functions are React views provided with the output of the selector and action functions,
|
|
136
|
+
- View functions are React views provided with the output of the selector and action functions, and the currently active slots
|
|
149
137
|
|
|
150
138
|
## API
|
|
151
139
|
|
|
152
|
-
To assist in making xstate-tree easy to use with TypeScript there
|
|
140
|
+
To assist in making xstate-tree easy to use with TypeScript there is the `createXStateTreeMachine` function for typing selectors, actions and view arguments and stapling the resulting functions to the xstate machine
|
|
153
141
|
|
|
154
|
-
|
|
155
|
-
* `
|
|
156
|
-
* `
|
|
157
|
-
* `
|
|
142
|
+
`createXStateTreeMachine` accepts the xstate machine as the first argument and takes an options argument with the following fields, it is important the fields are defined in this order or TypeScript will infer the wrong types:
|
|
143
|
+
* `selectors`, receives an object with `ctx`, `inState`, and `canHandleEvent` fields. `ctx` is the machines current context, `inState` is the xstate `state.matches` function to allow determining if the machine is in a given state, and `canHandleEvent` accepts an event object and returns whether the machine will do anything in response to that event in it's current state
|
|
144
|
+
* `actions`, receives an object with `send` and `selectors` fields. `send` is the xstate `send` function bound to the machine, and `selectors` is the result of calling the selector function
|
|
145
|
+
* `view`, is a React component that receives `actions`, `selectors`, and `slots` as props. `actions` and `selectors` being the result of the action/selector functions and `slots` being an object with keys as the slot names and the values the slots React component
|
|
158
146
|
|
|
159
147
|
Full API docs coming soon, see [#20](https://github.com/koordinates/xstate-tree/issues/20)
|
|
160
148
|
|
|
@@ -203,15 +191,6 @@ It is relatively simple to display xstate-tree views directly in Storybook. Sinc
|
|
|
203
191
|
|
|
204
192
|
There are a few utilities in xstate-tree to make this easier
|
|
205
193
|
|
|
206
|
-
#### `buildViewProps`
|
|
207
|
-
This is a builder function that accepts a view to provide typings and then an object containing
|
|
208
|
-
actions/selector fields. With the typings it provides these fields are type safe and you can autocomplete them.
|
|
209
|
-
|
|
210
|
-
It returns the props object and extends it with an `inState` factory function, so you can destructure it for use in Stories. The `inState` function accepts a state string as an argument, and returns a function that returns true if the state supplied matches that. So you can easily render the view in a specific machine state in the Story
|
|
211
|
-
```
|
|
212
|
-
const { actions, selectors, inState } = buildViewProps(view, { actions: {], selectors: {} });
|
|
213
|
-
```
|
|
214
|
-
|
|
215
194
|
#### `genericSlotsTestingDummy`
|
|
216
195
|
|
|
217
196
|
This is a simple Proxy object that renders a <div> containing the name of the slot whenever rendering
|
package/lib/builders.js
CHANGED
|
@@ -14,6 +14,7 @@ import React from "react";
|
|
|
14
14
|
* @param machine - The machine to create the selectors for
|
|
15
15
|
* @param selectors - The selector function
|
|
16
16
|
* @returns The selectors - ready to be passed to {@link buildActions}
|
|
17
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
17
18
|
*/
|
|
18
19
|
export function buildSelectors(__machine, selectors) {
|
|
19
20
|
let lastState = undefined;
|
|
@@ -52,6 +53,7 @@ export function buildSelectors(__machine, selectors) {
|
|
|
52
53
|
* @param selectors - The selectors function
|
|
53
54
|
* @param actions - The action function
|
|
54
55
|
* @returns The actions function - ready to be passed to {@link buildView}
|
|
56
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
55
57
|
* */
|
|
56
58
|
export function buildActions(__machine, __selectors, actions) {
|
|
57
59
|
return actions;
|
|
@@ -73,6 +75,7 @@ export function buildActions(__machine, __selectors, actions) {
|
|
|
73
75
|
* @param slots - The array of slots that can be rendered by the view
|
|
74
76
|
* @param view - The view function
|
|
75
77
|
* @returns The React view
|
|
78
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
76
79
|
*/
|
|
77
80
|
export function buildView(__machine, __selectors, __actions, __slots, view) {
|
|
78
81
|
return React.memo(view);
|
|
@@ -85,11 +88,52 @@ export function buildView(__machine, __selectors, __actions, __slots, view) {
|
|
|
85
88
|
* @param machine - The machine to staple the selectors/actions/slots/view to
|
|
86
89
|
* @param metadata - The xstate-tree metadata to staple to the machine
|
|
87
90
|
* @returns The xstate-tree machine, ready to be invoked by other xstate-machines or used with `buildRootComponent`
|
|
91
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
88
92
|
*/
|
|
89
93
|
export function buildXStateTreeMachine(machine, meta) {
|
|
90
94
|
const copiedMeta = { ...meta };
|
|
91
95
|
copiedMeta.xstateTreeMachine = true;
|
|
92
|
-
machine.config.meta = {
|
|
93
|
-
|
|
96
|
+
machine.config.meta = {
|
|
97
|
+
...machine.config.meta,
|
|
98
|
+
...copiedMeta,
|
|
99
|
+
builderVersion: 1,
|
|
100
|
+
};
|
|
101
|
+
machine.meta = { ...machine.meta, ...copiedMeta, builderVersion: 1 };
|
|
102
|
+
return machine;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* @public
|
|
106
|
+
* Creates an xstate-tree machine from an xstate-machine
|
|
107
|
+
*
|
|
108
|
+
* Accepts an options object defining the selectors/actions/slots and view for the xstate-tree machine
|
|
109
|
+
*
|
|
110
|
+
* Selectors/slots/actions can be omitted from the options object and will default to
|
|
111
|
+
* - actions: an empty object
|
|
112
|
+
* - selectors: the context of the machine
|
|
113
|
+
* - slots: an empty array
|
|
114
|
+
*
|
|
115
|
+
* @param machine - The xstate machine to create the xstate-tree machine from
|
|
116
|
+
* @param options - the xstate-tree options
|
|
117
|
+
*/
|
|
118
|
+
export function createXStateTreeMachine(machine, options) {
|
|
119
|
+
var _a, _b, _c;
|
|
120
|
+
const selectors = (_a = options.selectors) !== null && _a !== void 0 ? _a : (({ ctx }) => ctx);
|
|
121
|
+
const actions = (_b = options.actions) !== null && _b !== void 0 ? _b : (() => ({}));
|
|
122
|
+
const xstateTreeMeta = {
|
|
123
|
+
selectors,
|
|
124
|
+
actions,
|
|
125
|
+
view: options.view,
|
|
126
|
+
slots: (_c = options.slots) !== null && _c !== void 0 ? _c : [],
|
|
127
|
+
};
|
|
128
|
+
machine.meta = {
|
|
129
|
+
...machine.meta,
|
|
130
|
+
...xstateTreeMeta,
|
|
131
|
+
builderVersion: 2,
|
|
132
|
+
};
|
|
133
|
+
machine.config.meta = {
|
|
134
|
+
...machine.config.meta,
|
|
135
|
+
...xstateTreeMeta,
|
|
136
|
+
builderVersion: 2,
|
|
137
|
+
};
|
|
94
138
|
return machine;
|
|
95
139
|
}
|
package/lib/xstate-tree.d.ts
CHANGED
|
@@ -18,6 +18,14 @@ import { StateMachine } from 'xstate';
|
|
|
18
18
|
import { TypegenDisabled } from 'xstate';
|
|
19
19
|
import * as Z from 'zod';
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export declare type Actions<TMachine extends AnyStateMachine, TSelectorsOutput, TOut> = (args: {
|
|
25
|
+
send: InterpreterFrom<TMachine>["send"];
|
|
26
|
+
selectors: TSelectorsOutput;
|
|
27
|
+
}) => TOut;
|
|
28
|
+
|
|
21
29
|
/**
|
|
22
30
|
* @public
|
|
23
31
|
*/
|
|
@@ -33,7 +41,7 @@ export declare type AnyRoute = {
|
|
|
33
41
|
getEvent: any;
|
|
34
42
|
event: string;
|
|
35
43
|
basePath: string;
|
|
36
|
-
history: XstateTreeHistory;
|
|
44
|
+
history: () => XstateTreeHistory;
|
|
37
45
|
parent?: AnyRoute;
|
|
38
46
|
paramsSchema?: Z.ZodObject<any>;
|
|
39
47
|
querySchema?: Z.ZodObject<any>;
|
|
@@ -45,12 +53,12 @@ export declare type AnyRoute = {
|
|
|
45
53
|
/**
|
|
46
54
|
* @public
|
|
47
55
|
*/
|
|
48
|
-
export declare type AnySelector =
|
|
56
|
+
export declare type AnySelector = V1Selectors<any, any, any, any>;
|
|
49
57
|
|
|
50
58
|
/**
|
|
51
59
|
* @public
|
|
52
60
|
*/
|
|
53
|
-
export declare type AnyXstateTreeMachine = StateMachine<any,
|
|
61
|
+
export declare type AnyXstateTreeMachine = StateMachine<any, XstateTreeMachineStateSchemaV1<AnyStateMachine, AnySelector, AnyActions> | XstateTreeMachineStateSchemaV2<AnyStateMachine, any, any>, any>;
|
|
54
62
|
|
|
55
63
|
/**
|
|
56
64
|
* @public
|
|
@@ -80,6 +88,7 @@ export declare function broadcast(event: GlobalEvents): void;
|
|
|
80
88
|
* @param selectors - The selectors function
|
|
81
89
|
* @param actions - The action function
|
|
82
90
|
* @returns The actions function - ready to be passed to {@link buildView}
|
|
91
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
83
92
|
* */
|
|
84
93
|
export declare function buildActions<TMachine extends AnyStateMachine, TActions, TSelectors, TSend = InterpreterFrom<TMachine>["send"]>(__machine: TMachine, __selectors: TSelectors, actions: (send: TSend, selectors: OutputFromSelector<TSelectors>) => TActions): (send: TSend, selectors: OutputFromSelector<TSelectors>) => TActions;
|
|
85
94
|
|
|
@@ -91,7 +100,7 @@ export declare function buildActions<TMachine extends AnyStateMachine, TActions,
|
|
|
91
100
|
* @param history - the history object to use for this route factory, this needs to be the same one used in the trees root component
|
|
92
101
|
* @param basePath - the base path for this route factory
|
|
93
102
|
*/
|
|
94
|
-
export declare function buildCreateRoute(history: XstateTreeHistory, basePath: string): {
|
|
103
|
+
export declare function buildCreateRoute(history: () => XstateTreeHistory, basePath: string): {
|
|
95
104
|
simpleRoute<TBaseRoute extends AnyRoute>(baseRoute?: TBaseRoute | undefined): <TEvent extends string, TParamsSchema extends Z.ZodObject<any, "strip", Z.ZodTypeAny, {
|
|
96
105
|
[x: string]: any;
|
|
97
106
|
}, {
|
|
@@ -174,8 +183,9 @@ export declare function buildRootComponent(machine: AnyXstateTreeMachine, routin
|
|
|
174
183
|
* @param machine - The machine to create the selectors for
|
|
175
184
|
* @param selectors - The selector function
|
|
176
185
|
* @returns The selectors - ready to be passed to {@link buildActions}
|
|
186
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
177
187
|
*/
|
|
178
|
-
export declare function buildSelectors<TMachine extends AnyStateMachine, TSelectors, TContext = ContextFrom<TMachine>>(__machine: TMachine, selectors: (ctx: TContext, canHandleEvent: CanHandleEvent<TMachine>, inState: MatchesFrom<TMachine>, __currentState: never) => TSelectors):
|
|
188
|
+
export declare function buildSelectors<TMachine extends AnyStateMachine, TSelectors, TContext = ContextFrom<TMachine>>(__machine: TMachine, selectors: (ctx: TContext, canHandleEvent: CanHandleEvent<TMachine>, inState: MatchesFrom<TMachine>, __currentState: never) => TSelectors): V1Selectors<TContext, EventFrom<TMachine>, TSelectors, MatchesFrom<TMachine>>;
|
|
179
189
|
|
|
180
190
|
/**
|
|
181
191
|
* @public
|
|
@@ -192,7 +202,7 @@ export declare function buildSelectors<TMachine extends AnyStateMachine, TSelect
|
|
|
192
202
|
*
|
|
193
203
|
* It also delays for 5ms to ensure any React re-rendering happens in response to the state transition
|
|
194
204
|
*/
|
|
195
|
-
export declare function buildTestRootComponent<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions, TContext = ContextFrom<TMachine>>(machine: StateMachine<TContext,
|
|
205
|
+
export declare function buildTestRootComponent<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions, TContext = ContextFrom<TMachine>>(machine: StateMachine<TContext, XstateTreeMachineStateSchemaV1<TMachine, TSelectors, TActions>, EventFrom<TMachine>>, logger: typeof console.log): {
|
|
196
206
|
rootComponent: () => JSX.Element | null;
|
|
197
207
|
addTransitionListener: (listener: () => void) => void;
|
|
198
208
|
awaitTransition(): Promise<void>;
|
|
@@ -215,6 +225,7 @@ export declare function buildTestRootComponent<TMachine extends AnyStateMachine,
|
|
|
215
225
|
* @param slots - The array of slots that can be rendered by the view
|
|
216
226
|
* @param view - The view function
|
|
217
227
|
* @returns The React view
|
|
228
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
218
229
|
*/
|
|
219
230
|
export declare function buildView<TMachine extends AnyStateMachine, TEvent extends EventObject, TActions, TSelectors extends AnySelector, TSlots extends readonly Slot[] = [], TMatches extends AnyFunction = MatchesFrom<TMachine>, TViewProps = ViewProps<OutputFromSelector<TSelectors>, TActions, TSlots, TMatches>, TSend = (send: TEvent) => void>(__machine: TMachine, __selectors: TSelectors, __actions: (send: TSend, selectors: OutputFromSelector<TSelectors>) => TActions, __slots: TSlots, view: React_2.ComponentType<TViewProps>): React_2.ComponentType<TViewProps>;
|
|
220
231
|
|
|
@@ -237,13 +248,33 @@ export declare function buildViewProps<C extends keyof JSX.IntrinsicElements | J
|
|
|
237
248
|
* @param machine - The machine to staple the selectors/actions/slots/view to
|
|
238
249
|
* @param metadata - The xstate-tree metadata to staple to the machine
|
|
239
250
|
* @returns The xstate-tree machine, ready to be invoked by other xstate-machines or used with `buildRootComponent`
|
|
251
|
+
* @deprecated use {@link createXStateTreeMachine} instead
|
|
240
252
|
*/
|
|
241
|
-
export declare function buildXStateTreeMachine<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions>(machine: TMachine, meta:
|
|
253
|
+
export declare function buildXStateTreeMachine<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions>(machine: TMachine, meta: XStateTreeMachineMetaV1<TMachine, TSelectors, TActions>): StateMachine<ContextFrom<TMachine>, XstateTreeMachineStateSchemaV1<TMachine, TSelectors, TActions>, EventFrom<TMachine>, any, any, any, any>;
|
|
242
254
|
|
|
243
|
-
|
|
255
|
+
/**
|
|
256
|
+
* @internal
|
|
257
|
+
*/
|
|
258
|
+
export declare type CanHandleEvent<TMachine extends AnyStateMachine> = (e: EventFrom<TMachine>) => boolean;
|
|
244
259
|
|
|
245
260
|
declare type Context = {};
|
|
246
261
|
|
|
262
|
+
/**
|
|
263
|
+
* @public
|
|
264
|
+
* Creates an xstate-tree machine from an xstate-machine
|
|
265
|
+
*
|
|
266
|
+
* Accepts an options object defining the selectors/actions/slots and view for the xstate-tree machine
|
|
267
|
+
*
|
|
268
|
+
* Selectors/slots/actions can be omitted from the options object and will default to
|
|
269
|
+
* - actions: an empty object
|
|
270
|
+
* - selectors: the context of the machine
|
|
271
|
+
* - slots: an empty array
|
|
272
|
+
*
|
|
273
|
+
* @param machine - The xstate machine to create the xstate-tree machine from
|
|
274
|
+
* @param options - the xstate-tree options
|
|
275
|
+
*/
|
|
276
|
+
export declare function createXStateTreeMachine<TMachine extends AnyStateMachine, TSelectorsOutput = ContextFrom<TMachine>, TActionsOutput = Record<never, string>, TSlots extends readonly Slot[] = []>(machine: TMachine, options: V2BuilderMeta<TMachine, TSelectorsOutput, TActionsOutput, TSlots>): StateMachine<ContextFrom<TMachine>, XstateTreeMachineStateSchemaV2<TMachine, TSelectorsOutput, TActionsOutput, TSlots>, EventFrom<TMachine>, any, any, any, any>;
|
|
277
|
+
|
|
247
278
|
declare type EmptyKeys<T> = keyof {
|
|
248
279
|
[K in keyof T as IsEmptyObject<T[K], true> extends true ? K : never]: T[K];
|
|
249
280
|
};
|
|
@@ -400,7 +431,7 @@ declare type Options<TContext> = {
|
|
|
400
431
|
/**
|
|
401
432
|
* @public
|
|
402
433
|
*/
|
|
403
|
-
export declare type OutputFromSelector<T> = T extends
|
|
434
|
+
export declare type OutputFromSelector<T> = T extends V1Selectors<any, any, infer O, any> ? O : never;
|
|
404
435
|
|
|
405
436
|
/**
|
|
406
437
|
* @public
|
|
@@ -498,7 +529,7 @@ export declare type Route<TParams, TQuery, TEvent, TMeta> = {
|
|
|
498
529
|
* Event type for this route
|
|
499
530
|
*/
|
|
500
531
|
event: TEvent;
|
|
501
|
-
history: XstateTreeHistory;
|
|
532
|
+
history: () => XstateTreeHistory;
|
|
502
533
|
basePath: string;
|
|
503
534
|
parent?: AnyRoute;
|
|
504
535
|
paramsSchema?: Z.ZodObject<any>;
|
|
@@ -582,7 +613,11 @@ export declare type RoutingEvent<T> = T extends Route<infer TParams, infer TQuer
|
|
|
582
613
|
/**
|
|
583
614
|
* @public
|
|
584
615
|
*/
|
|
585
|
-
export declare type Selectors<
|
|
616
|
+
export declare type Selectors<TMachine extends AnyStateMachine, TOut> = (args: {
|
|
617
|
+
ctx: ContextFrom<TMachine>;
|
|
618
|
+
canHandleEvent: CanHandleEvent<TMachine>;
|
|
619
|
+
inState: MatchesFrom<TMachine>;
|
|
620
|
+
}) => TOut;
|
|
586
621
|
|
|
587
622
|
/**
|
|
588
623
|
* @public
|
|
@@ -636,7 +671,7 @@ export declare type Slot = SingleSlot<any> | MultiSlot<any>;
|
|
|
636
671
|
* @param name - the string to render in the machines view
|
|
637
672
|
* @returns a dummy machine that renders a div containing the supplied string
|
|
638
673
|
*/
|
|
639
|
-
export declare function slotTestingDummyFactory(name: string): StateMachine<unknown,
|
|
674
|
+
export declare function slotTestingDummyFactory(name: string): StateMachine<unknown, XstateTreeMachineStateSchemaV1<StateMachine<unknown, any, AnyEventObject, {
|
|
640
675
|
value: any;
|
|
641
676
|
context: unknown;
|
|
642
677
|
}, BaseActionObject, ServiceMap, ResolveTypegenMeta<TypegenDisabled, AnyEventObject, BaseActionObject, ServiceMap>>, () => {}, () => {}>, AnyEventObject, any, any, any, any>;
|
|
@@ -662,6 +697,30 @@ declare type States = {
|
|
|
662
697
|
*/
|
|
663
698
|
export declare type StyledLink<TStyleProps = {}> = <TRoute extends AnyRoute>(props: LinkProps<TRoute> & TStyleProps) => JSX.Element;
|
|
664
699
|
|
|
700
|
+
/**
|
|
701
|
+
* @public
|
|
702
|
+
*/
|
|
703
|
+
export declare type V1Selectors<TContext, TEvent, TSelectors, TMatches> = (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: TMatches, __currentState: never) => TSelectors;
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* @public
|
|
707
|
+
*/
|
|
708
|
+
export declare type V2BuilderMeta<TMachine extends AnyStateMachine, TSelectorsOutput = ContextFrom<TMachine>, TActionsOutput = Record<never, string>, TSlots extends readonly Slot[] = Slot[]> = {
|
|
709
|
+
selectors?: Selectors<TMachine, TSelectorsOutput>;
|
|
710
|
+
actions?: Actions<TMachine, TSelectorsOutput, TActionsOutput>;
|
|
711
|
+
slots?: TSlots;
|
|
712
|
+
view: View<TActionsOutput, TSelectorsOutput, TSlots>;
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* @public
|
|
717
|
+
*/
|
|
718
|
+
export declare type View<TActionsOutput, TSelectorsOutput, TSlots extends readonly Slot[]> = React_2.ComponentType<{
|
|
719
|
+
slots: Record<GetSlotNames<TSlots>, React_2.ComponentType>;
|
|
720
|
+
actions: TActionsOutput;
|
|
721
|
+
selectors: TSelectorsOutput;
|
|
722
|
+
}>;
|
|
723
|
+
|
|
665
724
|
/**
|
|
666
725
|
* @public
|
|
667
726
|
*/
|
|
@@ -669,6 +728,9 @@ export declare type ViewProps<TSelectors, TActions, TSlots extends readonly Slot
|
|
|
669
728
|
slots: Record<GetSlotNames<TSlots>, React_2.ComponentType>;
|
|
670
729
|
actions: TActions;
|
|
671
730
|
selectors: TSelectors;
|
|
731
|
+
/**
|
|
732
|
+
* @deprecated see https://github.com/koordinates/xstate-tree/issues/33 use `inState` in the selector function instead
|
|
733
|
+
*/
|
|
672
734
|
inState: TMatches;
|
|
673
735
|
};
|
|
674
736
|
|
|
@@ -683,7 +745,7 @@ export declare type XstateTreeHistory<T = unknown> = History_2<{
|
|
|
683
745
|
/**
|
|
684
746
|
* @public
|
|
685
747
|
*/
|
|
686
|
-
export declare type
|
|
748
|
+
export declare type XStateTreeMachineMetaV1<TMachine extends AnyStateMachine, TSelectors, TActions extends AnyActions, TSlots extends readonly Slot[] = Slot[]> = {
|
|
687
749
|
slots: TSlots;
|
|
688
750
|
view: React_2.ComponentType<ViewProps<OutputFromSelector<TSelectors>, ReturnType<TActions>, TSlots, MatchesFrom<TMachine>>>;
|
|
689
751
|
selectors: TSelectors;
|
|
@@ -694,8 +756,19 @@ export declare type XStateTreeMachineMeta<TMachine extends AnyStateMachine, TSel
|
|
|
694
756
|
/**
|
|
695
757
|
* @public
|
|
696
758
|
*/
|
|
697
|
-
export declare type
|
|
698
|
-
meta:
|
|
759
|
+
export declare type XstateTreeMachineStateSchemaV1<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions> = {
|
|
760
|
+
meta: XStateTreeMachineMetaV1<TMachine, TSelectors, TActions> & {
|
|
761
|
+
builderVersion: 1;
|
|
762
|
+
};
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* @public
|
|
767
|
+
*/
|
|
768
|
+
export declare type XstateTreeMachineStateSchemaV2<TMachine extends AnyStateMachine, TSelectorsOutput = ContextFrom<TMachine>, TActionsOutput = Record<never, string>, TSlots extends readonly Slot[] = Slot[]> = {
|
|
769
|
+
meta: Required<V2BuilderMeta<TMachine, TSelectorsOutput, TActionsOutput, TSlots> & {
|
|
770
|
+
builderVersion: 2;
|
|
771
|
+
}>;
|
|
699
772
|
};
|
|
700
773
|
|
|
701
774
|
export { }
|
package/lib/xstateTree.js
CHANGED
|
@@ -104,11 +104,12 @@ function XstateTreeMultiSlotView({ childInterpreters, }) {
|
|
|
104
104
|
* @internal
|
|
105
105
|
*/
|
|
106
106
|
export function XstateTreeView({ interpreter }) {
|
|
107
|
+
var _a, _b;
|
|
107
108
|
const [current] = useService(interpreter);
|
|
108
109
|
const currentRef = useRef(current);
|
|
109
110
|
currentRef.current = current;
|
|
110
111
|
const selectorsRef = useRef(undefined);
|
|
111
|
-
const {
|
|
112
|
+
const { slots: interpreterSlots } = interpreter.machine.meta;
|
|
112
113
|
const slots = useSlots(interpreter, interpreterSlots.map((x) => x.name));
|
|
113
114
|
const canHandleEvent = useCallback((e) => {
|
|
114
115
|
var _a;
|
|
@@ -131,14 +132,44 @@ export function XstateTreeView({ interpreter }) {
|
|
|
131
132
|
});
|
|
132
133
|
});
|
|
133
134
|
const actions = useConstant(() => {
|
|
134
|
-
|
|
135
|
+
var _a;
|
|
136
|
+
switch ((_a = interpreter.machine.meta) === null || _a === void 0 ? void 0 : _a.builderVersion) {
|
|
137
|
+
case 1:
|
|
138
|
+
return interpreter.machine.meta.actions(interpreter.send, selectorsProxy);
|
|
139
|
+
case 2:
|
|
140
|
+
return interpreter.machine.meta.actions({
|
|
141
|
+
send: interpreter.send,
|
|
142
|
+
selectors: selectorsProxy,
|
|
143
|
+
});
|
|
144
|
+
default:
|
|
145
|
+
throw new Error("builderVersion not set");
|
|
146
|
+
}
|
|
135
147
|
});
|
|
136
148
|
if (!current) {
|
|
137
149
|
return null;
|
|
138
150
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
151
|
+
switch ((_a = interpreter.machine.meta) === null || _a === void 0 ? void 0 : _a.builderVersion) {
|
|
152
|
+
case 1:
|
|
153
|
+
selectorsRef.current = interpreter.machine.meta.selectors(current.context, canHandleEvent, inState, current.value);
|
|
154
|
+
break;
|
|
155
|
+
case 2:
|
|
156
|
+
selectorsRef.current = interpreter.machine.meta.selectors({
|
|
157
|
+
ctx: current.context,
|
|
158
|
+
canHandleEvent,
|
|
159
|
+
inState,
|
|
160
|
+
});
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
switch ((_b = interpreter.machine.meta) === null || _b === void 0 ? void 0 : _b.builderVersion) {
|
|
164
|
+
case 1:
|
|
165
|
+
const ViewV1 = interpreter.machine.meta.view;
|
|
166
|
+
return (React.createElement(ViewV1, { selectors: selectorsRef.current, actions: actions, slots: slots, inState: inState }));
|
|
167
|
+
case 2:
|
|
168
|
+
const ViewV2 = interpreter.machine.meta.view;
|
|
169
|
+
return (React.createElement(ViewV2, { selectors: selectorsRef.current, actions: actions, slots: slots }));
|
|
170
|
+
default:
|
|
171
|
+
throw new Error("builderVersion not set");
|
|
172
|
+
}
|
|
142
173
|
}
|
|
143
174
|
/**
|
|
144
175
|
* @internal
|
package/package.json
CHANGED