@koordinates/xstate-tree 1.2.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 -51
- 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,21 +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
18
|
import { TypegenDisabled } from 'xstate';
|
|
16
|
-
import { Typestate } from 'xstate';
|
|
17
19
|
import * as Z from 'zod';
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export declare type AnyActions = (send: any, selectors: any) => any;
|
|
25
|
+
|
|
19
26
|
/**
|
|
20
27
|
* @public
|
|
21
28
|
*/
|
|
@@ -33,6 +40,16 @@ export declare type AnyRoute = {
|
|
|
33
40
|
querySchema?: Z.ZodObject<any>;
|
|
34
41
|
};
|
|
35
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
|
+
|
|
36
53
|
/**
|
|
37
54
|
* @public
|
|
38
55
|
*/
|
|
@@ -46,7 +63,7 @@ export declare function broadcast(event: GlobalEvents): void;
|
|
|
46
63
|
/**
|
|
47
64
|
* @public
|
|
48
65
|
*/
|
|
49
|
-
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;
|
|
50
67
|
|
|
51
68
|
/**
|
|
52
69
|
* @public
|
|
@@ -130,39 +147,21 @@ export declare function buildCreateRoute(history: XstateTreeHistory, basePath: s
|
|
|
130
147
|
/**
|
|
131
148
|
* @public
|
|
132
149
|
*/
|
|
133
|
-
export declare function buildRootComponent
|
|
134
|
-
routes:
|
|
135
|
-
history:
|
|
136
|
-
meta?: any;
|
|
137
|
-
}>;
|
|
150
|
+
export declare function buildRootComponent(machine: AnyXstateTreeMachine, routing?: {
|
|
151
|
+
routes: AnyRoute[];
|
|
152
|
+
history: XstateTreeHistory<any>;
|
|
138
153
|
basePath: string;
|
|
139
154
|
getPathName?: () => string;
|
|
140
155
|
getQueryString?: () => string;
|
|
141
156
|
}): {
|
|
142
157
|
(): JSX.Element | null;
|
|
143
|
-
rootMachine:
|
|
158
|
+
rootMachine: AnyXstateTreeMachine;
|
|
144
159
|
};
|
|
145
160
|
|
|
146
161
|
/**
|
|
147
162
|
* @public
|
|
148
163
|
*/
|
|
149
|
-
export declare function buildSelectors<
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* @internal
|
|
153
|
-
* Builds a root component for use in Storybook
|
|
154
|
-
*
|
|
155
|
-
* Pass in an initial state and context and the machine will start from that state
|
|
156
|
-
*
|
|
157
|
-
* This does _not_ work for any machines using slots, nothing will be invoked unless
|
|
158
|
-
* it would be invoked by the state you have chosen the machine to start in
|
|
159
|
-
*
|
|
160
|
-
* XState will not run any invoke handlers for parent states or sibling states that
|
|
161
|
-
* would be passed through if the machine was executing normally
|
|
162
|
-
*
|
|
163
|
-
* I have no solutions for this
|
|
164
|
-
*/
|
|
165
|
-
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>>;
|
|
166
165
|
|
|
167
166
|
/**
|
|
168
167
|
* @public
|
|
@@ -179,7 +178,7 @@ export declare function buildStorybookComponent<TContext, TEvent extends EventOb
|
|
|
179
178
|
*
|
|
180
179
|
* It also delays for 5ms to ensure any React re-rendering happens in response to the state transition
|
|
181
180
|
*/
|
|
182
|
-
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): {
|
|
183
182
|
rootComponent: () => JSX.Element | null;
|
|
184
183
|
addTransitionListener: (listener: () => void) => void;
|
|
185
184
|
awaitTransition(): Promise<void>;
|
|
@@ -188,7 +187,7 @@ export declare function buildTestRootComponent<TContext, TEvent extends EventObj
|
|
|
188
187
|
/**
|
|
189
188
|
* @public
|
|
190
189
|
*/
|
|
191
|
-
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>;
|
|
192
191
|
|
|
193
192
|
/**
|
|
194
193
|
* @public
|
|
@@ -198,7 +197,9 @@ export declare function buildViewProps<C extends keyof JSX.IntrinsicElements | J
|
|
|
198
197
|
/**
|
|
199
198
|
* @public
|
|
200
199
|
*/
|
|
201
|
-
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;
|
|
202
203
|
|
|
203
204
|
declare type Context = {};
|
|
204
205
|
|
|
@@ -236,10 +237,10 @@ export declare type GlobalEvents = {
|
|
|
236
237
|
};
|
|
237
238
|
}[keyof XstateTreeEvents];
|
|
238
239
|
|
|
239
|
-
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> ? {
|
|
240
241
|
selectors: TSelectors;
|
|
241
242
|
actions: TActions;
|
|
242
|
-
inState: (state:
|
|
243
|
+
inState: (state: Parameters<TMatches>[0]) => TMatches;
|
|
243
244
|
} : never;
|
|
244
245
|
|
|
245
246
|
declare type IsEmptyObject<Obj, ExcludeOptional extends boolean = false> = [
|
|
@@ -291,6 +292,11 @@ export declare function loggingMetaOptions<TEvents extends EventObject, TContext
|
|
|
291
292
|
|
|
292
293
|
declare type MakeEmptyObjectPropertiesOptional<T> = Omit<T, EmptyKeys<T>> & Partial<Pick<T, EmptyKeys<T>>>;
|
|
293
294
|
|
|
295
|
+
/**
|
|
296
|
+
* @internal
|
|
297
|
+
*/
|
|
298
|
+
export declare type MatchesFrom<T extends AnyStateMachine> = StateFrom<T>["matches"];
|
|
299
|
+
|
|
294
300
|
/**
|
|
295
301
|
* @public
|
|
296
302
|
*/
|
|
@@ -347,6 +353,11 @@ declare type Options_2<TContext> = {
|
|
|
347
353
|
withContext?: () => Partial<TContext>;
|
|
348
354
|
};
|
|
349
355
|
|
|
356
|
+
/**
|
|
357
|
+
* @public
|
|
358
|
+
*/
|
|
359
|
+
export declare type OutputFromSelector<T> = T extends Selectors<any, any, infer O, any> ? O : never;
|
|
360
|
+
|
|
350
361
|
/**
|
|
351
362
|
* @public
|
|
352
363
|
*/
|
|
@@ -497,7 +508,10 @@ export declare type RoutingEvent<T> = T extends Route<infer TParams, infer TQuer
|
|
|
497
508
|
meta: TMeta;
|
|
498
509
|
} : never;
|
|
499
510
|
|
|
500
|
-
|
|
511
|
+
/**
|
|
512
|
+
* @public
|
|
513
|
+
*/
|
|
514
|
+
export declare type Selectors<TContext, TEvent, TSelectors, TMatches> = (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: TMatches, __currentState: never) => TSelectors;
|
|
501
515
|
|
|
502
516
|
/**
|
|
503
517
|
* @public
|
|
@@ -543,16 +557,10 @@ export declare type Slot = SingleSlot<any> | MultiSlot<any>;
|
|
|
543
557
|
/**
|
|
544
558
|
* @public
|
|
545
559
|
*/
|
|
546
|
-
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, {
|
|
547
561
|
value: any;
|
|
548
562
|
context: unknown;
|
|
549
|
-
}, {}, {}
|
|
550
|
-
value: any;
|
|
551
|
-
context: unknown;
|
|
552
|
-
}, TypegenDisabled>>, AnyEventObject, {
|
|
553
|
-
value: any;
|
|
554
|
-
context: unknown;
|
|
555
|
-
}, any, any, any>;
|
|
563
|
+
}, BaseActionObject, ServiceMap, ResolveTypegenMeta<TypegenDisabled, AnyEventObject, BaseActionObject, ServiceMap>>, () => {}, () => {}>, AnyEventObject, any, any, any, any>;
|
|
556
564
|
|
|
557
565
|
/**
|
|
558
566
|
* @public
|
|
@@ -578,37 +586,37 @@ export declare type StyledLink<TStyleProps = {}> = <TRoute extends AnyRoute>(pro
|
|
|
578
586
|
/**
|
|
579
587
|
* @public
|
|
580
588
|
*/
|
|
581
|
-
export declare type ViewProps<TSelectors, TActions, TSlots extends readonly Slot[],
|
|
589
|
+
export declare type ViewProps<TSelectors, TActions, TSlots extends readonly Slot[], TMatches extends AnyFunction> = {
|
|
582
590
|
slots: Record<GetSlotNames<TSlots>, React_2.ComponentType>;
|
|
583
591
|
actions: TActions;
|
|
584
592
|
selectors: TSelectors;
|
|
585
|
-
inState:
|
|
593
|
+
inState: TMatches;
|
|
586
594
|
};
|
|
587
595
|
|
|
588
596
|
/**
|
|
589
597
|
* @public
|
|
590
598
|
*/
|
|
591
|
-
export declare type XstateTreeHistory = History_2<{
|
|
592
|
-
meta?:
|
|
599
|
+
export declare type XstateTreeHistory<T = unknown> = History_2<{
|
|
600
|
+
meta?: T;
|
|
593
601
|
previousUrl?: string;
|
|
594
602
|
}>;
|
|
595
603
|
|
|
596
604
|
/**
|
|
597
605
|
* @public
|
|
598
606
|
*/
|
|
599
|
-
export declare type XStateTreeMachineMeta<
|
|
607
|
+
export declare type XStateTreeMachineMeta<TMachine extends AnyStateMachine, TSelectors, TActions extends AnyActions, TSlots extends readonly Slot[] = Slot[]> = {
|
|
600
608
|
slots: TSlots;
|
|
601
|
-
view: React_2.ComponentType<ViewProps<TSelectors
|
|
602
|
-
selectors:
|
|
603
|
-
actions:
|
|
609
|
+
view: React_2.ComponentType<ViewProps<OutputFromSelector<TSelectors>, ReturnType<TActions>, TSlots, MatchesFrom<TMachine>>>;
|
|
610
|
+
selectors: TSelectors;
|
|
611
|
+
actions: TActions;
|
|
604
612
|
xstateTreeMachine?: true;
|
|
605
613
|
};
|
|
606
614
|
|
|
607
615
|
/**
|
|
608
616
|
* @public
|
|
609
617
|
*/
|
|
610
|
-
export declare type XstateTreeMachineStateSchema<
|
|
611
|
-
meta: XStateTreeMachineMeta<
|
|
618
|
+
export declare type XstateTreeMachineStateSchema<TMachine extends AnyStateMachine, TSelectors extends AnySelector, TActions extends AnyActions> = {
|
|
619
|
+
meta: XStateTreeMachineMeta<TMachine, TSelectors, TActions>;
|
|
612
620
|
};
|
|
613
621
|
|
|
614
622
|
export { }
|