@koordinates/xstate-tree 4.3.0-beta.1 → 4.3.0-beta.2
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 +18 -7
- package/lib/index.js +40 -8
- package/lib/lazy.js +20 -13
- package/lib/routing/Link.js +12 -5
- package/lib/routing/createRoute/createRoute.js +15 -11
- package/lib/routing/createRoute/index.js +5 -1
- package/lib/routing/handleLocationChange/handleLocationChange.js +11 -7
- package/lib/routing/handleLocationChange/index.js +5 -1
- package/lib/routing/index.js +20 -8
- package/lib/routing/joinRoutes.js +5 -1
- package/lib/routing/matchRoute/index.js +5 -1
- package/lib/routing/matchRoute/matchRoute.js +5 -1
- package/lib/routing/providers.js +15 -7
- package/lib/routing/routingEvent.js +2 -1
- package/lib/routing/useHref.js +7 -3
- package/lib/routing/useIsRouteActive.js +7 -3
- package/lib/routing/useRouteArgsIfActive.js +11 -7
- package/lib/setupScript.js +3 -1
- package/lib/slots/index.js +17 -1
- package/lib/slots/slots.js +9 -4
- package/lib/testingUtilities.js +54 -25
- package/lib/types.js +2 -1
- package/lib/useConstant.js +7 -3
- package/lib/useService.js +16 -11
- package/lib/utils.js +17 -7
- package/lib/xstateTree.js +97 -61
- package/package.json +1 -1
package/lib/testingUtilities.js
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
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;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.buildTestRootComponent = exports.buildViewProps = exports.genericSlotsTestingDummy = exports.slotTestingDummyFactory = void 0;
|
|
1
27
|
// ignore file coverage
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
28
|
+
const react_1 = require("@xstate/react");
|
|
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");
|
|
9
35
|
/**
|
|
10
36
|
* @public
|
|
11
37
|
*
|
|
@@ -14,8 +40,8 @@ import { emitter, recursivelySend, XstateTreeView } from "./xstateTree";
|
|
|
14
40
|
* @param name - the string to render in the machines view
|
|
15
41
|
* @returns a dummy machine that renders a div containing the supplied string
|
|
16
42
|
*/
|
|
17
|
-
|
|
18
|
-
return buildXStateTreeMachine(createMachine({
|
|
43
|
+
function slotTestingDummyFactory(name) {
|
|
44
|
+
return (0, builders_1.buildXStateTreeMachine)((0, xstate_1.createMachine)({
|
|
19
45
|
id: name,
|
|
20
46
|
initial: "idle",
|
|
21
47
|
states: {
|
|
@@ -25,20 +51,21 @@ export function slotTestingDummyFactory(name) {
|
|
|
25
51
|
actions: () => ({}),
|
|
26
52
|
selectors: () => ({}),
|
|
27
53
|
slots: [],
|
|
28
|
-
view: () => (
|
|
29
|
-
|
|
54
|
+
view: () => (react_2.default.createElement("div", null,
|
|
55
|
+
react_2.default.createElement("p", null, name))),
|
|
30
56
|
});
|
|
31
57
|
}
|
|
58
|
+
exports.slotTestingDummyFactory = slotTestingDummyFactory;
|
|
32
59
|
/**
|
|
33
60
|
* @public
|
|
34
61
|
*
|
|
35
62
|
* Can be used as the slots prop for an xstate-tree view, will render a div containing a <p>slotName-slot<p> for each slot
|
|
36
63
|
*/
|
|
37
|
-
|
|
64
|
+
exports.genericSlotsTestingDummy = new Proxy({}, {
|
|
38
65
|
get(_target, prop) {
|
|
39
|
-
return () => (
|
|
40
|
-
|
|
41
|
-
|
|
66
|
+
return () => (react_2.default.createElement("div", null,
|
|
67
|
+
react_2.default.createElement("p", null,
|
|
68
|
+
react_2.default.createElement(react_2.default.Fragment, null,
|
|
42
69
|
prop,
|
|
43
70
|
"-slot"))));
|
|
44
71
|
},
|
|
@@ -52,12 +79,13 @@ export const genericSlotsTestingDummy = new Proxy({}, {
|
|
|
52
79
|
* @param props - The actions/selectors props to pass to the view
|
|
53
80
|
* @returns An object with the view's selectors, actions, and inState function props
|
|
54
81
|
*/
|
|
55
|
-
|
|
82
|
+
function buildViewProps(_view, props) {
|
|
56
83
|
return {
|
|
57
84
|
...props,
|
|
58
85
|
inState: (testState) => (state) => state === testState || testState.startsWith(state),
|
|
59
86
|
};
|
|
60
87
|
}
|
|
88
|
+
exports.buildViewProps = buildViewProps;
|
|
61
89
|
/**
|
|
62
90
|
* @public
|
|
63
91
|
*
|
|
@@ -73,7 +101,7 @@ export function buildViewProps(_view, props) {
|
|
|
73
101
|
*
|
|
74
102
|
* It also delays for 5ms to ensure any React re-rendering happens in response to the state transition
|
|
75
103
|
*/
|
|
76
|
-
|
|
104
|
+
function buildTestRootComponent(machine, logger) {
|
|
77
105
|
if (!machine.meta) {
|
|
78
106
|
throw new Error("Root machine has no meta");
|
|
79
107
|
}
|
|
@@ -81,19 +109,19 @@ export function buildTestRootComponent(machine, logger) {
|
|
|
81
109
|
(machine.meta.builderVersion === 2 && !machine.meta.View)) {
|
|
82
110
|
throw new Error("Root machine has no associated view");
|
|
83
111
|
}
|
|
84
|
-
const onChangeEmitter = new TinyEmitter();
|
|
112
|
+
const onChangeEmitter = new tiny_emitter_1.TinyEmitter();
|
|
85
113
|
function addTransitionListener(listener) {
|
|
86
114
|
onChangeEmitter.once("transition", listener);
|
|
87
115
|
}
|
|
88
116
|
return {
|
|
89
117
|
rootComponent: function XstateTreeRootComponent() {
|
|
90
|
-
const [_, __, interpreter] = useMachine(machine, { devTools: true });
|
|
91
|
-
useEffect(() => {
|
|
118
|
+
const [_, __, interpreter] = (0, react_1.useMachine)(machine, { devTools: true });
|
|
119
|
+
(0, react_2.useEffect)(() => {
|
|
92
120
|
function handler(event) {
|
|
93
|
-
recursivelySend(interpreter, event);
|
|
121
|
+
(0, xstateTree_1.recursivelySend)(interpreter, event);
|
|
94
122
|
}
|
|
95
123
|
function changeHandler(ctx, oldCtx) {
|
|
96
|
-
logger("onChange: ", JSON.stringify(difference(ctx, oldCtx), null, 2));
|
|
124
|
+
logger("onChange: ", JSON.stringify((0, utils_1.difference)(ctx, oldCtx), null, 2));
|
|
97
125
|
onChangeEmitter.emit("changed", ctx);
|
|
98
126
|
}
|
|
99
127
|
function onEventHandler(e) {
|
|
@@ -106,9 +134,9 @@ export function buildTestRootComponent(machine, logger) {
|
|
|
106
134
|
interpreter.onChange(changeHandler);
|
|
107
135
|
interpreter.onEvent(onEventHandler);
|
|
108
136
|
interpreter.onTransition(onTransitionHandler);
|
|
109
|
-
emitter.on("event", handler);
|
|
137
|
+
xstateTree_1.emitter.on("event", handler);
|
|
110
138
|
return () => {
|
|
111
|
-
emitter.off("event", handler);
|
|
139
|
+
xstateTree_1.emitter.off("event", handler);
|
|
112
140
|
interpreter.off(changeHandler);
|
|
113
141
|
interpreter.off(onEventHandler);
|
|
114
142
|
interpreter.off(onTransitionHandler);
|
|
@@ -117,7 +145,7 @@ export function buildTestRootComponent(machine, logger) {
|
|
|
117
145
|
if (!interpreter.initialized) {
|
|
118
146
|
return null;
|
|
119
147
|
}
|
|
120
|
-
return
|
|
148
|
+
return react_2.default.createElement(xstateTree_1.XstateTreeView, { interpreter: interpreter });
|
|
121
149
|
},
|
|
122
150
|
addTransitionListener,
|
|
123
151
|
awaitTransition() {
|
|
@@ -129,3 +157,4 @@ export function buildTestRootComponent(machine, logger) {
|
|
|
129
157
|
},
|
|
130
158
|
};
|
|
131
159
|
}
|
|
160
|
+
exports.buildTestRootComponent = buildTestRootComponent;
|
package/lib/types.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/lib/useConstant.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useConstant = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function useConstant(fn) {
|
|
6
|
+
const ref = (0, react_1.useRef)();
|
|
4
7
|
if (!ref.current) {
|
|
5
8
|
ref.current = { v: fn() };
|
|
6
9
|
}
|
|
7
10
|
return ref.current.v;
|
|
8
11
|
}
|
|
12
|
+
exports.useConstant = useConstant;
|
package/lib/useService.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useService = exports.loggingMetaOptions = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
3
6
|
/**
|
|
4
7
|
* @public
|
|
5
8
|
*/
|
|
6
|
-
|
|
9
|
+
function loggingMetaOptions(ignoredEvents, ignoreContext = undefined) {
|
|
7
10
|
const ignoredEventMap = new Map();
|
|
8
11
|
ignoredEvents.forEach((event) => {
|
|
9
12
|
ignoredEventMap.set(event, true);
|
|
@@ -15,17 +18,18 @@ export function loggingMetaOptions(ignoredEvents, ignoreContext = undefined) {
|
|
|
15
18
|
},
|
|
16
19
|
};
|
|
17
20
|
}
|
|
21
|
+
exports.loggingMetaOptions = loggingMetaOptions;
|
|
18
22
|
/**
|
|
19
23
|
* @internal
|
|
20
24
|
*/
|
|
21
|
-
|
|
22
|
-
const [current, setCurrent] = useState(service.state);
|
|
23
|
-
const [children, setChildren] = useState(service.children);
|
|
24
|
-
const childrenRef = useRef(new Map());
|
|
25
|
-
useEffect(() => {
|
|
25
|
+
function useService(service) {
|
|
26
|
+
const [current, setCurrent] = (0, react_1.useState)(service.state);
|
|
27
|
+
const [children, setChildren] = (0, react_1.useState)(service.children);
|
|
28
|
+
const childrenRef = (0, react_1.useRef)(new Map());
|
|
29
|
+
(0, react_1.useEffect)(() => {
|
|
26
30
|
childrenRef.current = children;
|
|
27
31
|
}, [children]);
|
|
28
|
-
useEffect(function () {
|
|
32
|
+
(0, react_1.useEffect)(function () {
|
|
29
33
|
// Set to current service state as there is a possibility
|
|
30
34
|
// of a transition occurring between the initial useState()
|
|
31
35
|
// initialization and useEffect() commit.
|
|
@@ -34,7 +38,7 @@ export function useService(service) {
|
|
|
34
38
|
const listener = function (state) {
|
|
35
39
|
if (state.changed) {
|
|
36
40
|
setCurrent(state);
|
|
37
|
-
if (!isEqual(childrenRef.current, service.children)) {
|
|
41
|
+
if (!(0, utils_1.isEqual)(childrenRef.current, service.children)) {
|
|
38
42
|
setChildren(new Map(service.children));
|
|
39
43
|
}
|
|
40
44
|
}
|
|
@@ -44,7 +48,7 @@ export function useService(service) {
|
|
|
44
48
|
sub.unsubscribe();
|
|
45
49
|
};
|
|
46
50
|
}, [service, setChildren]);
|
|
47
|
-
useEffect(() => {
|
|
51
|
+
(0, react_1.useEffect)(() => {
|
|
48
52
|
function handler(event) {
|
|
49
53
|
var _a, _b, _c;
|
|
50
54
|
if (event.type.includes("done")) {
|
|
@@ -81,3 +85,4 @@ export function useService(service) {
|
|
|
81
85
|
children,
|
|
82
86
|
];
|
|
83
87
|
}
|
|
88
|
+
exports.useService = useService;
|
package/lib/utils.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isNil = exports.isEqual = exports.difference = exports.isLikelyPageLoad = exports.assert = exports.assertIsDefined = exports.delay = void 0;
|
|
4
|
+
function delay(ms = 0) {
|
|
2
5
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3
6
|
}
|
|
4
|
-
|
|
7
|
+
exports.delay = delay;
|
|
8
|
+
function assertIsDefined(val, msg) {
|
|
5
9
|
if (val === undefined || val === null) {
|
|
6
10
|
throw new Error(`Expected 'val' to be defined, but received ${val} ${msg ? `(${msg})` : ""}`);
|
|
7
11
|
}
|
|
8
12
|
}
|
|
9
|
-
|
|
13
|
+
exports.assertIsDefined = assertIsDefined;
|
|
14
|
+
function assert(value, msg) {
|
|
10
15
|
if (typeof expect !== "undefined") {
|
|
11
16
|
if (value !== true && msg) {
|
|
12
17
|
console.error(msg);
|
|
@@ -20,7 +25,8 @@ export function assert(value, msg) {
|
|
|
20
25
|
throw new Error("assertion failed");
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
|
-
|
|
28
|
+
exports.assert = assert;
|
|
29
|
+
function isLikelyPageLoad() {
|
|
24
30
|
// without performance API, we can't tell if this is a page load
|
|
25
31
|
if (typeof performance === "undefined") {
|
|
26
32
|
return false;
|
|
@@ -28,6 +34,7 @@ export function isLikelyPageLoad() {
|
|
|
28
34
|
// if it's been < 5 seconds since the page was loaded, it's probably a page load
|
|
29
35
|
return performance.now() < 5000;
|
|
30
36
|
}
|
|
37
|
+
exports.isLikelyPageLoad = isLikelyPageLoad;
|
|
31
38
|
/*
|
|
32
39
|
* @private
|
|
33
40
|
*
|
|
@@ -37,7 +44,7 @@ export function isLikelyPageLoad() {
|
|
|
37
44
|
* @param {Object} obj2 The object to compare against it
|
|
38
45
|
* @return {Object} An object of differences between the two
|
|
39
46
|
*/
|
|
40
|
-
|
|
47
|
+
function difference(obj1, obj2) {
|
|
41
48
|
if (!obj2 || Object.prototype.toString.call(obj2) !== "[object Object]") {
|
|
42
49
|
return obj1;
|
|
43
50
|
}
|
|
@@ -113,6 +120,7 @@ export function difference(obj1, obj2) {
|
|
|
113
120
|
}
|
|
114
121
|
return diffs;
|
|
115
122
|
}
|
|
123
|
+
exports.difference = difference;
|
|
116
124
|
/*
|
|
117
125
|
* @private
|
|
118
126
|
*
|
|
@@ -122,7 +130,7 @@ export function difference(obj1, obj2) {
|
|
|
122
130
|
* @param {*} obj2 The second item
|
|
123
131
|
* @return {Boolean} Returns true if they're equal in value
|
|
124
132
|
*/
|
|
125
|
-
|
|
133
|
+
function isEqual(obj1, obj2) {
|
|
126
134
|
/**
|
|
127
135
|
* More accurately check the type of a JavaScript object
|
|
128
136
|
* @param {Object} obj The object
|
|
@@ -168,8 +176,10 @@ export function isEqual(obj1, obj2) {
|
|
|
168
176
|
return areFunctionsEqual();
|
|
169
177
|
return arePrimitivesEqual();
|
|
170
178
|
}
|
|
171
|
-
|
|
179
|
+
exports.isEqual = isEqual;
|
|
180
|
+
function isNil(
|
|
172
181
|
// eslint-disable-next-line @rushstack/no-new-null
|
|
173
182
|
value) {
|
|
174
183
|
return value === null || value === undefined;
|
|
175
184
|
}
|
|
185
|
+
exports.isNil = isNil;
|
package/lib/xstateTree.js
CHANGED
|
@@ -1,13 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
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;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.buildRootComponent = exports.recursivelySend = exports.XstateTreeView = exports.getMultiSlotViewForChildren = exports.onBroadcast = exports.broadcast = exports.emitter = void 0;
|
|
30
|
+
const react_1 = require("@xstate/react");
|
|
31
|
+
const fast_memoize_1 = __importDefault(require("fast-memoize"));
|
|
32
|
+
const react_2 = __importStar(require("react"));
|
|
33
|
+
const tiny_emitter_1 = require("tiny-emitter");
|
|
34
|
+
const routing_1 = require("./routing");
|
|
35
|
+
const providers_1 = require("./routing/providers");
|
|
36
|
+
const useConstant_1 = require("./useConstant");
|
|
37
|
+
const useService_1 = require("./useService");
|
|
38
|
+
const utils_1 = require("./utils");
|
|
39
|
+
exports.emitter = new tiny_emitter_1.TinyEmitter();
|
|
11
40
|
/**
|
|
12
41
|
* @public
|
|
13
42
|
*
|
|
@@ -15,10 +44,11 @@ export const emitter = new TinyEmitter();
|
|
|
15
44
|
*
|
|
16
45
|
* @param event - the event to broadcast
|
|
17
46
|
*/
|
|
18
|
-
|
|
47
|
+
function broadcast(event) {
|
|
19
48
|
console.debug("[xstate-tree] broadcasting event ", event.type);
|
|
20
|
-
emitter.emit("event", event);
|
|
49
|
+
exports.emitter.emit("event", event);
|
|
21
50
|
}
|
|
51
|
+
exports.broadcast = broadcast;
|
|
22
52
|
/**
|
|
23
53
|
* @public
|
|
24
54
|
*
|
|
@@ -26,21 +56,22 @@ export function broadcast(event) {
|
|
|
26
56
|
*
|
|
27
57
|
* @param handler - the handler to call when an event is broadcast
|
|
28
58
|
*/
|
|
29
|
-
|
|
30
|
-
emitter.on("event", handler);
|
|
59
|
+
function onBroadcast(handler) {
|
|
60
|
+
exports.emitter.on("event", handler);
|
|
31
61
|
return () => {
|
|
32
|
-
emitter.off("event", handler);
|
|
62
|
+
exports.emitter.off("event", handler);
|
|
33
63
|
};
|
|
34
64
|
}
|
|
65
|
+
exports.onBroadcast = onBroadcast;
|
|
35
66
|
function cacheKeyForInterpreter(
|
|
36
67
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
37
68
|
interpreter) {
|
|
38
69
|
return interpreter.sessionId;
|
|
39
70
|
}
|
|
40
|
-
const getViewForInterpreter =
|
|
41
|
-
return
|
|
42
|
-
const activeRouteEvents = useActiveRouteEvents();
|
|
43
|
-
useEffect(() => {
|
|
71
|
+
const getViewForInterpreter = (0, fast_memoize_1.default)((interpreter) => {
|
|
72
|
+
return react_2.default.memo(function InterpreterView() {
|
|
73
|
+
const activeRouteEvents = (0, providers_1.useActiveRouteEvents)();
|
|
74
|
+
(0, react_2.useEffect)(() => {
|
|
44
75
|
if (activeRouteEvents) {
|
|
45
76
|
activeRouteEvents.forEach((event) => {
|
|
46
77
|
if (interpreter.state.nextEvents.includes(event.type)) {
|
|
@@ -49,7 +80,7 @@ const getViewForInterpreter = memoize((interpreter) => {
|
|
|
49
80
|
});
|
|
50
81
|
}
|
|
51
82
|
}, []);
|
|
52
|
-
return
|
|
83
|
+
return react_2.default.createElement(XstateTreeView, { interpreter: interpreter });
|
|
53
84
|
});
|
|
54
85
|
},
|
|
55
86
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -57,35 +88,35 @@ const getViewForInterpreter = memoize((interpreter) => {
|
|
|
57
88
|
/**
|
|
58
89
|
* @private
|
|
59
90
|
*/
|
|
60
|
-
|
|
61
|
-
return
|
|
62
|
-
const [_, children] = useService(parent);
|
|
91
|
+
exports.getMultiSlotViewForChildren = (0, fast_memoize_1.default)((parent, slot) => {
|
|
92
|
+
return react_2.default.memo(function MultiSlotView() {
|
|
93
|
+
const [_, children] = (0, useService_1.useService)(parent);
|
|
63
94
|
const interpreters = [...children.values()];
|
|
64
95
|
// Once the interpreter is stopped, initialized gets set to false
|
|
65
96
|
// We don't want to render stopped interpreters
|
|
66
97
|
const interpretersWeCareAbout = interpreters.filter((i) => i.id.includes(slot) && i.initialized);
|
|
67
|
-
return (
|
|
98
|
+
return (react_2.default.createElement(XstateTreeMultiSlotView, { childInterpreters: interpretersWeCareAbout }));
|
|
68
99
|
});
|
|
69
100
|
}, {
|
|
70
101
|
serializer: (args) => `${cacheKeyForInterpreter(args[0])}-${args[1]}`,
|
|
71
102
|
});
|
|
72
103
|
function useSlots(interpreter, slots) {
|
|
73
|
-
return useConstant(() => {
|
|
104
|
+
return (0, useConstant_1.useConstant)(() => {
|
|
74
105
|
return slots.reduce((views, slot) => {
|
|
75
106
|
return {
|
|
76
107
|
...views,
|
|
77
108
|
[slot]: () => {
|
|
78
109
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
79
|
-
const [__, children] = useService(interpreter);
|
|
110
|
+
const [__, children] = (0, useService_1.useService)(interpreter);
|
|
80
111
|
if (slot.toString().endsWith("Multi")) {
|
|
81
|
-
const MultiView = getMultiSlotViewForChildren(interpreter, slot.toLowerCase());
|
|
82
|
-
return
|
|
112
|
+
const MultiView = (0, exports.getMultiSlotViewForChildren)(interpreter, slot.toLowerCase());
|
|
113
|
+
return react_2.default.createElement(MultiView, null);
|
|
83
114
|
}
|
|
84
115
|
else {
|
|
85
116
|
const interpreterForSlot = children.get(`${slot.toLowerCase()}-slot`);
|
|
86
117
|
if (interpreterForSlot) {
|
|
87
118
|
const View = getViewForInterpreter(interpreterForSlot);
|
|
88
|
-
return
|
|
119
|
+
return react_2.default.createElement(View, null);
|
|
89
120
|
}
|
|
90
121
|
else {
|
|
91
122
|
// Waiting for the interpreter for this slot to be invoked
|
|
@@ -98,23 +129,23 @@ function useSlots(interpreter, slots) {
|
|
|
98
129
|
});
|
|
99
130
|
}
|
|
100
131
|
function XstateTreeMultiSlotView({ childInterpreters, }) {
|
|
101
|
-
return (
|
|
132
|
+
return (react_2.default.createElement(react_2.default.Fragment, null, childInterpreters.map((i) => (react_2.default.createElement(XstateTreeView, { key: i.id, interpreter: i })))));
|
|
102
133
|
}
|
|
103
134
|
/**
|
|
104
135
|
* @internal
|
|
105
136
|
*/
|
|
106
|
-
|
|
137
|
+
function XstateTreeView({ interpreter }) {
|
|
107
138
|
var _a, _b;
|
|
108
|
-
const [current] = useService(interpreter);
|
|
109
|
-
const currentRef = useRef(current);
|
|
139
|
+
const [current] = (0, useService_1.useService)(interpreter);
|
|
140
|
+
const currentRef = (0, react_2.useRef)(current);
|
|
110
141
|
currentRef.current = current;
|
|
111
|
-
const selectorsRef = useRef(undefined);
|
|
142
|
+
const selectorsRef = (0, react_2.useRef)(undefined);
|
|
112
143
|
const { slots: interpreterSlots } = interpreter.machine.meta;
|
|
113
144
|
const slots = useSlots(interpreter, interpreterSlots.map((x) => x.name));
|
|
114
|
-
const canHandleEvent = useCallback((e) => {
|
|
145
|
+
const canHandleEvent = (0, react_2.useCallback)((e) => {
|
|
115
146
|
return interpreter.getSnapshot().can(e);
|
|
116
147
|
}, [interpreter]);
|
|
117
|
-
const inState = useCallback((state) => {
|
|
148
|
+
const inState = (0, react_2.useCallback)((state) => {
|
|
118
149
|
var _a, _b;
|
|
119
150
|
return (_b = (_a = currentRef.current) === null || _a === void 0 ? void 0 : _a.matches(state)) !== null && _b !== void 0 ? _b : false;
|
|
120
151
|
},
|
|
@@ -122,7 +153,7 @@ export function XstateTreeView({ interpreter }) {
|
|
|
122
153
|
// current state the machine is in changes. But _only_ then
|
|
123
154
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
124
155
|
[current.value]);
|
|
125
|
-
const selectorsProxy = useConstant(() => {
|
|
156
|
+
const selectorsProxy = (0, useConstant_1.useConstant)(() => {
|
|
126
157
|
return new Proxy({}, {
|
|
127
158
|
get: (_target, prop) => {
|
|
128
159
|
var _a;
|
|
@@ -130,7 +161,7 @@ export function XstateTreeView({ interpreter }) {
|
|
|
130
161
|
},
|
|
131
162
|
});
|
|
132
163
|
});
|
|
133
|
-
const actions = useConstant(() => {
|
|
164
|
+
const actions = (0, useConstant_1.useConstant)(() => {
|
|
134
165
|
var _a;
|
|
135
166
|
switch ((_a = interpreter.machine.meta) === null || _a === void 0 ? void 0 : _a.builderVersion) {
|
|
136
167
|
case 1:
|
|
@@ -162,18 +193,19 @@ export function XstateTreeView({ interpreter }) {
|
|
|
162
193
|
switch ((_b = interpreter.machine.meta) === null || _b === void 0 ? void 0 : _b.builderVersion) {
|
|
163
194
|
case 1:
|
|
164
195
|
const ViewV1 = interpreter.machine.meta.view;
|
|
165
|
-
return (
|
|
196
|
+
return (react_2.default.createElement(ViewV1, { selectors: selectorsRef.current, actions: actions, slots: slots, inState: inState }));
|
|
166
197
|
case 2:
|
|
167
198
|
const ViewV2 = interpreter.machine.meta.View;
|
|
168
|
-
return (
|
|
199
|
+
return (react_2.default.createElement(ViewV2, { selectors: selectorsRef.current, actions: actions, slots: slots }));
|
|
169
200
|
default:
|
|
170
201
|
throw new Error("builderVersion not set");
|
|
171
202
|
}
|
|
172
203
|
}
|
|
204
|
+
exports.XstateTreeView = XstateTreeView;
|
|
173
205
|
/**
|
|
174
206
|
* @internal
|
|
175
207
|
*/
|
|
176
|
-
|
|
208
|
+
function recursivelySend(service, event) {
|
|
177
209
|
const children = ([...service.children.values()] || []).filter((s) => s.id.includes("-slot"));
|
|
178
210
|
// If the service can't handle the event, don't send it
|
|
179
211
|
if (service.state.nextEvents.includes(event.type)) {
|
|
@@ -186,6 +218,7 @@ export function recursivelySend(service, event) {
|
|
|
186
218
|
}
|
|
187
219
|
children.forEach((child) => recursivelySend(child, event));
|
|
188
220
|
}
|
|
221
|
+
exports.recursivelySend = recursivelySend;
|
|
189
222
|
/**
|
|
190
223
|
* @public
|
|
191
224
|
*
|
|
@@ -194,7 +227,7 @@ export function recursivelySend(service, event) {
|
|
|
194
227
|
* @param machine - The root machine of the tree
|
|
195
228
|
* @param routing - The routing configuration for the tree
|
|
196
229
|
*/
|
|
197
|
-
|
|
230
|
+
function buildRootComponent(machine, routing) {
|
|
198
231
|
if (!machine.meta) {
|
|
199
232
|
throw new Error("Root machine has no meta");
|
|
200
233
|
}
|
|
@@ -211,23 +244,23 @@ export function buildRootComponent(machine, routing) {
|
|
|
211
244
|
break;
|
|
212
245
|
}
|
|
213
246
|
const RootComponent = function XstateTreeRootComponent() {
|
|
214
|
-
const [_, __, interpreter] = useMachine(machine, { devTools: true });
|
|
215
|
-
const [activeRoute, setActiveRoute] = useState(undefined);
|
|
216
|
-
const activeRouteEventsRef = useRef([]);
|
|
217
|
-
const [forceRenderValue, forceRender] = useState(false);
|
|
247
|
+
const [_, __, interpreter] = (0, react_1.useMachine)(machine, { devTools: true });
|
|
248
|
+
const [activeRoute, setActiveRoute] = (0, react_2.useState)(undefined);
|
|
249
|
+
const activeRouteEventsRef = (0, react_2.useRef)([]);
|
|
250
|
+
const [forceRenderValue, forceRender] = (0, react_2.useState)(false);
|
|
218
251
|
const setActiveRouteEvents = (events) => {
|
|
219
252
|
activeRouteEventsRef.current = events;
|
|
220
253
|
};
|
|
221
|
-
useEffect(() => {
|
|
254
|
+
(0, react_2.useEffect)(() => {
|
|
222
255
|
function handler(event) {
|
|
223
256
|
recursivelySend(interpreter, event);
|
|
224
257
|
}
|
|
225
|
-
emitter.on("event", handler);
|
|
258
|
+
exports.emitter.on("event", handler);
|
|
226
259
|
return () => {
|
|
227
|
-
emitter.off("event", handler);
|
|
260
|
+
exports.emitter.off("event", handler);
|
|
228
261
|
};
|
|
229
262
|
}, [interpreter]);
|
|
230
|
-
useEffect(() => {
|
|
263
|
+
(0, react_2.useEffect)(() => {
|
|
231
264
|
if (activeRoute === undefined) {
|
|
232
265
|
return;
|
|
233
266
|
}
|
|
@@ -240,7 +273,7 @@ export function buildRootComponent(machine, routing) {
|
|
|
240
273
|
}
|
|
241
274
|
const routeEventPairs = [];
|
|
242
275
|
const activeRoutesEvent = activeRouteEventsRef.current.find((e) => e.type === activeRoute.event);
|
|
243
|
-
assertIsDefined(activeRoutesEvent);
|
|
276
|
+
(0, utils_1.assertIsDefined)(activeRoutesEvent);
|
|
244
277
|
for (let i = 0; i < routes.length; i++) {
|
|
245
278
|
const route = routes[i];
|
|
246
279
|
const routeEvent = activeRouteEventsRef.current[i];
|
|
@@ -250,7 +283,7 @@ export function buildRootComponent(machine, routing) {
|
|
|
250
283
|
return route.redirect !== undefined;
|
|
251
284
|
});
|
|
252
285
|
const redirectPromises = routePairsWithRedirects.map(([route, event]) => {
|
|
253
|
-
assertIsDefined(route.redirect);
|
|
286
|
+
(0, utils_1.assertIsDefined)(route.redirect);
|
|
254
287
|
return route.redirect({
|
|
255
288
|
signal: controller.signal,
|
|
256
289
|
query: event.query,
|
|
@@ -284,11 +317,11 @@ export function buildRootComponent(machine, routing) {
|
|
|
284
317
|
controller.abort();
|
|
285
318
|
};
|
|
286
319
|
}, [activeRoute]);
|
|
287
|
-
useEffect(() => {
|
|
320
|
+
(0, react_2.useEffect)(() => {
|
|
288
321
|
if (routing) {
|
|
289
322
|
const { getPathName = () => routing.history.location.pathname, getQueryString = () => routing.history.location.search, } = routing;
|
|
290
323
|
const queryString = getQueryString();
|
|
291
|
-
const result = handleLocationChange(routing.routes, routing.basePath, getPathName(), getQueryString(), { onloadEvent: isLikelyPageLoad() });
|
|
324
|
+
const result = (0, routing_1.handleLocationChange)(routing.routes, routing.basePath, getPathName(), getQueryString(), { onloadEvent: (0, utils_1.isLikelyPageLoad)() });
|
|
292
325
|
if (result) {
|
|
293
326
|
setActiveRouteEvents(result.events);
|
|
294
327
|
setActiveRoute({ ...result.matchedRoute });
|
|
@@ -299,11 +332,11 @@ export function buildRootComponent(machine, routing) {
|
|
|
299
332
|
routing.history.replace(`${getPathName()}${queryString}`, {});
|
|
300
333
|
}
|
|
301
334
|
}, []);
|
|
302
|
-
useEffect(() => {
|
|
335
|
+
(0, react_2.useEffect)(() => {
|
|
303
336
|
if (routing) {
|
|
304
337
|
const unsub = routing.history.listen((location) => {
|
|
305
338
|
var _a;
|
|
306
|
-
const result = handleLocationChange(routing.routes, routing.basePath, location.pathname, location.search, (_a = location.state) === null || _a === void 0 ? void 0 : _a.meta);
|
|
339
|
+
const result = (0, routing_1.handleLocationChange)(routing.routes, routing.basePath, location.pathname, location.search, (_a = location.state) === null || _a === void 0 ? void 0 : _a.meta);
|
|
307
340
|
if (result) {
|
|
308
341
|
setActiveRouteEvents(result.events);
|
|
309
342
|
setActiveRoute({ ...result.matchedRoute });
|
|
@@ -315,26 +348,29 @@ export function buildRootComponent(machine, routing) {
|
|
|
315
348
|
}
|
|
316
349
|
return undefined;
|
|
317
350
|
}, []);
|
|
318
|
-
const routingProviderValue = useMemo(() => {
|
|
351
|
+
const routingProviderValue = (0, react_2.useMemo)(() => {
|
|
352
|
+
// Just to satisfy linter, need this memo to be re-calculated on route changes
|
|
353
|
+
activeRoute;
|
|
319
354
|
if (!routing) {
|
|
320
355
|
return null;
|
|
321
356
|
}
|
|
322
357
|
return {
|
|
323
358
|
activeRouteEvents: activeRouteEventsRef,
|
|
324
359
|
};
|
|
325
|
-
}, []);
|
|
360
|
+
}, [activeRoute]);
|
|
326
361
|
if (!interpreter.initialized) {
|
|
327
362
|
setTimeout(() => forceRender(!forceRenderValue), 0);
|
|
328
363
|
return null;
|
|
329
364
|
}
|
|
330
365
|
if (routingProviderValue) {
|
|
331
|
-
return (
|
|
332
|
-
|
|
366
|
+
return (react_2.default.createElement(routing_1.RoutingContext.Provider, { value: routingProviderValue },
|
|
367
|
+
react_2.default.createElement(XstateTreeView, { interpreter: interpreter })));
|
|
333
368
|
}
|
|
334
369
|
else {
|
|
335
|
-
return
|
|
370
|
+
return react_2.default.createElement(XstateTreeView, { interpreter: interpreter });
|
|
336
371
|
}
|
|
337
372
|
};
|
|
338
373
|
RootComponent.rootMachine = machine;
|
|
339
374
|
return RootComponent;
|
|
340
375
|
}
|
|
376
|
+
exports.buildRootComponent = buildRootComponent;
|