@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 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,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 { 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
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<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TActions, TSelectors, TSend = (send: TEvent) => void>(__machine: StateMachine<TContext, any, TEvent, TTypestate, any, any, any>, __selectors: Selectors<TContext, TEvent, TSelectors, TTypestate["value"]>, 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;
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<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?: {
134
- routes: Route<any, any, any, any>[];
135
- history: History_2<{
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: 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;
144
159
  };
145
160
 
146
161
  /**
147
162
  * @public
148
163
  */
149
- export declare function buildSelectors<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TSelectors>(__machine: StateMachine<TContext, any, TEvent, TTypestate, any, any, any>, selectors: Selectors<TContext, TEvent, TSelectors, TTypestate["value"]>): (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: (state: TTypestate["value"]) => boolean, currentState: TTypestate["value"]) => TSelectors;
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<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): {
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<TContext, TEvent extends EventObject, TTypestate extends Typestate<TContext>, TActions, TSelectors, TSlots extends readonly Slot[] = [], TViewProps = ViewProps<TSelectors, TActions, TSlots, TTypestate["value"]>, TSend = (send: TEvent) => void>(__machine: StateMachine<TContext, any, TEvent, TTypestate, any, any, any>, __selectors: Selectors<TContext, TEvent, TSelectors, TTypestate["value"]>, __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>;
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<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;
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 TStates> ? {
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: TStates) => (state: TStates) => boolean;
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
- 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;
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
- }, {}, {}, never[], Interpreter<unknown, any, AnyEventObject, {
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[], TState> = {
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: (state: TState) => boolean;
593
+ inState: TMatches;
586
594
  };
587
595
 
588
596
  /**
589
597
  * @public
590
598
  */
591
- export declare type XstateTreeHistory = History_2<{
592
- meta?: unknown;
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<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[]> = {
600
608
  slots: TSlots;
601
- view: React_2.ComponentType<ViewProps<TSelectors, TActions, TSlots, TTypestate["value"]>>;
602
- selectors: (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: (state: TTypestate["value"]) => boolean, _state: TTypestate["value"]) => TSelectors;
603
- 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;
604
612
  xstateTreeMachine?: true;
605
613
  };
606
614
 
607
615
  /**
608
616
  * @public
609
617
  */
610
- 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>> = {
611
- 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>;
612
620
  };
613
621
 
614
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.2.0",
5
+ "version": "2.0.0",
6
6
  "dependencies": {
7
7
  "@xstate/react": "3.0.0",
8
8
  "fast-memoize": "2.5.2",