@koordinates/xstate-tree 1.0.0-beta.2 → 1.0.0-beta.4
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/LICENSE +8 -0
- package/lib/routing/Link.js +2 -1
- package/lib/routing/createRoute/createRoute.js +10 -10
- package/lib/routing/handleLocationChange/handleLocationChange.js +2 -2
- package/lib/routing/matchRoute/matchRoute.js +3 -2
- package/lib/routing/providers.js +1 -1
- package/lib/slots/slots.js +4 -1
- package/lib/testingUtilities.js +4 -1
- package/lib/useService.js +4 -2
- package/lib/xstate-tree.d.ts +37 -10
- package/lib/xstateTree.js +6 -3
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
Copyright © 2022 Koordinates
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
5
|
+
|
|
6
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
7
|
+
|
|
8
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/lib/routing/Link.js
CHANGED
|
@@ -13,7 +13,8 @@ export function Link({ to, children, testId, ...rest }) {
|
|
|
13
13
|
const { params, query, meta, ...props } = rest;
|
|
14
14
|
const href = useHref(to, params, query);
|
|
15
15
|
return (React.createElement("a", { ...props, href: href, "data-testid": testId, onClick: (e) => {
|
|
16
|
-
|
|
16
|
+
var _a;
|
|
17
|
+
if (((_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, e)) === false) {
|
|
17
18
|
return;
|
|
18
19
|
}
|
|
19
20
|
// Holding the Command key on Mac or the Control Key on Windows while clicking the link will open a new tab/window
|
|
@@ -7,7 +7,7 @@ import { joinRoutes } from "../joinRoutes";
|
|
|
7
7
|
*/
|
|
8
8
|
export function buildCreateRoute(history, basePath) {
|
|
9
9
|
function navigate({ history, url, meta, }) {
|
|
10
|
-
const method = meta
|
|
10
|
+
const method = (meta === null || meta === void 0 ? void 0 : meta.replace) ? history.replace : history.push;
|
|
11
11
|
method(url, {
|
|
12
12
|
meta,
|
|
13
13
|
previousUrl: window.location.pathname,
|
|
@@ -32,8 +32,8 @@ export function buildCreateRoute(history, basePath) {
|
|
|
32
32
|
dynamicRoute: function createDynamicRoute(opts) {
|
|
33
33
|
return ({ event, matches, reverse, }) => {
|
|
34
34
|
return {
|
|
35
|
-
paramsSchema: opts
|
|
36
|
-
querySchema: opts
|
|
35
|
+
paramsSchema: opts === null || opts === void 0 ? void 0 : opts.params,
|
|
36
|
+
querySchema: opts === null || opts === void 0 ? void 0 : opts.query,
|
|
37
37
|
event,
|
|
38
38
|
history,
|
|
39
39
|
basePath,
|
|
@@ -49,10 +49,10 @@ export function buildCreateRoute(history, basePath) {
|
|
|
49
49
|
if (match === false) {
|
|
50
50
|
return undefined;
|
|
51
51
|
}
|
|
52
|
-
if (opts
|
|
52
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.params) && "params" in match) {
|
|
53
53
|
opts.params.parse(match.params);
|
|
54
54
|
}
|
|
55
|
-
if (opts
|
|
55
|
+
if ((opts === null || opts === void 0 ? void 0 : opts.query) && "query" in match) {
|
|
56
56
|
opts.query.parse(match.query);
|
|
57
57
|
}
|
|
58
58
|
return { type: event, originalUrl: `${url}${search}`, ...match };
|
|
@@ -107,16 +107,16 @@ export function buildCreateRoute(history, basePath) {
|
|
|
107
107
|
: urlWithTrailingSlash;
|
|
108
108
|
const matcher = match(fullUrl, {});
|
|
109
109
|
const reverser = compile(fullUrl);
|
|
110
|
-
const paramsSchema = baseRoute
|
|
111
|
-
? opts
|
|
110
|
+
const paramsSchema = (baseRoute === null || baseRoute === void 0 ? void 0 : baseRoute.paramsSchema)
|
|
111
|
+
? (opts === null || opts === void 0 ? void 0 : opts.params)
|
|
112
112
|
? baseRoute.paramsSchema.merge(opts.params)
|
|
113
113
|
: baseRoute.paramsSchema
|
|
114
|
-
: opts
|
|
114
|
+
: (opts === null || opts === void 0 ? void 0 : opts.params)
|
|
115
115
|
? opts.params
|
|
116
116
|
: undefined;
|
|
117
117
|
return {
|
|
118
118
|
paramsSchema,
|
|
119
|
-
querySchema: opts
|
|
119
|
+
querySchema: opts === null || opts === void 0 ? void 0 : opts.query,
|
|
120
120
|
event,
|
|
121
121
|
history,
|
|
122
122
|
basePath,
|
|
@@ -138,7 +138,7 @@ export function buildCreateRoute(history, basePath) {
|
|
|
138
138
|
paramsSchema.parse(params);
|
|
139
139
|
}
|
|
140
140
|
const query = parse(search);
|
|
141
|
-
if (opts
|
|
141
|
+
if (opts === null || opts === void 0 ? void 0 : opts.query) {
|
|
142
142
|
opts.query.parse(query);
|
|
143
143
|
}
|
|
144
144
|
return {
|
|
@@ -20,13 +20,13 @@ export function handleLocationChange(routes, basePath, path, search, setActiveRo
|
|
|
20
20
|
}
|
|
21
21
|
else {
|
|
22
22
|
const matchedEvent = match.event;
|
|
23
|
-
matchedEvent.meta = { ...(meta
|
|
23
|
+
matchedEvent.meta = { ...(meta !== null && meta !== void 0 ? meta : {}) };
|
|
24
24
|
matchedEvent.meta.indexEvent = true;
|
|
25
25
|
const { params } = match.event;
|
|
26
26
|
const routingEvents = [];
|
|
27
27
|
let route = match.route;
|
|
28
28
|
while (route.parent) {
|
|
29
|
-
routingEvents.push(route.parent.getEvent({ params, query: {}, meta: { ...(meta
|
|
29
|
+
routingEvents.push(route.parent.getEvent({ params, query: {}, meta: { ...(meta !== null && meta !== void 0 ? meta : {}) } }));
|
|
30
30
|
route = route.parent;
|
|
31
31
|
}
|
|
32
32
|
setActiveRouteEvents([...routingEvents, match.event]);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* @public
|
|
3
3
|
*/
|
|
4
4
|
export function matchRoute(routes, basePath, path, search) {
|
|
5
|
+
var _a;
|
|
5
6
|
const realBase = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
|
|
6
7
|
const realPath = (() => {
|
|
7
8
|
if (path.startsWith(realBase) && realBase.length > 0) {
|
|
@@ -9,7 +10,7 @@ export function matchRoute(routes, basePath, path, search) {
|
|
|
9
10
|
}
|
|
10
11
|
return path;
|
|
11
12
|
})();
|
|
12
|
-
const [matchingRoute, event] = routes
|
|
13
|
+
const [matchingRoute, event] = (_a = routes
|
|
13
14
|
.map((route) => {
|
|
14
15
|
try {
|
|
15
16
|
const match = route.matches(realPath, search);
|
|
@@ -24,7 +25,7 @@ export function matchRoute(routes, basePath, path, search) {
|
|
|
24
25
|
}
|
|
25
26
|
return [undefined, undefined];
|
|
26
27
|
})
|
|
27
|
-
.find(([match]) => Boolean(match))
|
|
28
|
+
.find(([match]) => Boolean(match))) !== null && _a !== void 0 ? _a : [undefined, undefined];
|
|
28
29
|
if (matchingRoute === undefined) {
|
|
29
30
|
return { type: "no-matches" };
|
|
30
31
|
}
|
package/lib/routing/providers.js
CHANGED
package/lib/slots/slots.js
CHANGED
package/lib/testingUtilities.js
CHANGED
|
@@ -152,7 +152,10 @@ function difference(object, base) {
|
|
|
152
152
|
*
|
|
153
153
|
* I have no solutions for this
|
|
154
154
|
*/
|
|
155
|
-
export function buildStorybookComponent(machine, state
|
|
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 : {}; }
|
|
156
159
|
// `set` converts a state.like.this to a {state: { like: this {} } }
|
|
157
160
|
const objectState = set({}, String(state), undefined);
|
|
158
161
|
const startingState = new State({
|
package/lib/useService.js
CHANGED
|
@@ -46,18 +46,20 @@ export function useService(service) {
|
|
|
46
46
|
}, [service, setChildren]);
|
|
47
47
|
useEffect(() => {
|
|
48
48
|
function handler(event) {
|
|
49
|
+
var _a, _b, _c;
|
|
49
50
|
if (event.type.includes("done")) {
|
|
50
51
|
const idOfFinishedChild = event.type.split(".")[2];
|
|
51
52
|
childrenRef.current.delete(idOfFinishedChild);
|
|
52
53
|
setChildren(new Map(childrenRef.current));
|
|
53
54
|
}
|
|
54
|
-
console.debug(`[xstate-tree] ${service.id} handling event`, service.machine.meta
|
|
55
|
+
console.debug(`[xstate-tree] ${service.id} handling event`, ((_c = (_b = (_a = service.machine.meta) === null || _a === void 0 ? void 0 : _a.xstateTree) === null || _b === void 0 ? void 0 : _b.ignoredEvents) === null || _c === void 0 ? void 0 : _c.has(event.type))
|
|
55
56
|
? event.type
|
|
56
57
|
: event);
|
|
57
58
|
}
|
|
58
59
|
let prevState = undefined;
|
|
59
60
|
function transitionHandler(state) {
|
|
60
|
-
|
|
61
|
+
var _a, _b;
|
|
62
|
+
const ignoreContext = (_b = (_a = service.machine.meta) === null || _a === void 0 ? void 0 : _a.xstateTree) === null || _b === void 0 ? void 0 : _b.ignoreContext;
|
|
61
63
|
const context = ignoreContext
|
|
62
64
|
? ignoreContext.length > 0
|
|
63
65
|
? omit(state.context, ignoreContext)
|
package/lib/xstate-tree.d.ts
CHANGED
|
@@ -216,7 +216,7 @@ declare type Events = any;
|
|
|
216
216
|
export declare const genericSlotsTestingDummy: any;
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
|
-
* @
|
|
219
|
+
* @public
|
|
220
220
|
*/
|
|
221
221
|
export declare type GetSlotNames<TSlots extends readonly Slot[]> = TSlots[number]["name"];
|
|
222
222
|
|
|
@@ -296,11 +296,17 @@ declare type MakeEmptyObjectPropertiesOptional<T> = Omit<T, EmptyKeys<T>> & Part
|
|
|
296
296
|
*/
|
|
297
297
|
export declare function matchRoute<TRoutes extends Route<any, any, any, any>[]>(routes: TRoutes, basePath: string, path: string, search: string): Return;
|
|
298
298
|
|
|
299
|
-
|
|
299
|
+
/**
|
|
300
|
+
* @public
|
|
301
|
+
*/
|
|
302
|
+
export declare type Meta<T> = T extends {
|
|
300
303
|
meta: infer TMeta;
|
|
301
304
|
} ? TMeta : undefined;
|
|
302
305
|
|
|
303
|
-
|
|
306
|
+
/**
|
|
307
|
+
* @public
|
|
308
|
+
*/
|
|
309
|
+
export declare type MultiSlot<T> = {
|
|
304
310
|
type: SlotType.MultiSlot;
|
|
305
311
|
name: T;
|
|
306
312
|
getId(id: string): string;
|
|
@@ -320,7 +326,10 @@ declare type OmitOptional<T> = {
|
|
|
320
326
|
*/
|
|
321
327
|
export declare function onBroadcast(handler: (event: GlobalEvents) => void): () => void;
|
|
322
328
|
|
|
323
|
-
|
|
329
|
+
/**
|
|
330
|
+
* @public
|
|
331
|
+
*/
|
|
332
|
+
export declare type Options<TParamsSchema extends Z.ZodObject<any>, TQuerySchema extends Z.ZodObject<any>, TMetaSchema> = {
|
|
324
333
|
params?: TParamsSchema;
|
|
325
334
|
query?: TQuerySchema;
|
|
326
335
|
meta?: TMetaSchema;
|
|
@@ -338,7 +347,10 @@ declare type Options_2<TContext> = {
|
|
|
338
347
|
withContext?: () => Partial<TContext>;
|
|
339
348
|
};
|
|
340
349
|
|
|
341
|
-
|
|
350
|
+
/**
|
|
351
|
+
* @public
|
|
352
|
+
*/
|
|
353
|
+
export declare type Params<T> = T extends {
|
|
342
354
|
params: infer TParams;
|
|
343
355
|
} ? TParams : undefined;
|
|
344
356
|
|
|
@@ -355,7 +367,10 @@ export declare type PickEvent<T extends Extract<GlobalEvents, {
|
|
|
355
367
|
|
|
356
368
|
declare type PropsOf<C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>> = JSX.LibraryManagedAttributes<C, ComponentPropsWithRef<C>>;
|
|
357
369
|
|
|
358
|
-
|
|
370
|
+
/**
|
|
371
|
+
* @public
|
|
372
|
+
*/
|
|
373
|
+
export declare type Query<T> = T extends {
|
|
359
374
|
query: infer TQuery;
|
|
360
375
|
} ? TQuery : undefined;
|
|
361
376
|
|
|
@@ -421,7 +436,10 @@ export declare type Route<TParams, TQuery, TEvent, TMeta> = {
|
|
|
421
436
|
querySchema?: Z.ZodObject<any>;
|
|
422
437
|
};
|
|
423
438
|
|
|
424
|
-
|
|
439
|
+
/**
|
|
440
|
+
* @public
|
|
441
|
+
*/
|
|
442
|
+
export declare type RouteArgumentFunctions<TReturn, TParams, TQuery, TMeta, TArgs = RouteArguments<TParams, TQuery, TMeta>> = IsEmptyObject<TArgs> extends true ? () => TReturn : keyof TArgs extends "meta" ? (args?: TArgs) => TReturn : EmptyRouteArguments<TParams, TQuery> extends true ? (args?: Partial<TArgs>) => TReturn : (args: MakeEmptyObjectPropertiesOptional<TArgs>) => TReturn;
|
|
425
443
|
|
|
426
444
|
/**
|
|
427
445
|
* @public
|
|
@@ -481,7 +499,10 @@ export declare type RoutingEvent<T> = T extends Route<infer TParams, infer TQuer
|
|
|
481
499
|
|
|
482
500
|
declare type Selectors<TContext, TEvent extends EventObject, TSelectors, TStates> = (ctx: TContext, canHandleEvent: (e: TEvent) => boolean, inState: (state: TStates) => boolean, __currentState: TStates) => TSelectors;
|
|
483
501
|
|
|
484
|
-
|
|
502
|
+
/**
|
|
503
|
+
* @public
|
|
504
|
+
*/
|
|
505
|
+
export declare type SharedMeta = {
|
|
485
506
|
/**
|
|
486
507
|
* Suppresses this routing change event from being picked up by react-router
|
|
487
508
|
*/
|
|
@@ -496,7 +517,10 @@ declare type SharedMeta = {
|
|
|
496
517
|
replace?: boolean;
|
|
497
518
|
};
|
|
498
519
|
|
|
499
|
-
|
|
520
|
+
/**
|
|
521
|
+
* @public
|
|
522
|
+
*/
|
|
523
|
+
export declare type SingleSlot<T> = {
|
|
500
524
|
type: SlotType.SingleSlot;
|
|
501
525
|
name: T;
|
|
502
526
|
getId(): string;
|
|
@@ -526,7 +550,10 @@ context: unknown;
|
|
|
526
550
|
context: unknown;
|
|
527
551
|
}, any, any, any>;
|
|
528
552
|
|
|
529
|
-
|
|
553
|
+
/**
|
|
554
|
+
* @public
|
|
555
|
+
*/
|
|
556
|
+
export declare enum SlotType {
|
|
530
557
|
SingleSlot = 0,
|
|
531
558
|
MultiSlot = 1
|
|
532
559
|
}
|
package/lib/xstateTree.js
CHANGED
|
@@ -102,10 +102,12 @@ export function XstateTreeView({ interpreter }) {
|
|
|
102
102
|
const { view: View, actions: actionsFactory, selectors: selectorsFactory, slots: interpreterSlots, } = interpreter.machine.meta;
|
|
103
103
|
const slots = useSlots(interpreter, interpreterSlots.map((x) => x.name));
|
|
104
104
|
const canHandleEvent = useCallback((e) => {
|
|
105
|
-
|
|
105
|
+
var _a;
|
|
106
|
+
return (_a = interpreter.nextState(e).changed) !== null && _a !== void 0 ? _a : false;
|
|
106
107
|
}, [interpreter]);
|
|
107
108
|
const inState = useCallback((state) => {
|
|
108
|
-
|
|
109
|
+
var _a, _b;
|
|
110
|
+
return (_b = (_a = currentRef.current) === null || _a === void 0 ? void 0 : _a.matches(state)) !== null && _b !== void 0 ? _b : false;
|
|
109
111
|
},
|
|
110
112
|
// This is needed because the inState function needs to be recreated if the
|
|
111
113
|
// current state the machine is in changes. But _only_ then
|
|
@@ -171,7 +173,8 @@ export function buildRootComponent(machine, routing) {
|
|
|
171
173
|
useEffect(() => {
|
|
172
174
|
if (routing) {
|
|
173
175
|
const unsub = routing.history.listen((location) => {
|
|
174
|
-
|
|
176
|
+
var _a;
|
|
177
|
+
handleLocationChange(routing.routes, routing.basePath, location.pathname, location.search, setActiveRouteEvents, (_a = location.state) === null || _a === void 0 ? void 0 : _a.meta);
|
|
175
178
|
});
|
|
176
179
|
return () => {
|
|
177
180
|
unsub();
|