@koordinates/xstate-tree 4.6.4 → 5.1.0-next.10
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/builders.js +13 -129
- package/lib/index.js +1 -4
- package/lib/lazy.js +23 -23
- package/lib/routing/Link.js +5 -6
- package/lib/routing/createRoute/createRoute.js +9 -10
- package/lib/routing/handleLocationChange/handleLocationChange.js +2 -2
- package/lib/routing/matchRoute/matchRoute.js +2 -3
- package/lib/routing/providers.js +2 -3
- package/lib/routing/useRouteArgsIfActive.js +1 -1
- package/lib/testingUtilities.js +7 -145
- package/lib/useService.js +9 -49
- package/lib/utils.js +19 -1
- package/lib/xstate-tree.d.ts +54 -228
- package/lib/xstateTree.js +69 -88
- package/package.json +7 -8
package/lib/builders.js
CHANGED
|
@@ -3,116 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.buildRoutingMachine = exports.viewToMachine = exports.createXStateTreeMachine =
|
|
6
|
+
exports.buildRoutingMachine = exports.viewToMachine = exports.createXStateTreeMachine = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const xstate_1 = require("xstate");
|
|
9
9
|
const slots_1 = require("./slots");
|
|
10
|
-
/**
|
|
11
|
-
* @public
|
|
12
|
-
*
|
|
13
|
-
* Factory function for selectors. The selectors function is passed three arguments:
|
|
14
|
-
* - `ctx` - the current context of the machines state
|
|
15
|
-
* - `canHandleEvent` - a function that can be used to determine if the machine can handle a
|
|
16
|
-
* given event, by simulating sending the event and seeing if a stat change would happen.
|
|
17
|
-
* Handles guards
|
|
18
|
-
* - `inState` - equivalent to xstates `state.matches`, allows checking if the machine is in a given state
|
|
19
|
-
*
|
|
20
|
-
* The resulting selector function has memoization. It will return the same value until the
|
|
21
|
-
* machine's state changes or the machine's context changes
|
|
22
|
-
* @param machine - The machine to create the selectors for
|
|
23
|
-
* @param selectors - The selector function
|
|
24
|
-
* @returns The selectors - ready to be passed to {@link buildActions}
|
|
25
|
-
* @deprecated use {@link createXStateTreeMachine} instead
|
|
26
|
-
*/
|
|
27
|
-
function buildSelectors(__machine, selectors) {
|
|
28
|
-
let lastState = undefined;
|
|
29
|
-
let lastCachedResult = undefined;
|
|
30
|
-
let lastCtxRef = undefined;
|
|
31
|
-
return (ctx, canHandleEvent, inState, currentState) => {
|
|
32
|
-
// Handles caching to ensure stable references to selector results
|
|
33
|
-
// Only re-run the selector if
|
|
34
|
-
// * The reference to the context object has changed (the context object should never be mutated)
|
|
35
|
-
// * The last state we ran the selectors in has changed. This is to ensure `canHandleEvent` and `inState` calls aren't stale
|
|
36
|
-
if (lastCtxRef === ctx &&
|
|
37
|
-
lastState === currentState &&
|
|
38
|
-
lastCachedResult !== undefined) {
|
|
39
|
-
return lastCachedResult;
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
42
|
-
const result = selectors(ctx, canHandleEvent, inState, currentState);
|
|
43
|
-
lastCtxRef = ctx;
|
|
44
|
-
lastCachedResult = result;
|
|
45
|
-
lastState = currentState;
|
|
46
|
-
return result;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
exports.buildSelectors = buildSelectors;
|
|
51
|
-
/**
|
|
52
|
-
* @public
|
|
53
|
-
*
|
|
54
|
-
* Factory function for actions. The actions function is passed two arguments:
|
|
55
|
-
* - `send` - the interpreters send function, which can be used to send events to the machine
|
|
56
|
-
* - `selectors` - the output of the selectors function from {@link buildSelectors}
|
|
57
|
-
*
|
|
58
|
-
* The resulting action function will only be called once per invocation of a machine.
|
|
59
|
-
* The selectors are passed in as a proxy to always read the latest selector value
|
|
60
|
-
*
|
|
61
|
-
* @param machine - The machine to create the actions for
|
|
62
|
-
* @param selectors - The selectors function
|
|
63
|
-
* @param actions - The action function
|
|
64
|
-
* @returns The actions function - ready to be passed to {@link buildView}
|
|
65
|
-
* @deprecated use {@link createXStateTreeMachine} instead
|
|
66
|
-
* */
|
|
67
|
-
function buildActions(__machine, __selectors, actions) {
|
|
68
|
-
return actions;
|
|
69
|
-
}
|
|
70
|
-
exports.buildActions = buildActions;
|
|
71
|
-
/**
|
|
72
|
-
* @public
|
|
73
|
-
*
|
|
74
|
-
* Factory function for views. The view is passed four props:
|
|
75
|
-
* - `slots` - the slots object, which can be used to render the children of the view invoked by the machine
|
|
76
|
-
* - `actions` - the output of the actions function from {@link buildActions}
|
|
77
|
-
* - `selectors` - the output of the selectors function from {@link buildSelectors}
|
|
78
|
-
* - `inState` - equivalent to xstates `state.matches`, allows checking if the machine is in a given state
|
|
79
|
-
*
|
|
80
|
-
* The resulting view is wrapped in React.memo, it will re-render when the actions or selectors reference changes
|
|
81
|
-
*
|
|
82
|
-
* @param machine - The machine to create the view for
|
|
83
|
-
* @param selectors - The selectors function from {@link buildSelectors}
|
|
84
|
-
* @param actions - The actions function from {@link buildActions}
|
|
85
|
-
* @param slots - The array of slots that can be rendered by the view
|
|
86
|
-
* @param view - The view function
|
|
87
|
-
* @returns The React view
|
|
88
|
-
* @deprecated use {@link createXStateTreeMachine} instead
|
|
89
|
-
*/
|
|
90
|
-
function buildView(__machine, __selectors, __actions, __slots, view) {
|
|
91
|
-
return react_1.default.memo(view);
|
|
92
|
-
}
|
|
93
|
-
exports.buildView = buildView;
|
|
94
|
-
/**
|
|
95
|
-
* @public
|
|
96
|
-
*
|
|
97
|
-
* staples xstate machine and xstate-tree metadata together into an xstate-tree machine
|
|
98
|
-
*
|
|
99
|
-
* @param machine - The machine to staple the selectors/actions/slots/view to
|
|
100
|
-
* @param metadata - The xstate-tree metadata to staple to the machine
|
|
101
|
-
* @returns The xstate-tree machine, ready to be invoked by other xstate-machines or used with `buildRootComponent`
|
|
102
|
-
* @deprecated use {@link createXStateTreeMachine} instead
|
|
103
|
-
*/
|
|
104
|
-
function buildXStateTreeMachine(machine, meta) {
|
|
105
|
-
const copiedMeta = { ...meta };
|
|
106
|
-
copiedMeta.xstateTreeMachine = true;
|
|
107
|
-
machine.config.meta = {
|
|
108
|
-
...machine.config.meta,
|
|
109
|
-
...copiedMeta,
|
|
110
|
-
builderVersion: 1,
|
|
111
|
-
};
|
|
112
|
-
machine.meta = { ...machine.meta, ...copiedMeta, builderVersion: 1 };
|
|
113
|
-
return machine;
|
|
114
|
-
}
|
|
115
|
-
exports.buildXStateTreeMachine = buildXStateTreeMachine;
|
|
116
10
|
/**
|
|
117
11
|
* @public
|
|
118
12
|
* Creates an xstate-tree machine from an xstate-machine
|
|
@@ -128,26 +22,16 @@ exports.buildXStateTreeMachine = buildXStateTreeMachine;
|
|
|
128
22
|
* @param options - the xstate-tree options
|
|
129
23
|
*/
|
|
130
24
|
function createXStateTreeMachine(machine, options) {
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
selectors,
|
|
136
|
-
actions,
|
|
25
|
+
const selectors = options.selectors ?? (({ ctx }) => ctx);
|
|
26
|
+
const actions = options.actions ?? (() => ({}));
|
|
27
|
+
const machineWithMeta = machine;
|
|
28
|
+
machineWithMeta._xstateTree = {
|
|
29
|
+
selectors: selectors,
|
|
30
|
+
actions: actions,
|
|
137
31
|
View: options.View,
|
|
138
|
-
slots: (
|
|
139
|
-
};
|
|
140
|
-
machine.meta = {
|
|
141
|
-
...machine.meta,
|
|
142
|
-
...xstateTreeMeta,
|
|
143
|
-
builderVersion: 2,
|
|
144
|
-
};
|
|
145
|
-
machine.config.meta = {
|
|
146
|
-
...machine.config.meta,
|
|
147
|
-
...xstateTreeMeta,
|
|
148
|
-
builderVersion: 2,
|
|
32
|
+
slots: (options.slots ?? []),
|
|
149
33
|
};
|
|
150
|
-
return
|
|
34
|
+
return machineWithMeta;
|
|
151
35
|
}
|
|
152
36
|
exports.createXStateTreeMachine = createXStateTreeMachine;
|
|
153
37
|
/**
|
|
@@ -186,9 +70,7 @@ function buildRoutingMachine(_routes, mappings) {
|
|
|
186
70
|
...acc,
|
|
187
71
|
[event]: {
|
|
188
72
|
invoke: {
|
|
189
|
-
src:
|
|
190
|
-
return mappings[e.type];
|
|
191
|
-
},
|
|
73
|
+
src: event,
|
|
192
74
|
id: contentSlot.getId(),
|
|
193
75
|
},
|
|
194
76
|
},
|
|
@@ -200,7 +82,9 @@ function buildRoutingMachine(_routes, mappings) {
|
|
|
200
82
|
target: `.${event}`,
|
|
201
83
|
},
|
|
202
84
|
}), {});
|
|
203
|
-
const machine = (0, xstate_1.
|
|
85
|
+
const machine = (0, xstate_1.setup)({
|
|
86
|
+
actors: mappings,
|
|
87
|
+
}).createMachine({
|
|
204
88
|
on: {
|
|
205
89
|
...mappingsToEvents,
|
|
206
90
|
},
|
package/lib/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.lazy = exports.loggingMetaOptions = exports.TestRoutingContext = exports.useActiveRouteEvents = exports.useRouteArgsIfActive = exports.useIsRouteActive = exports.matchRoute = exports.buildCreateRoute = exports.Link = exports.
|
|
17
|
+
exports.lazy = exports.loggingMetaOptions = exports.TestRoutingContext = exports.useActiveRouteEvents = exports.useRouteArgsIfActive = exports.useIsRouteActive = exports.matchRoute = exports.buildCreateRoute = exports.Link = exports.genericSlotsTestingDummy = exports.onBroadcast = exports.buildRootComponent = exports.broadcast = void 0;
|
|
18
18
|
__exportStar(require("./builders"), exports);
|
|
19
19
|
__exportStar(require("./slots"), exports);
|
|
20
20
|
var xstateTree_1 = require("./xstateTree");
|
|
@@ -23,10 +23,7 @@ Object.defineProperty(exports, "buildRootComponent", { enumerable: true, get: fu
|
|
|
23
23
|
Object.defineProperty(exports, "onBroadcast", { enumerable: true, get: function () { return xstateTree_1.onBroadcast; } });
|
|
24
24
|
__exportStar(require("./types"), exports);
|
|
25
25
|
var testingUtilities_1 = require("./testingUtilities");
|
|
26
|
-
Object.defineProperty(exports, "buildTestRootComponent", { enumerable: true, get: function () { return testingUtilities_1.buildTestRootComponent; } });
|
|
27
|
-
Object.defineProperty(exports, "buildViewProps", { enumerable: true, get: function () { return testingUtilities_1.buildViewProps; } });
|
|
28
26
|
Object.defineProperty(exports, "genericSlotsTestingDummy", { enumerable: true, get: function () { return testingUtilities_1.genericSlotsTestingDummy; } });
|
|
29
|
-
Object.defineProperty(exports, "slotTestingDummyFactory", { enumerable: true, get: function () { return testingUtilities_1.slotTestingDummyFactory; } });
|
|
30
27
|
var routing_1 = require("./routing");
|
|
31
28
|
Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return routing_1.Link; } });
|
|
32
29
|
Object.defineProperty(exports, "buildCreateRoute", { enumerable: true, get: function () { return routing_1.buildCreateRoute; } });
|
package/lib/lazy.js
CHANGED
|
@@ -18,41 +18,41 @@ const slots_1 = require("./slots");
|
|
|
18
18
|
* @param options - configure loading component and context to invoke machine with
|
|
19
19
|
* @returns an xstate-tree machine that wraps the promise, invoking the resulting machine when it resolves
|
|
20
20
|
*/
|
|
21
|
-
function lazy(factory, { Loader = () => null,
|
|
21
|
+
function lazy(factory, { Loader = () => null, input } = {}) {
|
|
22
22
|
const loadedMachineSlot = (0, slots_1.singleSlot)("loadedMachine");
|
|
23
23
|
const slots = [loadedMachineSlot];
|
|
24
|
-
const machine = (0, xstate_1.
|
|
24
|
+
const machine = (0, xstate_1.setup)({}).createMachine({
|
|
25
25
|
initial: "loading",
|
|
26
|
+
context: {},
|
|
26
27
|
states: {
|
|
27
28
|
loading: {
|
|
28
29
|
invoke: {
|
|
29
|
-
src: ()
|
|
30
|
-
onDone:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
src: (0, xstate_1.fromPromise)(factory),
|
|
31
|
+
onDone: {
|
|
32
|
+
target: "rendering",
|
|
33
|
+
actions: (0, xstate_1.assign)({
|
|
34
|
+
loadedMachine: ({ spawn, event }) => spawn(event.output, {
|
|
35
|
+
id: loadedMachineSlot.getId(),
|
|
36
|
+
input,
|
|
37
|
+
}),
|
|
38
|
+
}),
|
|
38
39
|
},
|
|
39
40
|
},
|
|
40
41
|
},
|
|
42
|
+
rendering: {},
|
|
41
43
|
},
|
|
42
44
|
});
|
|
43
|
-
|
|
44
|
-
const actions = (0, builders_1.buildActions)(machine, selectors, (_send, _selectors) => { });
|
|
45
|
-
const view = (0, builders_1.buildView)(machine, selectors, actions, slots, ({ slots, inState }) => {
|
|
46
|
-
if (inState("loading")) {
|
|
47
|
-
return react_1.default.createElement(Loader, null);
|
|
48
|
-
}
|
|
49
|
-
return react_1.default.createElement(slots.loadedMachine, null);
|
|
50
|
-
});
|
|
51
|
-
return (0, builders_1.buildXStateTreeMachine)(machine, {
|
|
52
|
-
actions,
|
|
53
|
-
selectors,
|
|
45
|
+
return (0, builders_1.createXStateTreeMachine)(machine, {
|
|
54
46
|
slots,
|
|
55
|
-
|
|
47
|
+
selectors({ inState }) {
|
|
48
|
+
return { loading: inState("loading") };
|
|
49
|
+
},
|
|
50
|
+
View({ selectors, slots }) {
|
|
51
|
+
if (selectors.loading) {
|
|
52
|
+
return react_1.default.createElement(Loader, null);
|
|
53
|
+
}
|
|
54
|
+
return react_1.default.createElement(slots.loadedMachine, null);
|
|
55
|
+
},
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
exports.lazy = lazy;
|
package/lib/routing/Link.js
CHANGED
|
@@ -34,13 +34,13 @@ function LinkInner({ to, children, testId, preloadOnHoverMs, preloadOnInteractio
|
|
|
34
34
|
const href = (0, useHref_1.useHref)(to, params, query);
|
|
35
35
|
const onMouseDown = preloadOnInteraction
|
|
36
36
|
? (e) => {
|
|
37
|
-
_onMouseDown
|
|
37
|
+
_onMouseDown?.(e);
|
|
38
38
|
to.preload({ params, query, meta });
|
|
39
39
|
}
|
|
40
40
|
: undefined;
|
|
41
41
|
const onMouseEnter = preloadOnHoverMs !== undefined
|
|
42
42
|
? (e) => {
|
|
43
|
-
_onMouseEnter
|
|
43
|
+
_onMouseEnter?.(e);
|
|
44
44
|
timeout = setTimeout(() => {
|
|
45
45
|
to.preload({ params, query, meta });
|
|
46
46
|
}, preloadOnHoverMs);
|
|
@@ -48,15 +48,14 @@ function LinkInner({ to, children, testId, preloadOnHoverMs, preloadOnInteractio
|
|
|
48
48
|
: undefined;
|
|
49
49
|
const onMouseLeave = preloadOnHoverMs !== undefined
|
|
50
50
|
? (e) => {
|
|
51
|
-
_onMouseLeave
|
|
51
|
+
_onMouseLeave?.(e);
|
|
52
52
|
if (timeout !== undefined) {
|
|
53
53
|
clearTimeout(timeout);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
: undefined;
|
|
57
|
-
return (react_1.default.createElement("a", { ...props, ref: ref, href: href, "data-testid": testId, onMouseDown: onMouseDown
|
|
58
|
-
|
|
59
|
-
if (((_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, e)) === false) {
|
|
57
|
+
return (react_1.default.createElement("a", { ...props, ref: ref, href: href, "data-testid": testId, onMouseDown: onMouseDown ?? _onMouseDown, onMouseEnter: onMouseEnter ?? _onMouseEnter, onMouseLeave: onMouseLeave ?? _onMouseLeave, "data-xstate-tree": true, onClick: (e) => {
|
|
58
|
+
if (props.onClick?.(e) === false) {
|
|
60
59
|
return;
|
|
61
60
|
}
|
|
62
61
|
// Holding the Command key on Mac or the Control Key on Windows while clicking the link will open a new tab/window
|
|
@@ -14,7 +14,7 @@ const joinRoutes_1 = require("../joinRoutes");
|
|
|
14
14
|
*/
|
|
15
15
|
function buildCreateRoute(history, basePath) {
|
|
16
16
|
function navigate({ history, url, meta, }) {
|
|
17
|
-
const method =
|
|
17
|
+
const method = meta?.replace ? history.replace : history.push;
|
|
18
18
|
method(url, {
|
|
19
19
|
meta,
|
|
20
20
|
previousUrl: `${window.location.pathname}${window.location.search}`,
|
|
@@ -90,12 +90,11 @@ function buildCreateRoute(history, basePath) {
|
|
|
90
90
|
reverser: reverser,
|
|
91
91
|
// @ts-ignore :cry:
|
|
92
92
|
getEvent(args) {
|
|
93
|
-
const { params, query, meta } = args
|
|
93
|
+
const { params, query, meta } = args ?? {};
|
|
94
94
|
return { type: event, params, query, meta };
|
|
95
95
|
},
|
|
96
96
|
// @ts-ignore :cry:
|
|
97
97
|
matches(suppliedUrl, search) {
|
|
98
|
-
var _a, _b, _c;
|
|
99
98
|
const fullUrl = suppliedUrl.endsWith("/")
|
|
100
99
|
? suppliedUrl
|
|
101
100
|
: suppliedUrl + "/";
|
|
@@ -115,7 +114,7 @@ function buildCreateRoute(history, basePath) {
|
|
|
115
114
|
if (!url.startsWith("/")) {
|
|
116
115
|
url = "/" + url;
|
|
117
116
|
}
|
|
118
|
-
params = { ...params, ...(
|
|
117
|
+
params = { ...params, ...(parentMatch.params ?? {}) };
|
|
119
118
|
}
|
|
120
119
|
const matches = matcher(url, (0, query_string_1.parse)(search));
|
|
121
120
|
// if there is any URL left after matching this route, the last to match
|
|
@@ -125,7 +124,7 @@ function buildCreateRoute(history, basePath) {
|
|
|
125
124
|
}
|
|
126
125
|
const fullParams = {
|
|
127
126
|
...params,
|
|
128
|
-
...(
|
|
127
|
+
...(matches.params ?? {}),
|
|
129
128
|
};
|
|
130
129
|
if (fullParamsSchema) {
|
|
131
130
|
fullParamsSchema.parse(fullParams);
|
|
@@ -137,12 +136,12 @@ function buildCreateRoute(history, basePath) {
|
|
|
137
136
|
originalUrl: `${fullUrl}${search}`,
|
|
138
137
|
type: event,
|
|
139
138
|
params: fullParams,
|
|
140
|
-
query:
|
|
139
|
+
query: matches.query ?? {},
|
|
141
140
|
};
|
|
142
141
|
},
|
|
143
142
|
// @ts-ignore :cry:
|
|
144
143
|
reverse(args) {
|
|
145
|
-
const { params, query } = args
|
|
144
|
+
const { params, query } = args ?? {};
|
|
146
145
|
const parentRoutes = getParentArray();
|
|
147
146
|
const baseUrl = parentRoutes
|
|
148
147
|
.map((route) => route.reverser({ params }))
|
|
@@ -151,7 +150,7 @@ function buildCreateRoute(history, basePath) {
|
|
|
151
150
|
},
|
|
152
151
|
// @ts-ignore :cry:
|
|
153
152
|
navigate(args) {
|
|
154
|
-
const { params, query, meta } = args
|
|
153
|
+
const { params, query, meta } = args ?? {};
|
|
155
154
|
const url = this.reverse({ params, query });
|
|
156
155
|
navigate({
|
|
157
156
|
url: (0, joinRoutes_1.joinRoutes)(this.basePath, url),
|
|
@@ -163,9 +162,9 @@ function buildCreateRoute(history, basePath) {
|
|
|
163
162
|
preload(args) {
|
|
164
163
|
const parentRoutes = getParentArray();
|
|
165
164
|
parentRoutes.forEach((route) => {
|
|
166
|
-
route
|
|
165
|
+
route?.preload(args);
|
|
167
166
|
});
|
|
168
|
-
preload
|
|
167
|
+
preload?.(args);
|
|
169
168
|
},
|
|
170
169
|
};
|
|
171
170
|
};
|
|
@@ -25,14 +25,14 @@ function handleLocationChange(routes, basePath, path, search, meta) {
|
|
|
25
25
|
else {
|
|
26
26
|
console.log("[xstate-tree] matched route", match.event);
|
|
27
27
|
const matchedEvent = match.event;
|
|
28
|
-
matchedEvent.meta = { ...(meta
|
|
28
|
+
matchedEvent.meta = { ...(meta ?? {}) };
|
|
29
29
|
matchedEvent.meta.indexEvent = true;
|
|
30
30
|
const { params, query } = match.event;
|
|
31
31
|
const routingEvents = [];
|
|
32
32
|
let route = match.route;
|
|
33
33
|
route.preload({ params, query, meta: matchedEvent.meta });
|
|
34
34
|
while (route.parent) {
|
|
35
|
-
routingEvents.push(route.parent.getEvent({ params, query: {}, meta: { ...(meta
|
|
35
|
+
routingEvents.push(route.parent.getEvent({ params, query: {}, meta: { ...(meta ?? {}) } }));
|
|
36
36
|
route = route.parent;
|
|
37
37
|
}
|
|
38
38
|
const clonedRoutingEvents = [...routingEvents];
|
|
@@ -5,7 +5,6 @@ exports.matchRoute = void 0;
|
|
|
5
5
|
* @public
|
|
6
6
|
*/
|
|
7
7
|
function matchRoute(routes, basePath, path, search) {
|
|
8
|
-
var _a;
|
|
9
8
|
const realBase = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
10
9
|
const realPath = (() => {
|
|
11
10
|
if (path.startsWith(realBase) && realBase.length > 0) {
|
|
@@ -13,7 +12,7 @@ function matchRoute(routes, basePath, path, search) {
|
|
|
13
12
|
}
|
|
14
13
|
return path;
|
|
15
14
|
})();
|
|
16
|
-
const [matchingRoute, event] =
|
|
15
|
+
const [matchingRoute, event] = routes
|
|
17
16
|
.map((route) => {
|
|
18
17
|
try {
|
|
19
18
|
const match = route.matches(realPath, search);
|
|
@@ -28,7 +27,7 @@ function matchRoute(routes, basePath, path, search) {
|
|
|
28
27
|
}
|
|
29
28
|
return [undefined, undefined];
|
|
30
29
|
})
|
|
31
|
-
.find(([match]) => Boolean(match))
|
|
30
|
+
.find(([match]) => Boolean(match)) ?? [undefined, undefined];
|
|
32
31
|
if (matchingRoute === undefined) {
|
|
33
32
|
return { type: "no-matches" };
|
|
34
33
|
}
|
package/lib/routing/providers.js
CHANGED
|
@@ -28,12 +28,11 @@ exports.useInRoutingContext = useInRoutingContext;
|
|
|
28
28
|
* Returns the list of active routing events, or undefined if there are none / used outside of an xstate-tree routing context
|
|
29
29
|
*/
|
|
30
30
|
function useActiveRouteEvents() {
|
|
31
|
-
var _a;
|
|
32
31
|
try {
|
|
33
32
|
const context = useRoutingContext();
|
|
34
|
-
return
|
|
33
|
+
return context.activeRouteEvents?.current;
|
|
35
34
|
}
|
|
36
|
-
catch
|
|
35
|
+
catch {
|
|
37
36
|
return undefined;
|
|
38
37
|
}
|
|
39
38
|
}
|
|
@@ -19,7 +19,7 @@ function useRouteArgsIfActive(route) {
|
|
|
19
19
|
if (!isActive) {
|
|
20
20
|
return undefined;
|
|
21
21
|
}
|
|
22
|
-
const activeRoute = activeRoutes
|
|
22
|
+
const activeRoute = activeRoutes?.find((activeRoute) => activeRoute.type === route.event);
|
|
23
23
|
(0, utils_1.assertIsDefined)(activeRoute, "active route is not defined, but the route is active??");
|
|
24
24
|
return {
|
|
25
25
|
params: activeRoute.params,
|
package/lib/testingUtilities.js
CHANGED
|
@@ -1,61 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
4
|
};
|
|
25
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
6
|
+
exports.genericSlotsTestingDummy = void 0;
|
|
27
7
|
// ignore file coverage
|
|
28
|
-
const react_1 = require("
|
|
29
|
-
const react_2 = __importStar(require("react"));
|
|
30
|
-
const tiny_emitter_1 = require("tiny-emitter");
|
|
31
|
-
const xstate_1 = require("xstate");
|
|
32
|
-
const builders_1 = require("./builders");
|
|
33
|
-
const utils_1 = require("./utils");
|
|
34
|
-
const xstateTree_1 = require("./xstateTree");
|
|
35
|
-
/**
|
|
36
|
-
* @public
|
|
37
|
-
*
|
|
38
|
-
* Creates a dummy machine that just renders the supplied string - useful for rendering xstate-tree views in isolation
|
|
39
|
-
*
|
|
40
|
-
* @param name - the string to render in the machines view
|
|
41
|
-
* @returns a dummy machine that renders a div containing the supplied string
|
|
42
|
-
*/
|
|
43
|
-
function slotTestingDummyFactory(name) {
|
|
44
|
-
return (0, builders_1.buildXStateTreeMachine)((0, xstate_1.createMachine)({
|
|
45
|
-
id: name,
|
|
46
|
-
initial: "idle",
|
|
47
|
-
states: {
|
|
48
|
-
idle: {},
|
|
49
|
-
},
|
|
50
|
-
}), {
|
|
51
|
-
actions: () => ({}),
|
|
52
|
-
selectors: () => ({}),
|
|
53
|
-
slots: [],
|
|
54
|
-
view: () => (react_2.default.createElement("div", null,
|
|
55
|
-
react_2.default.createElement("p", null, name))),
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
exports.slotTestingDummyFactory = slotTestingDummyFactory;
|
|
8
|
+
const react_1 = __importDefault(require("react"));
|
|
59
9
|
/**
|
|
60
10
|
* @public
|
|
61
11
|
*
|
|
@@ -63,98 +13,10 @@ exports.slotTestingDummyFactory = slotTestingDummyFactory;
|
|
|
63
13
|
*/
|
|
64
14
|
exports.genericSlotsTestingDummy = new Proxy({}, {
|
|
65
15
|
get(_target, prop) {
|
|
66
|
-
return () => (
|
|
67
|
-
|
|
68
|
-
|
|
16
|
+
return () => (react_1.default.createElement("div", null,
|
|
17
|
+
react_1.default.createElement("p", null,
|
|
18
|
+
react_1.default.createElement(react_1.default.Fragment, null,
|
|
69
19
|
prop,
|
|
70
20
|
"-slot"))));
|
|
71
21
|
},
|
|
72
22
|
});
|
|
73
|
-
/**
|
|
74
|
-
* @public
|
|
75
|
-
*
|
|
76
|
-
* Aids in type inference for creating props objects for xstate-tree views.
|
|
77
|
-
*
|
|
78
|
-
* @param view - The view to create props for
|
|
79
|
-
* @param props - The actions/selectors props to pass to the view
|
|
80
|
-
* @returns An object with the view's selectors, actions, and inState function props
|
|
81
|
-
*/
|
|
82
|
-
function buildViewProps(_view, props) {
|
|
83
|
-
return {
|
|
84
|
-
...props,
|
|
85
|
-
inState: (testState) => (state) => state === testState || testState.startsWith(state),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
exports.buildViewProps = buildViewProps;
|
|
89
|
-
/**
|
|
90
|
-
* @public
|
|
91
|
-
*
|
|
92
|
-
* Sets up a root component for use in an \@xstate/test model backed by \@testing-library/react for the component
|
|
93
|
-
*
|
|
94
|
-
* The logger argument should just be a simple function which forwards the arguments to console.log,
|
|
95
|
-
* this is needed because Wallaby.js only displays console logs in tests that come from source code, not library code,
|
|
96
|
-
* so any logs from inside this file don't show up in the test explorer
|
|
97
|
-
*
|
|
98
|
-
* The returned object has a `rootComponent` property and a function, `awaitTransition`, that returns a Promise
|
|
99
|
-
* when called that is resolved the next time the underlying machine transitions. This can be used in the \@xstate/test
|
|
100
|
-
* model to ensure after an event action is executed the test in the next state doesn't run until after the machine transitions
|
|
101
|
-
*
|
|
102
|
-
* It also delays for 5ms to ensure any React re-rendering happens in response to the state transition
|
|
103
|
-
*/
|
|
104
|
-
function buildTestRootComponent(machine, logger) {
|
|
105
|
-
if (!machine.meta) {
|
|
106
|
-
throw new Error("Root machine has no meta");
|
|
107
|
-
}
|
|
108
|
-
if ((machine.meta.builderVersion === 1 && !machine.meta.view) ||
|
|
109
|
-
(machine.meta.builderVersion === 2 && !machine.meta.View)) {
|
|
110
|
-
throw new Error("Root machine has no associated view");
|
|
111
|
-
}
|
|
112
|
-
const onChangeEmitter = new tiny_emitter_1.TinyEmitter();
|
|
113
|
-
function addTransitionListener(listener) {
|
|
114
|
-
onChangeEmitter.once("transition", listener);
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
rootComponent: function XstateTreeRootComponent() {
|
|
118
|
-
const [_, __, interpreter] = (0, react_1.useMachine)(machine, { devTools: true });
|
|
119
|
-
(0, react_2.useEffect)(() => {
|
|
120
|
-
function handler(event) {
|
|
121
|
-
(0, xstateTree_1.recursivelySend)(interpreter, event);
|
|
122
|
-
}
|
|
123
|
-
function changeHandler(ctx, oldCtx) {
|
|
124
|
-
logger("onChange: ", (0, utils_1.difference)(oldCtx, ctx));
|
|
125
|
-
onChangeEmitter.emit("changed", ctx);
|
|
126
|
-
}
|
|
127
|
-
function onEventHandler(e) {
|
|
128
|
-
logger("onEvent", e);
|
|
129
|
-
}
|
|
130
|
-
function onTransitionHandler(s) {
|
|
131
|
-
logger("State: ", s.value);
|
|
132
|
-
onChangeEmitter.emit("transition");
|
|
133
|
-
}
|
|
134
|
-
interpreter.onChange(changeHandler);
|
|
135
|
-
interpreter.onEvent(onEventHandler);
|
|
136
|
-
interpreter.onTransition(onTransitionHandler);
|
|
137
|
-
xstateTree_1.emitter.on("event", handler);
|
|
138
|
-
return () => {
|
|
139
|
-
xstateTree_1.emitter.off("event", handler);
|
|
140
|
-
interpreter.off(changeHandler);
|
|
141
|
-
interpreter.off(onEventHandler);
|
|
142
|
-
interpreter.off(onTransitionHandler);
|
|
143
|
-
};
|
|
144
|
-
}, [interpreter]);
|
|
145
|
-
if (!interpreter.initialized) {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
return react_2.default.createElement(xstateTree_1.XstateTreeView, { interpreter: interpreter });
|
|
149
|
-
},
|
|
150
|
-
addTransitionListener,
|
|
151
|
-
awaitTransition() {
|
|
152
|
-
return new Promise((res) => {
|
|
153
|
-
addTransitionListener(() => {
|
|
154
|
-
setTimeout(res, 50);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
exports.buildTestRootComponent = buildTestRootComponent;
|