@solidjs/router 0.16.0 → 0.17.0-next.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/README.md +85 -79
- package/dist/components.jsx +22 -16
- package/dist/data/action.d.ts +12 -10
- package/dist/data/action.js +98 -78
- package/dist/data/events.d.ts +8 -1
- package/dist/data/events.js +3 -3
- package/dist/data/index.d.ts +2 -3
- package/dist/data/index.js +2 -3
- package/dist/data/query.d.ts +1 -3
- package/dist/data/query.js +10 -16
- package/dist/index.d.ts +2 -2
- package/dist/index.js +212 -261
- package/dist/index.jsx +1 -1
- package/dist/lifecycle.js +1 -1
- package/dist/routers/HashRouter.js +1 -1
- package/dist/routers/MemoryRouter.js +1 -1
- package/dist/routers/Router.js +2 -2
- package/dist/routers/StaticRouter.js +1 -1
- package/dist/routers/components.d.ts +0 -4
- package/dist/routers/components.jsx +30 -19
- package/dist/routing.d.ts +4 -3
- package/dist/routing.js +71 -49
- package/dist/types.d.ts +3 -18
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +8 -0
- package/package.json +8 -6
- package/dist/data/createAsync.d.ts +0 -32
- package/dist/data/createAsync.js +0 -93
- package/dist/src/components.d.ts +0 -31
- package/dist/src/components.jsx +0 -39
- package/dist/src/data/action.d.ts +0 -17
- package/dist/src/data/action.js +0 -163
- package/dist/src/data/action.spec.d.ts +0 -1
- package/dist/src/data/action.spec.js +0 -297
- package/dist/src/data/createAsync.d.ts +0 -32
- package/dist/src/data/createAsync.js +0 -96
- package/dist/src/data/createAsync.spec.d.ts +0 -1
- package/dist/src/data/createAsync.spec.js +0 -196
- package/dist/src/data/events.d.ts +0 -9
- package/dist/src/data/events.js +0 -123
- package/dist/src/data/events.spec.d.ts +0 -1
- package/dist/src/data/events.spec.js +0 -567
- package/dist/src/data/index.d.ts +0 -4
- package/dist/src/data/index.js +0 -4
- package/dist/src/data/query.d.ts +0 -23
- package/dist/src/data/query.js +0 -232
- package/dist/src/data/query.spec.d.ts +0 -1
- package/dist/src/data/query.spec.js +0 -354
- package/dist/src/data/response.d.ts +0 -4
- package/dist/src/data/response.js +0 -42
- package/dist/src/data/response.spec.d.ts +0 -1
- package/dist/src/data/response.spec.js +0 -165
- package/dist/src/index.d.ts +0 -7
- package/dist/src/index.jsx +0 -6
- package/dist/src/lifecycle.d.ts +0 -5
- package/dist/src/lifecycle.js +0 -69
- package/dist/src/routers/HashRouter.d.ts +0 -9
- package/dist/src/routers/HashRouter.js +0 -41
- package/dist/src/routers/MemoryRouter.d.ts +0 -24
- package/dist/src/routers/MemoryRouter.js +0 -57
- package/dist/src/routers/Router.d.ts +0 -9
- package/dist/src/routers/Router.js +0 -45
- package/dist/src/routers/StaticRouter.d.ts +0 -6
- package/dist/src/routers/StaticRouter.js +0 -15
- package/dist/src/routers/components.d.ts +0 -27
- package/dist/src/routers/components.jsx +0 -118
- package/dist/src/routers/createRouter.d.ts +0 -10
- package/dist/src/routers/createRouter.js +0 -41
- package/dist/src/routers/index.d.ts +0 -11
- package/dist/src/routers/index.js +0 -6
- package/dist/src/routing.d.ts +0 -175
- package/dist/src/routing.js +0 -560
- package/dist/src/types.d.ts +0 -200
- package/dist/src/types.js +0 -1
- package/dist/src/utils.d.ts +0 -13
- package/dist/src/utils.js +0 -185
- package/dist/test/helpers.d.ts +0 -6
- package/dist/test/helpers.js +0 -50
package/dist/index.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./routers/index.js";
|
|
2
2
|
export * from "./components.jsx";
|
|
3
3
|
export * from "./lifecycle.js";
|
|
4
|
-
export { useHref, useIsRouting, useLocation, useMatch, useCurrentMatches, useNavigate, useParams, useResolvedPath, useSearchParams, useBeforeLeave, usePreloadRoute } from "./routing.js";
|
|
4
|
+
export { useHref, useIsRouting, useLocation, useMatch, useCurrentMatches, useNavigate, useParams, useResolvedPath, useSearchParams, useBeforeLeave, usePreloadRoute, RouterContextObj as RouterContext } from "./routing.js";
|
|
5
5
|
export { mergeSearchString as _mergeSearchString } from "./utils.js";
|
|
6
6
|
export * from "./data/index.js";
|
package/dist/lifecycle.js
CHANGED
|
@@ -30,7 +30,7 @@ export function HashRouter(props) {
|
|
|
30
30
|
saveCurrentDepth();
|
|
31
31
|
},
|
|
32
32
|
init: notify => bindEvent(window, "hashchange", notifyIfNotBlocked(notify, delta => !beforeLeave.confirm(delta && delta < 0 ? delta : getSource()))),
|
|
33
|
-
create: setupNativeEvents(props.preload, props.explicitLinks, props.actionBase),
|
|
33
|
+
create: setupNativeEvents({ preload: props.preload, explicitLinks: props.explicitLinks, actionBase: props.actionBase }),
|
|
34
34
|
utils: {
|
|
35
35
|
go: delta => window.history.go(delta),
|
|
36
36
|
renderPath: path => `#${path}`,
|
|
@@ -49,7 +49,7 @@ export function MemoryRouter(props) {
|
|
|
49
49
|
get: memoryHistory.get,
|
|
50
50
|
set: memoryHistory.set,
|
|
51
51
|
init: memoryHistory.listen,
|
|
52
|
-
create: setupNativeEvents(props.preload, props.explicitLinks, props.actionBase),
|
|
52
|
+
create: setupNativeEvents({ preload: props.preload, explicitLinks: props.explicitLinks, actionBase: props.actionBase }),
|
|
53
53
|
utils: {
|
|
54
54
|
go: memoryHistory.go
|
|
55
55
|
}
|
package/dist/routers/Router.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isServer } from "
|
|
1
|
+
import { isServer } from "@solidjs/web";
|
|
2
2
|
import { createRouter, scrollToHash, bindEvent } from "./createRouter.js";
|
|
3
3
|
import { StaticRouter } from "./StaticRouter.js";
|
|
4
4
|
import { setupNativeEvents } from "../data/events.js";
|
|
@@ -36,7 +36,7 @@ export function Router(props) {
|
|
|
36
36
|
return !beforeLeave.confirm(s.value, { state: s.state });
|
|
37
37
|
}
|
|
38
38
|
})),
|
|
39
|
-
create: setupNativeEvents(props.preload, props.explicitLinks, props.actionBase, props.transformUrl),
|
|
39
|
+
create: setupNativeEvents({ preload: props.preload, explicitLinks: props.explicitLinks, actionBase: props.actionBase, transformUrl: props.transformUrl }),
|
|
40
40
|
utils: {
|
|
41
41
|
go: delta => window.history.go(delta),
|
|
42
42
|
beforeLeave
|
|
@@ -10,8 +10,6 @@ export type BaseRouterProps = {
|
|
|
10
10
|
singleFlight?: boolean;
|
|
11
11
|
children?: JSX.Element | RouteDefinition | RouteDefinition[];
|
|
12
12
|
transformUrl?: (url: string) => string;
|
|
13
|
-
/** @deprecated use rootPreload */
|
|
14
|
-
rootLoad?: RoutePreloadFunc;
|
|
15
13
|
};
|
|
16
14
|
export declare const createRouterComponent: (router: RouterIntegration) => (props: BaseRouterProps) => JSX.Element;
|
|
17
15
|
export type RouteProps<S extends string, T = unknown> = {
|
|
@@ -21,7 +19,5 @@ export type RouteProps<S extends string, T = unknown> = {
|
|
|
21
19
|
matchFilters?: MatchFilters<S>;
|
|
22
20
|
component?: Component<RouteSectionProps<T>>;
|
|
23
21
|
info?: Record<string, any>;
|
|
24
|
-
/** @deprecated use preload */
|
|
25
|
-
load?: RoutePreloadFunc<T>;
|
|
26
22
|
};
|
|
27
23
|
export declare const Route: <S extends string, T = unknown>(props: RouteProps<S, T>) => JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*@refresh skip*/
|
|
2
|
-
import { children, createMemo, createRoot, getOwner,
|
|
3
|
-
import { getRequestEvent, isServer } from "
|
|
2
|
+
import { children, createMemo, createRoot, getOwner, merge, untrack } from "solid-js";
|
|
3
|
+
import { getRequestEvent, isServer } from "@solidjs/web";
|
|
4
4
|
import { createBranches, createRouteContext, createRouterContext, getIntent, getRouteMatches, RouteContextObj, RouterContextObj, setInPreloadFn } from "../routing.js";
|
|
5
5
|
export const createRouterComponent = (router) => (props) => {
|
|
6
6
|
const { base } = props;
|
|
@@ -13,12 +13,12 @@ export const createRouterComponent = (router) => (props) => {
|
|
|
13
13
|
transformUrl: props.transformUrl,
|
|
14
14
|
});
|
|
15
15
|
router.create && router.create(routerState);
|
|
16
|
-
return (<RouterContextObj
|
|
17
|
-
<Root routerState={routerState} root={props.root} preload={props.rootPreload
|
|
16
|
+
return (<RouterContextObj value={routerState}>
|
|
17
|
+
<Root routerState={routerState} root={props.root} preload={props.rootPreload}>
|
|
18
18
|
{(context = getOwner()) && null}
|
|
19
19
|
<Routes routerState={routerState} branches={branches()}/>
|
|
20
20
|
</Root>
|
|
21
|
-
</RouterContextObj
|
|
21
|
+
</RouterContextObj>);
|
|
22
22
|
};
|
|
23
23
|
function Root(props) {
|
|
24
24
|
const location = props.routerState.location;
|
|
@@ -29,11 +29,13 @@ function Root(props) {
|
|
|
29
29
|
props.preload({ params, location, intent: getIntent() || "initial" });
|
|
30
30
|
setInPreloadFn(false);
|
|
31
31
|
}));
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const RootComp = props.root;
|
|
33
|
+
if (RootComp) {
|
|
34
|
+
return (<RootComp params={params} location={location} data={data()}>
|
|
35
|
+
{props.children}
|
|
36
|
+
</RootComp>);
|
|
37
|
+
}
|
|
38
|
+
return props.children;
|
|
37
39
|
}
|
|
38
40
|
function Routes(props) {
|
|
39
41
|
if (isServer) {
|
|
@@ -54,11 +56,14 @@ function Routes(props) {
|
|
|
54
56
|
}
|
|
55
57
|
const disposers = [];
|
|
56
58
|
let root;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
let prevMatches;
|
|
60
|
+
const routeStates = createMemo((prev) => {
|
|
61
|
+
const nextMatches = props.routerState.matches();
|
|
62
|
+
const previousMatches = prevMatches;
|
|
63
|
+
let equal = previousMatches && nextMatches.length === previousMatches.length;
|
|
59
64
|
const next = [];
|
|
60
65
|
for (let i = 0, len = nextMatches.length; i < len; i++) {
|
|
61
|
-
const prevMatch =
|
|
66
|
+
const prevMatch = previousMatches && previousMatches[i];
|
|
62
67
|
const nextMatch = nextMatches[i];
|
|
63
68
|
if (prev && prevMatch && nextMatch.route.key === prevMatch.route.key) {
|
|
64
69
|
next[i] = prev[i];
|
|
@@ -70,7 +75,7 @@ function Routes(props) {
|
|
|
70
75
|
}
|
|
71
76
|
createRoot(dispose => {
|
|
72
77
|
disposers[i] = dispose;
|
|
73
|
-
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => {
|
|
78
|
+
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()?.[i + 1]), () => {
|
|
74
79
|
const routeMatches = props.routerState.matches();
|
|
75
80
|
return routeMatches[i] ?? routeMatches[0];
|
|
76
81
|
});
|
|
@@ -79,21 +84,27 @@ function Routes(props) {
|
|
|
79
84
|
}
|
|
80
85
|
disposers.splice(nextMatches.length).forEach(dispose => dispose());
|
|
81
86
|
if (prev && equal) {
|
|
87
|
+
prevMatches = nextMatches;
|
|
82
88
|
return prev;
|
|
83
89
|
}
|
|
84
90
|
root = next[0];
|
|
91
|
+
prevMatches = nextMatches;
|
|
85
92
|
return next;
|
|
86
|
-
})
|
|
93
|
+
}, undefined);
|
|
87
94
|
return createOutlet(() => routeStates() && root)();
|
|
88
95
|
}
|
|
89
96
|
const createOutlet = (child) => {
|
|
90
|
-
return () =>
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
return () => {
|
|
98
|
+
const c = child();
|
|
99
|
+
if (c) {
|
|
100
|
+
return <RouteContextObj value={c}>{c.outlet()}</RouteContextObj>;
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
};
|
|
93
104
|
};
|
|
94
105
|
export const Route = (props) => {
|
|
95
106
|
const childRoutes = children(() => props.children);
|
|
96
|
-
return
|
|
107
|
+
return merge(props, {
|
|
97
108
|
get children() {
|
|
98
109
|
return childRoutes();
|
|
99
110
|
}
|
package/dist/routing.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { JSX, Accessor } from "solid-js";
|
|
2
2
|
import type { BeforeLeaveEventArgs, Branch, Intent, Location, MatchFilters, NavigateOptions, Navigator, Params, RouteDescription, RouteContext, RouteDefinition, RouteMatch, RouterContext, RouterIntegration, SearchParams, SetSearchParams } from "./types.js";
|
|
3
|
+
/** Consider this API opaque and internal. It is likely to change in the future. */
|
|
3
4
|
export declare const RouterContextObj: import("solid-js").Context<RouterContext | undefined>;
|
|
4
5
|
export declare const RouteContextObj: import("solid-js").Context<RouteContext | undefined>;
|
|
5
6
|
export declare const useRouter: () => RouterContext;
|
|
6
7
|
export declare const useRoute: () => RouteContext;
|
|
7
8
|
export declare const useResolvedPath: (path: () => string) => Accessor<string | undefined>;
|
|
8
|
-
export declare const useHref: (to: () =>
|
|
9
|
+
export declare const useHref: <T extends string | undefined>(to: () => T) => () => string | T;
|
|
9
10
|
/**
|
|
10
11
|
* Retrieves method to do navigation. The method accepts a path to navigate to and an optional object with the following options:
|
|
11
12
|
*
|
|
@@ -38,8 +39,8 @@ export declare const useNavigate: () => Navigator;
|
|
|
38
39
|
*/
|
|
39
40
|
export declare const useLocation: <S = unknown>() => Location<S>;
|
|
40
41
|
/**
|
|
41
|
-
* Retrieves signal that indicates whether the
|
|
42
|
-
* Useful for showing
|
|
42
|
+
* Retrieves a signal that indicates whether the router is currently processing a navigation.
|
|
43
|
+
* Useful for showing pending navigation state while the next route and its data settle.
|
|
43
44
|
*
|
|
44
45
|
* @example
|
|
45
46
|
* ```js
|
package/dist/routing.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createComponent, createContext, createMemo,
|
|
3
|
-
import { isServer, getRequestEvent } from "
|
|
1
|
+
import { flush, runWithOwner } from "solid-js";
|
|
2
|
+
import { createComponent, createContext, createMemo, createSignal, onCleanup, untrack, useContext } from "solid-js";
|
|
3
|
+
import { isServer, getRequestEvent } from "@solidjs/web";
|
|
4
4
|
import { createBeforeLeave } from "./lifecycle.js";
|
|
5
5
|
import { mockBase, createMemoObject, extractSearchParams, invariant, resolvePath, createMatcher, joinPaths, scoreRoute, mergeSearchString, expandOptionals } from "./utils.js";
|
|
6
6
|
const MAX_REDIRECTS = 100;
|
|
7
|
+
/** Consider this API opaque and internal. It is likely to change in the future. */
|
|
7
8
|
export const RouterContextObj = createContext();
|
|
8
9
|
export const RouteContextObj = createContext();
|
|
10
|
+
function useOptionalContext(context) {
|
|
11
|
+
try {
|
|
12
|
+
return useContext(context);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
9
18
|
export const useRouter = () => invariant(useContext(RouterContextObj), "<A> and 'use' router primitives can be only used inside a Route.");
|
|
10
19
|
let TempRoute;
|
|
11
|
-
export const useRoute = () => TempRoute ||
|
|
20
|
+
export const useRoute = () => TempRoute || useOptionalContext(RouteContextObj) || useRouter().base;
|
|
12
21
|
export const useResolvedPath = (path) => {
|
|
13
22
|
const route = useRoute();
|
|
14
23
|
return createMemo(() => route.resolvePath(path()));
|
|
@@ -52,8 +61,8 @@ export const useNavigate = () => useRouter().navigatorFactory();
|
|
|
52
61
|
*/
|
|
53
62
|
export const useLocation = () => useRouter().location;
|
|
54
63
|
/**
|
|
55
|
-
* Retrieves signal that indicates whether the
|
|
56
|
-
* Useful for showing
|
|
64
|
+
* Retrieves a signal that indicates whether the router is currently processing a navigation.
|
|
65
|
+
* Useful for showing pending navigation state while the next route and its data settle.
|
|
57
66
|
*
|
|
58
67
|
* @example
|
|
59
68
|
* ```js
|
|
@@ -204,12 +213,12 @@ export const useBeforeLeave = (listener) => {
|
|
|
204
213
|
onCleanup(s);
|
|
205
214
|
};
|
|
206
215
|
export function createRoutes(routeDef, base = "") {
|
|
207
|
-
const { component, preload,
|
|
216
|
+
const { component, preload, children, info } = routeDef;
|
|
208
217
|
const isLeaf = !children || (Array.isArray(children) && !children.length);
|
|
209
218
|
const shared = {
|
|
210
219
|
key: routeDef,
|
|
211
220
|
component,
|
|
212
|
-
preload
|
|
221
|
+
preload,
|
|
213
222
|
info
|
|
214
223
|
};
|
|
215
224
|
return asArray(routeDef.path).reduce((acc, originalPath) => {
|
|
@@ -308,7 +317,7 @@ function createLocation(path, state, queryWrapper) {
|
|
|
308
317
|
const search = createMemo(() => url().search, true);
|
|
309
318
|
const hash = createMemo(() => url().hash);
|
|
310
319
|
const key = () => "";
|
|
311
|
-
const queryFn =
|
|
320
|
+
const queryFn = createMemo(() => extractSearchParams(url()));
|
|
312
321
|
return {
|
|
313
322
|
get pathname() {
|
|
314
323
|
return pathname();
|
|
@@ -351,43 +360,32 @@ export function createRouterContext(integration, branches, getContext, options =
|
|
|
351
360
|
else if (basePath && !source().value) {
|
|
352
361
|
setSource({ value: basePath, replace: true, scroll: false });
|
|
353
362
|
}
|
|
354
|
-
const [isRouting, setIsRouting] = createSignal(false);
|
|
355
|
-
//
|
|
363
|
+
const [isRouting, setIsRouting] = createSignal(false, { pureWrite: true });
|
|
364
|
+
// Navigate override written from event handlers.
|
|
365
|
+
const [navigateTarget, setNavigateTarget] = createSignal(undefined, {
|
|
366
|
+
pureWrite: true
|
|
367
|
+
});
|
|
368
|
+
// Keep track of last target, so that last call to navigate wins
|
|
356
369
|
let lastTransitionTarget;
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
if (!isServer)
|
|
372
|
-
submissions[1](subs => subs.filter(s => s.pending));
|
|
373
|
-
}).finally(() => {
|
|
374
|
-
if (lastTransitionTarget !== newTarget)
|
|
375
|
-
return;
|
|
376
|
-
// Batch, in order for isRouting and final source update to happen together
|
|
377
|
-
batch(() => {
|
|
378
|
-
intent = undefined;
|
|
379
|
-
if (newIntent === "navigate")
|
|
380
|
-
navigateEnd(lastTransitionTarget);
|
|
381
|
-
setIsRouting(false);
|
|
382
|
-
lastTransitionTarget = undefined;
|
|
383
|
-
});
|
|
384
|
-
});
|
|
385
|
-
};
|
|
386
|
-
const [reference, setReference] = createSignal(source().value);
|
|
387
|
-
const [state, setState] = createSignal(source().state);
|
|
370
|
+
// source() remains canonical for native history changes; navigateTarget()
|
|
371
|
+
// temporarily overrides it for in-flight programmatic navigation.
|
|
372
|
+
const reference = createMemo(() => {
|
|
373
|
+
const nav = navigateTarget();
|
|
374
|
+
if (nav !== undefined)
|
|
375
|
+
return nav.value;
|
|
376
|
+
return source().value;
|
|
377
|
+
});
|
|
378
|
+
const state = createMemo(() => {
|
|
379
|
+
const nav = navigateTarget();
|
|
380
|
+
if (nav !== undefined)
|
|
381
|
+
return nav.state;
|
|
382
|
+
return source().state;
|
|
383
|
+
});
|
|
388
384
|
const location = createLocation(reference, state, utils.queryWrapper);
|
|
389
385
|
const referrers = [];
|
|
390
|
-
const submissions = createSignal(isServer ? initFromFlash() : []
|
|
386
|
+
const submissions = createSignal(isServer ? initFromFlash() : [], {
|
|
387
|
+
pureWrite: true
|
|
388
|
+
});
|
|
391
389
|
const matches = createMemo(() => {
|
|
392
390
|
if (typeof options.transformUrl === "function") {
|
|
393
391
|
return getRouteMatches(branches(), options.transformUrl(location.pathname));
|
|
@@ -413,8 +411,6 @@ export function createRouterContext(integration, branches, getContext, options =
|
|
|
413
411
|
return resolvePath(basePath, to);
|
|
414
412
|
}
|
|
415
413
|
};
|
|
416
|
-
// Create a native transition, when source updates
|
|
417
|
-
createRenderEffect(on(source, source => transition("native", source), { defer: true }));
|
|
418
414
|
return {
|
|
419
415
|
base: baseRoute,
|
|
420
416
|
location,
|
|
@@ -469,17 +465,35 @@ export function createRouterContext(integration, branches, getContext, options =
|
|
|
469
465
|
}
|
|
470
466
|
else if (beforeLeave.confirm(resolvedTo, options)) {
|
|
471
467
|
referrers.push({ value: current, replace, scroll, state: state() });
|
|
472
|
-
|
|
468
|
+
const newTarget = {
|
|
473
469
|
value: resolvedTo,
|
|
474
470
|
state: nextState
|
|
475
|
-
}
|
|
471
|
+
};
|
|
472
|
+
if (lastTransitionTarget === undefined) {
|
|
473
|
+
setIsRouting(true);
|
|
474
|
+
flush();
|
|
475
|
+
}
|
|
476
|
+
intent = "navigate";
|
|
477
|
+
lastTransitionTarget = newTarget;
|
|
478
|
+
if (lastTransitionTarget === newTarget) {
|
|
479
|
+
setNavigateTarget({ ...lastTransitionTarget });
|
|
480
|
+
queueMicrotask(() => {
|
|
481
|
+
if (lastTransitionTarget !== newTarget)
|
|
482
|
+
return;
|
|
483
|
+
intent = undefined;
|
|
484
|
+
navigateEnd(lastTransitionTarget);
|
|
485
|
+
setNavigateTarget(undefined);
|
|
486
|
+
setIsRouting(false);
|
|
487
|
+
lastTransitionTarget = undefined;
|
|
488
|
+
});
|
|
489
|
+
}
|
|
476
490
|
}
|
|
477
491
|
}
|
|
478
492
|
});
|
|
479
493
|
}
|
|
480
494
|
function navigatorFactory(route) {
|
|
481
495
|
// Workaround for vite issue (https://github.com/vitejs/vite/issues/3803)
|
|
482
|
-
route = route ||
|
|
496
|
+
route = route || useOptionalContext(RouteContextObj) || baseRoute;
|
|
483
497
|
return (to, options) => navigateFromRoute(route, to, options);
|
|
484
498
|
}
|
|
485
499
|
function navigateEnd(next) {
|
|
@@ -524,7 +538,15 @@ export function createRouterContext(integration, branches, getContext, options =
|
|
|
524
538
|
}
|
|
525
539
|
function initFromFlash() {
|
|
526
540
|
const e = getRequestEvent();
|
|
527
|
-
|
|
541
|
+
if (!(e && e.router && e.router.submission))
|
|
542
|
+
return [];
|
|
543
|
+
return [
|
|
544
|
+
{
|
|
545
|
+
...e.router.submission,
|
|
546
|
+
clear() { },
|
|
547
|
+
retry() { }
|
|
548
|
+
}
|
|
549
|
+
];
|
|
528
550
|
}
|
|
529
551
|
}
|
|
530
552
|
export function createRouteContext(router, parent, outlet, match) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Component, JSX, Signal } from "solid-js";
|
|
2
|
-
declare module "
|
|
2
|
+
declare module "@solidjs/web" {
|
|
3
3
|
interface RequestEvent {
|
|
4
4
|
response: {
|
|
5
5
|
status?: number;
|
|
@@ -12,6 +12,7 @@ declare module "solid-js/web" {
|
|
|
12
12
|
submission?: {
|
|
13
13
|
input: any;
|
|
14
14
|
result: any;
|
|
15
|
+
error?: any;
|
|
15
16
|
url: string;
|
|
16
17
|
};
|
|
17
18
|
dataOnly?: boolean | string[];
|
|
@@ -42,7 +43,7 @@ export interface NavigateOptions<S = unknown> {
|
|
|
42
43
|
state: S;
|
|
43
44
|
}
|
|
44
45
|
export interface Navigator {
|
|
45
|
-
(to: string, options?: Partial<NavigateOptions>): void;
|
|
46
|
+
(to: string | number, options?: Partial<NavigateOptions>): void;
|
|
46
47
|
(delta: number): void;
|
|
47
48
|
}
|
|
48
49
|
export type NavigatorFactory = (route?: RouteContext) => Navigator;
|
|
@@ -78,8 +79,6 @@ export type RouteDefinition<S extends string | string[] = any, T = unknown> = {
|
|
|
78
79
|
children?: RouteDefinition | RouteDefinition[];
|
|
79
80
|
component?: Component<RouteSectionProps<T>>;
|
|
80
81
|
info?: Record<string, any>;
|
|
81
|
-
/** @deprecated use preload */
|
|
82
|
-
load?: RoutePreloadFunc;
|
|
83
82
|
};
|
|
84
83
|
export type MatchFilter = readonly string[] | RegExp | ((s: string) => boolean);
|
|
85
84
|
export type PathParams<P extends string | readonly string[]> = P extends `${infer Head}/${infer Tail}` ? [...PathParams<Head>, ...PathParams<Tail>] : P extends `:${infer S}?` ? [S] : P extends `:${infer S}` ? [S] : P extends `*${infer S}` ? [S] : [];
|
|
@@ -166,20 +165,10 @@ export type Submission<T, U> = {
|
|
|
166
165
|
readonly input: T;
|
|
167
166
|
readonly result?: U;
|
|
168
167
|
readonly error: any;
|
|
169
|
-
readonly pending: boolean;
|
|
170
168
|
readonly url: string;
|
|
171
169
|
clear: () => void;
|
|
172
170
|
retry: () => void;
|
|
173
171
|
};
|
|
174
|
-
export type SubmissionStub = {
|
|
175
|
-
readonly input: undefined;
|
|
176
|
-
readonly result: undefined;
|
|
177
|
-
readonly error: undefined;
|
|
178
|
-
readonly pending: undefined;
|
|
179
|
-
readonly url: undefined;
|
|
180
|
-
clear: () => void;
|
|
181
|
-
retry: () => void;
|
|
182
|
-
};
|
|
183
172
|
export interface MaybePreloadableComponent extends Component {
|
|
184
173
|
preload?: () => void;
|
|
185
174
|
}
|
|
@@ -194,7 +183,3 @@ export type CustomResponse<T> = Omit<Response, "clone"> & {
|
|
|
194
183
|
customBody: () => T;
|
|
195
184
|
clone(...args: readonly unknown[]): CustomResponse<T>;
|
|
196
185
|
};
|
|
197
|
-
/** @deprecated */
|
|
198
|
-
export type RouteLoadFunc = RoutePreloadFunc;
|
|
199
|
-
/** @deprecated */
|
|
200
|
-
export type RouteLoadFuncArgs = RoutePreloadFuncArgs;
|
package/dist/utils.d.ts
CHANGED
|
@@ -10,3 +10,4 @@ export declare function scoreRoute(route: RouteDescription): number;
|
|
|
10
10
|
export declare function createMemoObject<T extends Record<string | symbol, unknown>>(fn: () => T): T;
|
|
11
11
|
export declare function mergeSearchString(search: string, params: SetSearchParams): string;
|
|
12
12
|
export declare function expandOptionals(pattern: string): string[];
|
|
13
|
+
export declare function setFunctionName<T>(obj: T, value: string): T;
|
package/dist/utils.js
CHANGED
|
@@ -175,3 +175,11 @@ export function expandOptionals(pattern) {
|
|
|
175
175
|
}
|
|
176
176
|
return expandOptionals(suffix).reduce((results, expansion) => [...results, ...prefixes.map(p => p + expansion)], []);
|
|
177
177
|
}
|
|
178
|
+
export function setFunctionName(obj, value) {
|
|
179
|
+
Object.defineProperty(obj, "name", {
|
|
180
|
+
value,
|
|
181
|
+
writable: false,
|
|
182
|
+
configurable: false
|
|
183
|
+
});
|
|
184
|
+
return obj;
|
|
185
|
+
}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"Ryan Turnquist"
|
|
7
7
|
],
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.17.0-next.0",
|
|
10
10
|
"homepage": "https://github.com/solidjs/solid-router#readme",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
],
|
|
30
30
|
"sideEffects": false,
|
|
31
31
|
"devDependencies": {
|
|
32
|
+
"@solidjs/web": "2.0.0-beta.3",
|
|
32
33
|
"@babel/core": "^7.26.0",
|
|
33
34
|
"@babel/preset-typescript": "^7.26.0",
|
|
34
35
|
"@changesets/cli": "^2.27.10",
|
|
@@ -37,21 +38,22 @@
|
|
|
37
38
|
"@rollup/plugin-terser": "0.4.4",
|
|
38
39
|
"@types/jest": "^29.5.14",
|
|
39
40
|
"@types/node": "^22.10.0",
|
|
40
|
-
"babel-preset-solid": "
|
|
41
|
+
"babel-preset-solid": "2.0.0-beta.3",
|
|
41
42
|
"jsdom": "^25.0.1",
|
|
42
43
|
"prettier": "^3.4.1",
|
|
43
44
|
"rollup": "^4.27.4",
|
|
44
|
-
"solid-js": "
|
|
45
|
+
"solid-js": "2.0.0-beta.3",
|
|
45
46
|
"typescript": "^5.7.2",
|
|
46
47
|
"vite": "^6.0.0",
|
|
47
|
-
"vite-plugin-solid": "
|
|
48
|
+
"vite-plugin-solid": "3.0.0-next.2",
|
|
48
49
|
"vitest": "^2.1.6"
|
|
49
50
|
},
|
|
50
51
|
"peerDependencies": {
|
|
51
|
-
"
|
|
52
|
+
"@solidjs/web": "^2.0.0-beta.3",
|
|
53
|
+
"solid-js": "^2.0.0-beta.3"
|
|
52
54
|
},
|
|
53
55
|
"scripts": {
|
|
54
|
-
"build": "tsc && rollup -c",
|
|
56
|
+
"build": "rm -rf dist && tsc && rollup -c",
|
|
55
57
|
"test": "vitest run && npm run test:types",
|
|
56
58
|
"test:watch": "vitest",
|
|
57
59
|
"test:types": "tsc --project tsconfig.test.json",
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { type ReconcileOptions } from "solid-js/store";
|
|
2
|
-
/**
|
|
3
|
-
* As `createAsync` and `createAsyncStore` are wrappers for `createResource`,
|
|
4
|
-
* this type allows to support `latest` field for these primitives.
|
|
5
|
-
* It will be removed in the future.
|
|
6
|
-
*/
|
|
7
|
-
export type AccessorWithLatest<T> = {
|
|
8
|
-
(): T;
|
|
9
|
-
latest: T;
|
|
10
|
-
};
|
|
11
|
-
export declare function createAsync<T>(fn: (prev: T) => Promise<T>, options: {
|
|
12
|
-
name?: string;
|
|
13
|
-
initialValue: T;
|
|
14
|
-
deferStream?: boolean;
|
|
15
|
-
}): AccessorWithLatest<T>;
|
|
16
|
-
export declare function createAsync<T>(fn: (prev: T | undefined) => Promise<T>, options?: {
|
|
17
|
-
name?: string;
|
|
18
|
-
initialValue?: T;
|
|
19
|
-
deferStream?: boolean;
|
|
20
|
-
}): AccessorWithLatest<T | undefined>;
|
|
21
|
-
export declare function createAsyncStore<T>(fn: (prev: T) => Promise<T>, options: {
|
|
22
|
-
name?: string;
|
|
23
|
-
initialValue: T;
|
|
24
|
-
deferStream?: boolean;
|
|
25
|
-
reconcile?: ReconcileOptions;
|
|
26
|
-
}): AccessorWithLatest<T>;
|
|
27
|
-
export declare function createAsyncStore<T>(fn: (prev: T | undefined) => Promise<T>, options?: {
|
|
28
|
-
name?: string;
|
|
29
|
-
initialValue?: T;
|
|
30
|
-
deferStream?: boolean;
|
|
31
|
-
reconcile?: ReconcileOptions;
|
|
32
|
-
}): AccessorWithLatest<T | undefined>;
|
package/dist/data/createAsync.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is mock of the eventual Solid 2.0 primitive. It is not fully featured.
|
|
3
|
-
*/
|
|
4
|
-
import { createResource, sharedConfig, untrack, catchError } from "solid-js";
|
|
5
|
-
import { createStore, reconcile, unwrap } from "solid-js/store";
|
|
6
|
-
import { isServer } from "solid-js/web";
|
|
7
|
-
export function createAsync(fn, options) {
|
|
8
|
-
let resource;
|
|
9
|
-
let prev = () => !resource || resource.state === "unresolved" ? undefined : resource.latest;
|
|
10
|
-
[resource] = createResource(() => subFetch(fn, catchError(() => untrack(prev), () => undefined)), v => v, options);
|
|
11
|
-
const resultAccessor = (() => resource());
|
|
12
|
-
Object.defineProperty(resultAccessor, "latest", {
|
|
13
|
-
get() {
|
|
14
|
-
return resource.latest;
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
return resultAccessor;
|
|
18
|
-
}
|
|
19
|
-
export function createAsyncStore(fn, options = {}) {
|
|
20
|
-
let resource;
|
|
21
|
-
let prev = () => !resource || resource.state === "unresolved"
|
|
22
|
-
? undefined
|
|
23
|
-
: unwrap(resource.latest);
|
|
24
|
-
[resource] = createResource(() => subFetch(fn, catchError(() => untrack(prev), () => undefined)), v => v, {
|
|
25
|
-
...options,
|
|
26
|
-
storage: (init) => createDeepSignal(init, options.reconcile)
|
|
27
|
-
});
|
|
28
|
-
const resultAccessor = (() => resource());
|
|
29
|
-
Object.defineProperty(resultAccessor, "latest", {
|
|
30
|
-
get() {
|
|
31
|
-
return resource.latest;
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
return resultAccessor;
|
|
35
|
-
}
|
|
36
|
-
function createDeepSignal(value, options) {
|
|
37
|
-
const [store, setStore] = createStore({
|
|
38
|
-
value: structuredClone(value)
|
|
39
|
-
});
|
|
40
|
-
return [
|
|
41
|
-
() => store.value,
|
|
42
|
-
(v) => {
|
|
43
|
-
typeof v === "function" && (v = v());
|
|
44
|
-
setStore("value", reconcile(structuredClone(v), options));
|
|
45
|
-
return store.value;
|
|
46
|
-
}
|
|
47
|
-
];
|
|
48
|
-
}
|
|
49
|
-
// mock promise while hydrating to prevent fetching
|
|
50
|
-
class MockPromise {
|
|
51
|
-
static all() {
|
|
52
|
-
return new MockPromise();
|
|
53
|
-
}
|
|
54
|
-
static allSettled() {
|
|
55
|
-
return new MockPromise();
|
|
56
|
-
}
|
|
57
|
-
static any() {
|
|
58
|
-
return new MockPromise();
|
|
59
|
-
}
|
|
60
|
-
static race() {
|
|
61
|
-
return new MockPromise();
|
|
62
|
-
}
|
|
63
|
-
static reject() {
|
|
64
|
-
return new MockPromise();
|
|
65
|
-
}
|
|
66
|
-
static resolve() {
|
|
67
|
-
return new MockPromise();
|
|
68
|
-
}
|
|
69
|
-
catch() {
|
|
70
|
-
return new MockPromise();
|
|
71
|
-
}
|
|
72
|
-
then() {
|
|
73
|
-
return new MockPromise();
|
|
74
|
-
}
|
|
75
|
-
finally() {
|
|
76
|
-
return new MockPromise();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
function subFetch(fn, prev) {
|
|
80
|
-
if (isServer || !sharedConfig.context)
|
|
81
|
-
return fn(prev);
|
|
82
|
-
const ogFetch = fetch;
|
|
83
|
-
const ogPromise = Promise;
|
|
84
|
-
try {
|
|
85
|
-
window.fetch = () => new MockPromise();
|
|
86
|
-
Promise = MockPromise;
|
|
87
|
-
return fn(prev);
|
|
88
|
-
}
|
|
89
|
-
finally {
|
|
90
|
-
window.fetch = ogFetch;
|
|
91
|
-
Promise = ogPromise;
|
|
92
|
-
}
|
|
93
|
-
}
|