@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 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 { buildStorybookComponent, buildTestRootComponent, buildViewProps, genericSlotsTestingDummy, slotTestingDummyFactory, } from "./testingUtilities";
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, identity);
38
- const actions = buildActions(machine, selectors, identity);
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);
@@ -1,10 +1,9 @@
1
1
  // ignore file coverage
2
2
  import { useMachine } from "@xstate/react";
3
- import { set, transform, isEqual, isObject, isNil } from "lodash";
4
- import React, { useEffect, useState } from "react";
3
+ import { transform, isEqual, isObject, isNil } from "lodash";
4
+ import React, { useEffect } from "react";
5
5
  import { TinyEmitter } from "tiny-emitter";
6
- import { State, createMachine, } from "xstate";
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
- }
@@ -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 { Interpreter } from 'xstate';
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<TContext, TStateSchema, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TXstateActions extends BaseActionObject, TServices extends ServiceMap, TTypegen extends TypegenConstraint, TActions, TSelectors, TStates = TTypegen extends TypegenEnabled ? TTypegen extends ResolveTypegenMeta<infer T, any, any, any> ? T extends TypegenMeta ? T["matchesStates"] : never : never : TTypestate["value"], TSend = (send: TEvent) => void>(__machine: StateMachine<TContext, TStateSchema, TEvent, TTypestate, TXstateActions, TServices, TTypegen>, __selectors: Selectors<TContext, TEvent, TSelectors, TStates>, actions: (send: TSend, selectors: TSelectors) => TActions): (send: TSend, selectors: TSelectors) => TActions;
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<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>, routing?: {
137
- routes: Route<any, any, any, any>[];
138
- history: History_2<{
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: StateMachine<TContext, XstateTreeMachineStateSchema<TContext, TEvent, TTypeState, TSelectors, TActions, TSlots, Interpreter<TContext, any, TEvent, TTypeState, TypegenDisabled>>, TEvent, TTypeState, BaseActionObject, ServiceMap, ResolveTypegenMeta<TypegenDisabled, NoInfer<TEvent>, BaseActionObject, ServiceMap>>;
158
+ rootMachine: AnyXstateTreeMachine;
147
159
  };
148
160
 
149
161
  /**
150
162
  * @public
151
163
  */
152
- export declare function buildSelectors<TContext, TStateSchema, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TXstateActions extends BaseActionObject, TServices extends ServiceMap, TTypegen extends TypegenConstraint, TSelectors, TStates = TTypegen extends TypegenEnabled ? TTypegen extends ResolveTypegenMeta<infer T, any, any, any> ? T extends TypegenMeta ? T["matchesStates"] : never : never : TTypestate["value"]>(__machine: StateMachine<TContext, TStateSchema, TEvent, TTypestate, TXstateActions, TServices, TTypegen>, selectors: Selectors<TContext, TEvent, TSelectors, TStates>): (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: (state: TStates) => boolean, currentState: TStates) => TSelectors;
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<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>, logger: typeof console.log): {
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<TContext, TStateSchema, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TXstateActions extends BaseActionObject, TServices extends ServiceMap, TTypegen extends TypegenConstraint, TActions, TSelectors, TSlots extends readonly Slot[] = [], TStates = TTypegen extends TypegenEnabled ? TTypegen extends ResolveTypegenMeta<infer T, any, any, any> ? T extends TypegenMeta ? T["matchesStates"] : never : never : TTypestate["value"], TViewProps = ViewProps<TSelectors, TActions, TSlots, TStates>, TSend = (send: TEvent) => void>(__machine: StateMachine<TContext, TStateSchema, TEvent, TTypestate, TXstateActions, TServices, TTypegen>, __selectors: Selectors<TContext, TEvent, TSelectors, TStates>, __actions: (send: TSend, selectors: TSelectors) => TActions, __slots: TSlots, view: React_2.ComponentType<TViewProps>): React_2.ComponentType<TViewProps>;
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<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TSelectors = unknown, TActions = unknown, TInterpreter extends Interpreter<TContext, any, TEvent, TTypestate> = Interpreter<TContext, any, TEvent, TTypestate>, TSlots extends readonly Slot[] = Slot[]>(machine: StateMachine<TContext, any, TEvent, TTypestate, any, any, any>, meta: XStateTreeMachineMeta<TContext, TEvent, TTypestate, TSelectors, TActions, TInterpreter, TSlots>): StateMachine<TContext, XstateTreeMachineStateSchema<TContext, TEvent, TTypestate, TSelectors, TActions, TSlots, TInterpreter>, TEvent, TTypestate, any, any, any>;
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 TStates> ? {
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: TStates) => (state: TStates) => boolean;
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
- declare type Selectors<TContext, TEvent extends EventObject, TSelectors, TStates> = (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: (state: TStates) => boolean, __currentState: TStates) => TSelectors;
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
- }, {}, {}, never[], Interpreter<unknown, any, AnyEventObject, {
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[], TState> = {
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: (state: TState) => boolean;
593
+ inState: TMatches;
589
594
  };
590
595
 
591
596
  /**
592
597
  * @public
593
598
  */
594
- export declare type XstateTreeHistory = History_2<{
595
- meta?: unknown;
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<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TSelectors = unknown, TActions = unknown, TInterpreter extends Interpreter<TContext, any, TEvent, TTypestate> = Interpreter<TContext, any, TEvent, TTypestate>, TSlots extends readonly Slot[] = Slot[]> = {
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, TActions, TSlots, TTypestate["value"]>>;
605
- selectors: (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: (state: TTypestate["value"]) => boolean, _state: TTypestate["value"]) => TSelectors;
606
- actions: (send: TInterpreter["send"], selectors: TSelectors) => TActions;
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<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TSelectors = unknown, TActions = unknown, TSlots extends readonly Slot[] = Slot[], TInterpreter extends Interpreter<TContext, any, TEvent, TTypestate> = Interpreter<TContext, any, TEvent, TTypestate>> = {
614
- meta: XStateTreeMachineMeta<TContext, TEvent, TTypestate, TSelectors, TActions, TInterpreter, TSlots>;
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 { }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@koordinates/xstate-tree",
3
3
  "main": "lib/index.js",
4
4
  "types": "lib/xstate-tree.d.ts",
5
- "version": "1.3.0",
5
+ "version": "2.0.0",
6
6
  "dependencies": {
7
7
  "@xstate/react": "3.0.0",
8
8
  "fast-memoize": "2.5.2",