@koordinates/xstate-tree 1.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +1 -1
- package/lib/lazy.js +2 -3
- package/lib/testingUtilities.js +3 -63
- package/lib/xstate-tree.d.ts +59 -54
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./builders";
|
|
|
2
2
|
export * from "./slots";
|
|
3
3
|
export { broadcast, buildRootComponent, onBroadcast } from "./xstateTree";
|
|
4
4
|
export * from "./types";
|
|
5
|
-
export {
|
|
5
|
+
export { buildTestRootComponent, buildViewProps, genericSlotsTestingDummy, slotTestingDummyFactory, } from "./testingUtilities";
|
|
6
6
|
export { Link, buildCreateRoute, matchRoute, } from "./routing";
|
|
7
7
|
export { loggingMetaOptions } from "./useService";
|
|
8
8
|
export { lazy } from "./lazy";
|
package/lib/lazy.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { identity } from "lodash";
|
|
2
1
|
import React from "react";
|
|
3
2
|
import { createMachine, } from "xstate";
|
|
4
3
|
import { buildActions, buildSelectors, buildView, buildXStateTreeMachine, } from "./builders";
|
|
@@ -34,8 +33,8 @@ export function lazy(factory, { Loader = () => null, withContext = () => ({}), }
|
|
|
34
33
|
},
|
|
35
34
|
},
|
|
36
35
|
});
|
|
37
|
-
const selectors = buildSelectors(machine,
|
|
38
|
-
const actions = buildActions(machine, selectors,
|
|
36
|
+
const selectors = buildSelectors(machine, (ctx) => ctx);
|
|
37
|
+
const actions = buildActions(machine, selectors, (_send, _selectors) => { });
|
|
39
38
|
const view = buildView(machine, selectors, actions, slots, ({ slots, inState }) => {
|
|
40
39
|
if (inState("loading")) {
|
|
41
40
|
return React.createElement(Loader, null);
|
package/lib/testingUtilities.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// ignore file coverage
|
|
2
2
|
import { useMachine } from "@xstate/react";
|
|
3
|
-
import {
|
|
4
|
-
import React, { useEffect
|
|
3
|
+
import { transform, isEqual, isObject, isNil } from "lodash";
|
|
4
|
+
import React, { useEffect } from "react";
|
|
5
5
|
import { TinyEmitter } from "tiny-emitter";
|
|
6
|
-
import {
|
|
7
|
-
import { initEvent } from "xstate/lib/actions";
|
|
6
|
+
import { createMachine, } from "xstate";
|
|
8
7
|
import { buildXStateTreeMachine } from "./builders";
|
|
9
8
|
import { emitter, recursivelySend, XstateTreeView } from "./xstateTree";
|
|
10
9
|
/**
|
|
@@ -138,62 +137,3 @@ function difference(object, base) {
|
|
|
138
137
|
}
|
|
139
138
|
return changes(object, base);
|
|
140
139
|
}
|
|
141
|
-
/**
|
|
142
|
-
* @internal
|
|
143
|
-
* Builds a root component for use in Storybook
|
|
144
|
-
*
|
|
145
|
-
* Pass in an initial state and context and the machine will start from that state
|
|
146
|
-
*
|
|
147
|
-
* This does _not_ work for any machines using slots, nothing will be invoked unless
|
|
148
|
-
* it would be invoked by the state you have chosen the machine to start in
|
|
149
|
-
*
|
|
150
|
-
* XState will not run any invoke handlers for parent states or sibling states that
|
|
151
|
-
* would be passed through if the machine was executing normally
|
|
152
|
-
*
|
|
153
|
-
* I have no solutions for this
|
|
154
|
-
*/
|
|
155
|
-
export function buildStorybookComponent(machine, state, context) {
|
|
156
|
-
var _a;
|
|
157
|
-
if (state === void 0) { state = machine.initial; }
|
|
158
|
-
if (context === void 0) { context = (_a = machine.context) !== null && _a !== void 0 ? _a : {}; }
|
|
159
|
-
// `set` converts a state.like.this to a {state: { like: this {} } }
|
|
160
|
-
const objectState = set({}, String(state), undefined);
|
|
161
|
-
const startingState = new State({
|
|
162
|
-
value: objectState,
|
|
163
|
-
context: context,
|
|
164
|
-
_event: initEvent,
|
|
165
|
-
_sessionid: null,
|
|
166
|
-
historyValue: undefined,
|
|
167
|
-
history: undefined,
|
|
168
|
-
actions: [],
|
|
169
|
-
activities: undefined,
|
|
170
|
-
meta: undefined,
|
|
171
|
-
events: [],
|
|
172
|
-
configuration: [],
|
|
173
|
-
transitions: [],
|
|
174
|
-
children: {},
|
|
175
|
-
});
|
|
176
|
-
return function XstateTreeStorybookComponent() {
|
|
177
|
-
const [_state, _send, interpreter] = useMachine(machine, {
|
|
178
|
-
devTools: true,
|
|
179
|
-
state: startingState,
|
|
180
|
-
});
|
|
181
|
-
const [_ignored, forceRender] = useState(0);
|
|
182
|
-
useEffect(() => {
|
|
183
|
-
function handler(event) {
|
|
184
|
-
recursivelySend(interpreter, event);
|
|
185
|
-
}
|
|
186
|
-
emitter.on("event", handler);
|
|
187
|
-
// Hack to get around the fact I'm not seeing it re-render after the
|
|
188
|
-
// interpreter is initialized
|
|
189
|
-
setTimeout(() => forceRender(1), 250);
|
|
190
|
-
return () => {
|
|
191
|
-
emitter.off("event", handler);
|
|
192
|
-
};
|
|
193
|
-
}, [interpreter]);
|
|
194
|
-
if (!interpreter.initialized) {
|
|
195
|
-
return null;
|
|
196
|
-
}
|
|
197
|
-
return React.createElement(XstateTreeView, { interpreter: interpreter });
|
|
198
|
-
};
|
|
199
|
-
}
|
package/lib/xstate-tree.d.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { AnyEventObject } from 'xstate';
|
|
2
|
+
import type { AnyFunction } from 'xstate';
|
|
2
3
|
import { AnyStateMachine } from 'xstate';
|
|
3
4
|
import { BaseActionObject } from 'xstate';
|
|
4
5
|
import { ComponentPropsWithRef } from 'react';
|
|
6
|
+
import { ContextFrom } from 'xstate';
|
|
7
|
+
import { EventFrom } from 'xstate';
|
|
5
8
|
import { EventObject } from 'xstate';
|
|
6
9
|
import { History as History_2 } from 'history';
|
|
7
|
-
import {
|
|
10
|
+
import type { InterpreterFrom } from 'xstate';
|
|
8
11
|
import { JSXElementConstructor } from 'react';
|
|
9
|
-
import { NoInfer } from 'xstate';
|
|
10
12
|
import { ParsedQuery } from 'query-string';
|
|
11
13
|
import { default as React_2 } from 'react';
|
|
12
14
|
import { ResolveTypegenMeta } from 'xstate';
|
|
13
15
|
import { ServiceMap } from 'xstate';
|
|
16
|
+
import type { StateFrom } from 'xstate';
|
|
14
17
|
import { StateMachine } from 'xstate';
|
|
15
|
-
import type { TypegenConstraint } from 'xstate';
|
|
16
18
|
import { TypegenDisabled } from 'xstate';
|
|
17
|
-
import type { TypegenEnabled } from 'xstate';
|
|
18
|
-
import type { TypegenMeta } from 'xstate';
|
|
19
|
-
import { Typestate } from 'xstate';
|
|
20
19
|
import * as Z from 'zod';
|
|
21
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export declare type AnyActions = (send: any, selectors: any) => any;
|
|
25
|
+
|
|
22
26
|
/**
|
|
23
27
|
* @public
|
|
24
28
|
*/
|
|
@@ -36,6 +40,16 @@ export declare type AnyRoute = {
|
|
|
36
40
|
querySchema?: Z.ZodObject<any>;
|
|
37
41
|
};
|
|
38
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export declare type AnySelector = Selectors<any, any, any, any>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export declare type AnyXstateTreeMachine = StateMachine<any, XstateTreeMachineStateSchema<AnyStateMachine, any, any>, any>;
|
|
52
|
+
|
|
39
53
|
/**
|
|
40
54
|
* @public
|
|
41
55
|
*/
|
|
@@ -49,7 +63,7 @@ export declare function broadcast(event: GlobalEvents): void;
|
|
|
49
63
|
/**
|
|
50
64
|
* @public
|
|
51
65
|
*/
|
|
52
|
-
export declare function buildActions<
|
|
66
|
+
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;
|
|
53
67
|
|
|
54
68
|
/**
|
|
55
69
|
* @public
|
|
@@ -133,39 +147,21 @@ export declare function buildCreateRoute(history: XstateTreeHistory, basePath: s
|
|
|
133
147
|
/**
|
|
134
148
|
* @public
|
|
135
149
|
*/
|
|
136
|
-
export declare function buildRootComponent
|
|
137
|
-
routes:
|
|
138
|
-
history:
|
|
139
|
-
meta?: any;
|
|
140
|
-
}>;
|
|
150
|
+
export declare function buildRootComponent(machine: AnyXstateTreeMachine, routing?: {
|
|
151
|
+
routes: AnyRoute[];
|
|
152
|
+
history: XstateTreeHistory<any>;
|
|
141
153
|
basePath: string;
|
|
142
154
|
getPathName?: () => string;
|
|
143
155
|
getQueryString?: () => string;
|
|
144
156
|
}): {
|
|
145
157
|
(): JSX.Element | null;
|
|
146
|
-
rootMachine:
|
|
158
|
+
rootMachine: AnyXstateTreeMachine;
|
|
147
159
|
};
|
|
148
160
|
|
|
149
161
|
/**
|
|
150
162
|
* @public
|
|
151
163
|
*/
|
|
152
|
-
export declare function buildSelectors<
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @internal
|
|
156
|
-
* Builds a root component for use in Storybook
|
|
157
|
-
*
|
|
158
|
-
* Pass in an initial state and context and the machine will start from that state
|
|
159
|
-
*
|
|
160
|
-
* This does _not_ work for any machines using slots, nothing will be invoked unless
|
|
161
|
-
* it would be invoked by the state you have chosen the machine to start in
|
|
162
|
-
*
|
|
163
|
-
* XState will not run any invoke handlers for parent states or sibling states that
|
|
164
|
-
* would be passed through if the machine was executing normally
|
|
165
|
-
*
|
|
166
|
-
* I have no solutions for this
|
|
167
|
-
*/
|
|
168
|
-
export declare function buildStorybookComponent<TContext, TEvent extends EventObject, TTypeState extends Typestate<TContext>, TSelectors, TActions, TSlots extends readonly Slot[]>(machine: StateMachine<TContext, XstateTreeMachineStateSchema<TContext, TEvent, TTypeState, TSelectors, TActions, TSlots>, TEvent, TTypeState>, state?: TTypeState["value"], context?: TContext): () => JSX.Element | null;
|
|
164
|
+
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): Selectors<TContext, EventFrom<TMachine>, TSelectors, MatchesFrom<TMachine>>;
|
|
169
165
|
|
|
170
166
|
/**
|
|
171
167
|
* @public
|
|
@@ -182,7 +178,7 @@ export declare function buildStorybookComponent<TContext, TEvent extends EventOb
|
|
|
182
178
|
*
|
|
183
179
|
* It also delays for 5ms to ensure any React re-rendering happens in response to the state transition
|
|
184
180
|
*/
|
|
185
|
-
export declare function buildTestRootComponent<
|
|
181
|
+
export declare function buildTestRootComponent<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions, TContext = ContextFrom<TMachine>>(machine: StateMachine<TContext, XstateTreeMachineStateSchema<TMachine, TSelectors, TActions>, EventFrom<TMachine>>, logger: typeof console.log): {
|
|
186
182
|
rootComponent: () => JSX.Element | null;
|
|
187
183
|
addTransitionListener: (listener: () => void) => void;
|
|
188
184
|
awaitTransition(): Promise<void>;
|
|
@@ -191,7 +187,7 @@ export declare function buildTestRootComponent<TContext, TEvent extends EventObj
|
|
|
191
187
|
/**
|
|
192
188
|
* @public
|
|
193
189
|
*/
|
|
194
|
-
export declare function buildView<
|
|
190
|
+
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>;
|
|
195
191
|
|
|
196
192
|
/**
|
|
197
193
|
* @public
|
|
@@ -201,7 +197,9 @@ export declare function buildViewProps<C extends keyof JSX.IntrinsicElements | J
|
|
|
201
197
|
/**
|
|
202
198
|
* @public
|
|
203
199
|
*/
|
|
204
|
-
export declare function buildXStateTreeMachine<
|
|
200
|
+
export declare function buildXStateTreeMachine<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions>(machine: TMachine, meta: XStateTreeMachineMeta<TMachine, TSelectors, TActions>): StateMachine<ContextFrom<TMachine>, XstateTreeMachineStateSchema<TMachine, TSelectors, TActions>, EventFrom<TMachine>, any, any, any, any>;
|
|
201
|
+
|
|
202
|
+
declare type CanHandleEvent<TMachine extends AnyStateMachine> = (e: EventFrom<TMachine>) => boolean;
|
|
205
203
|
|
|
206
204
|
declare type Context = {};
|
|
207
205
|
|
|
@@ -239,10 +237,10 @@ export declare type GlobalEvents = {
|
|
|
239
237
|
};
|
|
240
238
|
}[keyof XstateTreeEvents];
|
|
241
239
|
|
|
242
|
-
declare type InferViewProps<T> = T extends ViewProps<infer TSelectors, infer TActions, never, infer
|
|
240
|
+
declare type InferViewProps<T> = T extends ViewProps<infer TSelectors, infer TActions, never, infer TMatches> ? {
|
|
243
241
|
selectors: TSelectors;
|
|
244
242
|
actions: TActions;
|
|
245
|
-
inState: (state:
|
|
243
|
+
inState: (state: Parameters<TMatches>[0]) => TMatches;
|
|
246
244
|
} : never;
|
|
247
245
|
|
|
248
246
|
declare type IsEmptyObject<Obj, ExcludeOptional extends boolean = false> = [
|
|
@@ -294,6 +292,11 @@ export declare function loggingMetaOptions<TEvents extends EventObject, TContext
|
|
|
294
292
|
|
|
295
293
|
declare type MakeEmptyObjectPropertiesOptional<T> = Omit<T, EmptyKeys<T>> & Partial<Pick<T, EmptyKeys<T>>>;
|
|
296
294
|
|
|
295
|
+
/**
|
|
296
|
+
* @internal
|
|
297
|
+
*/
|
|
298
|
+
export declare type MatchesFrom<T extends AnyStateMachine> = StateFrom<T>["matches"];
|
|
299
|
+
|
|
297
300
|
/**
|
|
298
301
|
* @public
|
|
299
302
|
*/
|
|
@@ -350,6 +353,11 @@ declare type Options_2<TContext> = {
|
|
|
350
353
|
withContext?: () => Partial<TContext>;
|
|
351
354
|
};
|
|
352
355
|
|
|
356
|
+
/**
|
|
357
|
+
* @public
|
|
358
|
+
*/
|
|
359
|
+
export declare type OutputFromSelector<T> = T extends Selectors<any, any, infer O, any> ? O : never;
|
|
360
|
+
|
|
353
361
|
/**
|
|
354
362
|
* @public
|
|
355
363
|
*/
|
|
@@ -500,7 +508,10 @@ export declare type RoutingEvent<T> = T extends Route<infer TParams, infer TQuer
|
|
|
500
508
|
meta: TMeta;
|
|
501
509
|
} : never;
|
|
502
510
|
|
|
503
|
-
|
|
511
|
+
/**
|
|
512
|
+
* @public
|
|
513
|
+
*/
|
|
514
|
+
export declare type Selectors<TContext, TEvent, TSelectors, TMatches> = (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: TMatches, __currentState: never) => TSelectors;
|
|
504
515
|
|
|
505
516
|
/**
|
|
506
517
|
* @public
|
|
@@ -546,16 +557,10 @@ export declare type Slot = SingleSlot<any> | MultiSlot<any>;
|
|
|
546
557
|
/**
|
|
547
558
|
* @public
|
|
548
559
|
*/
|
|
549
|
-
export declare function slotTestingDummyFactory(name: string): StateMachine<unknown, XstateTreeMachineStateSchema<unknown, AnyEventObject, {
|
|
560
|
+
export declare function slotTestingDummyFactory(name: string): StateMachine<unknown, XstateTreeMachineStateSchema<StateMachine<unknown, any, AnyEventObject, {
|
|
550
561
|
value: any;
|
|
551
562
|
context: unknown;
|
|
552
|
-
}, {}, {}
|
|
553
|
-
value: any;
|
|
554
|
-
context: unknown;
|
|
555
|
-
}, TypegenDisabled>>, AnyEventObject, {
|
|
556
|
-
value: any;
|
|
557
|
-
context: unknown;
|
|
558
|
-
}, any, any, any>;
|
|
563
|
+
}, BaseActionObject, ServiceMap, ResolveTypegenMeta<TypegenDisabled, AnyEventObject, BaseActionObject, ServiceMap>>, () => {}, () => {}>, AnyEventObject, any, any, any, any>;
|
|
559
564
|
|
|
560
565
|
/**
|
|
561
566
|
* @public
|
|
@@ -581,37 +586,37 @@ export declare type StyledLink<TStyleProps = {}> = <TRoute extends AnyRoute>(pro
|
|
|
581
586
|
/**
|
|
582
587
|
* @public
|
|
583
588
|
*/
|
|
584
|
-
export declare type ViewProps<TSelectors, TActions, TSlots extends readonly Slot[],
|
|
589
|
+
export declare type ViewProps<TSelectors, TActions, TSlots extends readonly Slot[], TMatches extends AnyFunction> = {
|
|
585
590
|
slots: Record<GetSlotNames<TSlots>, React_2.ComponentType>;
|
|
586
591
|
actions: TActions;
|
|
587
592
|
selectors: TSelectors;
|
|
588
|
-
inState:
|
|
593
|
+
inState: TMatches;
|
|
589
594
|
};
|
|
590
595
|
|
|
591
596
|
/**
|
|
592
597
|
* @public
|
|
593
598
|
*/
|
|
594
|
-
export declare type XstateTreeHistory = History_2<{
|
|
595
|
-
meta?:
|
|
599
|
+
export declare type XstateTreeHistory<T = unknown> = History_2<{
|
|
600
|
+
meta?: T;
|
|
596
601
|
previousUrl?: string;
|
|
597
602
|
}>;
|
|
598
603
|
|
|
599
604
|
/**
|
|
600
605
|
* @public
|
|
601
606
|
*/
|
|
602
|
-
export declare type XStateTreeMachineMeta<
|
|
607
|
+
export declare type XStateTreeMachineMeta<TMachine extends AnyStateMachine, TSelectors, TActions extends AnyActions, TSlots extends readonly Slot[] = Slot[]> = {
|
|
603
608
|
slots: TSlots;
|
|
604
|
-
view: React_2.ComponentType<ViewProps<TSelectors
|
|
605
|
-
selectors:
|
|
606
|
-
actions:
|
|
609
|
+
view: React_2.ComponentType<ViewProps<OutputFromSelector<TSelectors>, ReturnType<TActions>, TSlots, MatchesFrom<TMachine>>>;
|
|
610
|
+
selectors: TSelectors;
|
|
611
|
+
actions: TActions;
|
|
607
612
|
xstateTreeMachine?: true;
|
|
608
613
|
};
|
|
609
614
|
|
|
610
615
|
/**
|
|
611
616
|
* @public
|
|
612
617
|
*/
|
|
613
|
-
export declare type XstateTreeMachineStateSchema<
|
|
614
|
-
meta: XStateTreeMachineMeta<
|
|
618
|
+
export declare type XstateTreeMachineStateSchema<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions> = {
|
|
619
|
+
meta: XStateTreeMachineMeta<TMachine, TSelectors, TActions>;
|
|
615
620
|
};
|
|
616
621
|
|
|
617
622
|
export { }
|