@solidjs/router 0.9.1 → 0.10.0-beta.1
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 +323 -282
- package/dist/components.d.ts +7 -21
- package/dist/components.jsx +18 -30
- package/dist/data/action.d.ts +8 -0
- package/dist/data/action.js +113 -0
- package/dist/data/cache.d.ts +3 -0
- package/dist/data/cache.js +114 -0
- package/dist/data/createAsync.d.ts +5 -0
- package/dist/data/createAsync.js +54 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/data/index.js +3 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +441 -121
- package/dist/index.jsx +2 -1
- package/dist/routing.d.ts +8 -9
- package/dist/routing.js +159 -72
- package/dist/types.d.ts +26 -20
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +1 -0
- package/package.json +3 -3
package/dist/index.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./components";
|
|
2
2
|
export * from "./integration";
|
|
3
3
|
export * from "./lifecycle";
|
|
4
|
-
export {
|
|
4
|
+
export { useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, useResolvedPath, useSearchParams, useBeforeLeave, } from "./routing";
|
|
5
5
|
export { mergeSearchString as _mergeSearchString } from "./utils";
|
|
6
|
+
export * from "./data";
|
package/dist/routing.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { BeforeLeaveEventArgs, Branch, Location, LocationChangeSignal, MatchFilters, NavigateOptions, Navigator, Params, Route, RouteContext,
|
|
1
|
+
import { JSX, Accessor } from "solid-js";
|
|
2
|
+
import type { BeforeLeaveEventArgs, Branch, Intent, Location, LocationChangeSignal, MatchFilters, NavigateOptions, Navigator, Params, Route, RouteContext, RouteDefinition, RouteMatch, RouterContext, RouterIntegration, SetParams } from "./types";
|
|
3
3
|
export declare const RouterContextObj: import("solid-js").Context<RouterContext | undefined>;
|
|
4
4
|
export declare const RouteContextObj: import("solid-js").Context<RouteContext | undefined>;
|
|
5
5
|
export declare const useRouter: () => RouterContext;
|
|
@@ -11,15 +11,14 @@ export declare const useLocation: <S = unknown>() => Location<S>;
|
|
|
11
11
|
export declare const useIsRouting: () => () => boolean;
|
|
12
12
|
export declare const useMatch: <S extends string>(path: () => S, matchFilters?: MatchFilters<S> | undefined) => Accessor<import("./types").PathMatch | undefined>;
|
|
13
13
|
export declare const useParams: <T extends Params>() => T;
|
|
14
|
-
type MaybeReturnType<T> = T extends (...args: any) => infer R ? R : T;
|
|
15
|
-
export declare const useRouteData: <T>() => MaybeReturnType<T>;
|
|
16
14
|
export declare const useSearchParams: <T extends Params>() => [T, (params: SetParams, options?: Partial<NavigateOptions>) => void];
|
|
17
15
|
export declare const useBeforeLeave: (listener: (e: BeforeLeaveEventArgs) => void) => void;
|
|
18
|
-
export declare function createRoutes(routeDef: RouteDefinition, base?: string
|
|
16
|
+
export declare function createRoutes(routeDef: RouteDefinition, base?: string): Route[];
|
|
19
17
|
export declare function createBranch(routes: Route[], index?: number): Branch;
|
|
20
|
-
export declare function createBranches(routeDef: RouteDefinition | RouteDefinition[], base?: string,
|
|
18
|
+
export declare function createBranches(routeDef: RouteDefinition | RouteDefinition[], base?: string, stack?: Route[], branches?: Branch[]): Branch[];
|
|
21
19
|
export declare function getRouteMatches(branches: Branch[], location: string): RouteMatch[];
|
|
22
20
|
export declare function createLocation(path: Accessor<string>, state: Accessor<any>): Location;
|
|
23
|
-
export declare function
|
|
24
|
-
export declare function
|
|
25
|
-
export
|
|
21
|
+
export declare function registerAction(url: string, fn: Function): void;
|
|
22
|
+
export declare function getIntent(): Intent | undefined;
|
|
23
|
+
export declare function createRouterContext(integration?: RouterIntegration | LocationChangeSignal, getBranches?: () => Branch[], base?: string): RouterContext;
|
|
24
|
+
export declare function createRouteContext(router: RouterContext, parent: RouteContext, outlet: () => JSX.Element, match: () => RouteMatch, params: Params): RouteContext;
|
package/dist/routing.js
CHANGED
|
@@ -35,7 +35,6 @@ export const useMatch = (path, matchFilters) => {
|
|
|
35
35
|
});
|
|
36
36
|
};
|
|
37
37
|
export const useParams = () => useRoute().params;
|
|
38
|
-
export const useRouteData = () => useRoute().data;
|
|
39
38
|
export const useSearchParams = () => {
|
|
40
39
|
const location = useLocation();
|
|
41
40
|
const navigate = useNavigate();
|
|
@@ -57,23 +56,13 @@ export const useBeforeLeave = (listener) => {
|
|
|
57
56
|
});
|
|
58
57
|
onCleanup(s);
|
|
59
58
|
};
|
|
60
|
-
export function createRoutes(routeDef, base = ""
|
|
61
|
-
const { component,
|
|
59
|
+
export function createRoutes(routeDef, base = "") {
|
|
60
|
+
const { component, load, children } = routeDef;
|
|
62
61
|
const isLeaf = !children || (Array.isArray(children) && !children.length);
|
|
63
62
|
const shared = {
|
|
64
63
|
key: routeDef,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
: () => {
|
|
68
|
-
const { element } = routeDef;
|
|
69
|
-
return element === undefined && fallback
|
|
70
|
-
? createComponent(fallback, {})
|
|
71
|
-
: element;
|
|
72
|
-
},
|
|
73
|
-
preload: routeDef.component
|
|
74
|
-
? component.preload
|
|
75
|
-
: routeDef.preload,
|
|
76
|
-
data
|
|
64
|
+
component,
|
|
65
|
+
load
|
|
77
66
|
};
|
|
78
67
|
return asArray(routeDef.path).reduce((acc, path) => {
|
|
79
68
|
for (const originalPath of expandOptionals(path)) {
|
|
@@ -113,17 +102,19 @@ export function createBranch(routes, index = 0) {
|
|
|
113
102
|
function asArray(value) {
|
|
114
103
|
return Array.isArray(value) ? value : [value];
|
|
115
104
|
}
|
|
116
|
-
export function createBranches(routeDef, base = "",
|
|
105
|
+
export function createBranches(routeDef, base = "", stack = [], branches = []) {
|
|
117
106
|
const routeDefs = asArray(routeDef);
|
|
118
107
|
for (let i = 0, len = routeDefs.length; i < len; i++) {
|
|
119
108
|
const def = routeDefs[i];
|
|
120
|
-
if (def && typeof def === "object"
|
|
121
|
-
|
|
109
|
+
if (def && typeof def === "object") {
|
|
110
|
+
if (!def.hasOwnProperty("path"))
|
|
111
|
+
def.path = "";
|
|
112
|
+
const routes = createRoutes(def, base);
|
|
122
113
|
for (const route of routes) {
|
|
123
114
|
stack.push(route);
|
|
124
115
|
const isEmptyArray = Array.isArray(def.children) && def.children.length === 0;
|
|
125
116
|
if (def.children && !isEmptyArray) {
|
|
126
|
-
createBranches(def.children, route.pattern,
|
|
117
|
+
createBranches(def.children, route.pattern, stack, branches);
|
|
127
118
|
}
|
|
128
119
|
else {
|
|
129
120
|
const branch = createBranch([...stack], branches.length);
|
|
@@ -162,7 +153,7 @@ export function createLocation(path, state) {
|
|
|
162
153
|
const pathname = createMemo(() => url().pathname);
|
|
163
154
|
const search = createMemo(() => url().search, true);
|
|
164
155
|
const hash = createMemo(() => url().hash);
|
|
165
|
-
const key =
|
|
156
|
+
const key = () => "";
|
|
166
157
|
return {
|
|
167
158
|
get pathname() {
|
|
168
159
|
return pathname();
|
|
@@ -182,18 +173,21 @@ export function createLocation(path, state) {
|
|
|
182
173
|
query: createMemoObject(on(search, () => extractSearchParams(url())))
|
|
183
174
|
};
|
|
184
175
|
}
|
|
185
|
-
|
|
176
|
+
const actions = new Map();
|
|
177
|
+
export function registerAction(url, fn) {
|
|
178
|
+
actions.set(url, fn);
|
|
179
|
+
}
|
|
180
|
+
let intent;
|
|
181
|
+
export function getIntent() {
|
|
182
|
+
return intent;
|
|
183
|
+
}
|
|
184
|
+
export function createRouterContext(integration, getBranches, base = "") {
|
|
186
185
|
const { signal: [source, setSource], utils = {} } = normalizeIntegration(integration);
|
|
187
186
|
const parsePath = utils.parsePath || (p => p);
|
|
188
187
|
const renderPath = utils.renderPath || (p => p);
|
|
189
188
|
const beforeLeave = utils.beforeLeave || createBeforeLeave();
|
|
189
|
+
let submissions = [];
|
|
190
190
|
const basePath = resolvePath("", base);
|
|
191
|
-
const output = isServer && out
|
|
192
|
-
? Object.assign(out, {
|
|
193
|
-
matches: [],
|
|
194
|
-
url: undefined
|
|
195
|
-
})
|
|
196
|
-
: undefined;
|
|
197
191
|
if (basePath === undefined) {
|
|
198
192
|
throw new Error(`${basePath} is not a valid base path`);
|
|
199
193
|
}
|
|
@@ -223,20 +217,6 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
223
217
|
return resolvePath(basePath, to);
|
|
224
218
|
}
|
|
225
219
|
};
|
|
226
|
-
if (data) {
|
|
227
|
-
try {
|
|
228
|
-
TempRoute = baseRoute;
|
|
229
|
-
baseRoute.data = data({
|
|
230
|
-
data: undefined,
|
|
231
|
-
params: {},
|
|
232
|
-
location,
|
|
233
|
-
navigate: navigatorFactory(baseRoute)
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
finally {
|
|
237
|
-
TempRoute = undefined;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
220
|
function navigateFromRoute(route, to, options) {
|
|
241
221
|
// Untrack in case someone navigates in an effect - don't want to track `reference` or route paths
|
|
242
222
|
untrack(() => {
|
|
@@ -268,9 +248,6 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
268
248
|
const current = reference();
|
|
269
249
|
if (resolvedTo !== current || nextState !== state()) {
|
|
270
250
|
if (isServer) {
|
|
271
|
-
if (output) {
|
|
272
|
-
output.url = resolvedTo;
|
|
273
|
-
}
|
|
274
251
|
const e = getRequestEvent();
|
|
275
252
|
e && (e.response = Response.redirect(resolvedTo, 302));
|
|
276
253
|
setSource({ value: resolvedTo, replace, scroll, state: nextState });
|
|
@@ -278,11 +255,13 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
278
255
|
else if (beforeLeave.confirm(resolvedTo, options)) {
|
|
279
256
|
const len = referrers.push({ value: current, replace, scroll, state: state() });
|
|
280
257
|
start(() => {
|
|
258
|
+
intent = "navigate";
|
|
281
259
|
setReference(resolvedTo);
|
|
282
260
|
setState(nextState);
|
|
283
261
|
resetErrorBoundaries();
|
|
284
262
|
}).then(() => {
|
|
285
263
|
if (referrers.length === len) {
|
|
264
|
+
intent = undefined;
|
|
286
265
|
navigateEnd({
|
|
287
266
|
value: resolvedTo,
|
|
288
267
|
state: nextState
|
|
@@ -317,14 +296,21 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
317
296
|
untrack(() => {
|
|
318
297
|
if (value !== reference()) {
|
|
319
298
|
start(() => {
|
|
299
|
+
intent = "native";
|
|
320
300
|
setReference(value);
|
|
321
301
|
setState(state);
|
|
302
|
+
}).then(() => {
|
|
303
|
+
intent = undefined;
|
|
322
304
|
});
|
|
323
305
|
}
|
|
324
306
|
});
|
|
325
307
|
});
|
|
326
308
|
if (!isServer) {
|
|
327
|
-
|
|
309
|
+
let preloadTimeout = {};
|
|
310
|
+
function isSvg(el) {
|
|
311
|
+
return el.namespaceURI === "http://www.w3.org/2000/svg";
|
|
312
|
+
}
|
|
313
|
+
function handleAnchor(evt) {
|
|
328
314
|
if (evt.defaultPrevented ||
|
|
329
315
|
evt.button !== 0 ||
|
|
330
316
|
evt.metaKey ||
|
|
@@ -335,18 +321,27 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
335
321
|
const a = evt
|
|
336
322
|
.composedPath()
|
|
337
323
|
.find(el => el instanceof Node && el.nodeName.toUpperCase() === "A");
|
|
338
|
-
if (!a
|
|
324
|
+
if (!a)
|
|
339
325
|
return;
|
|
340
|
-
const
|
|
341
|
-
|
|
326
|
+
const svg = isSvg(a);
|
|
327
|
+
const href = svg ? a.href.baseVal : a.href;
|
|
328
|
+
const target = svg ? a.target.baseVal : a.target;
|
|
329
|
+
if (target || (!href && !a.hasAttribute("state")))
|
|
342
330
|
return;
|
|
343
331
|
const rel = (a.getAttribute("rel") || "").split(/\s+/);
|
|
344
332
|
if (a.hasAttribute("download") || (rel && rel.includes("external")))
|
|
345
333
|
return;
|
|
346
|
-
const url = new URL(href);
|
|
334
|
+
const url = svg ? new URL(href, document.baseURI) : new URL(href);
|
|
347
335
|
if (url.origin !== window.location.origin ||
|
|
348
336
|
(basePath && url.pathname && !url.pathname.toLowerCase().startsWith(basePath.toLowerCase())))
|
|
349
337
|
return;
|
|
338
|
+
return [a, url];
|
|
339
|
+
}
|
|
340
|
+
function handleAnchorClick(evt) {
|
|
341
|
+
const res = handleAnchor(evt);
|
|
342
|
+
if (!res)
|
|
343
|
+
return;
|
|
344
|
+
const [a, url] = res;
|
|
350
345
|
const to = parsePath(url.pathname + url.search + url.hash);
|
|
351
346
|
const state = a.getAttribute("state");
|
|
352
347
|
evt.preventDefault();
|
|
@@ -357,49 +352,141 @@ export function createRouterContext(integration, base = "", data, out) {
|
|
|
357
352
|
state: state && JSON.parse(state)
|
|
358
353
|
});
|
|
359
354
|
}
|
|
360
|
-
|
|
361
|
-
|
|
355
|
+
function doPreload(a, url) {
|
|
356
|
+
const preload = a.getAttribute("preload") !== "false";
|
|
357
|
+
const matches = getRouteMatches(getBranches(), url.pathname);
|
|
358
|
+
const prevIntent = intent;
|
|
359
|
+
intent = "preload";
|
|
360
|
+
for (let match in matches) {
|
|
361
|
+
const { route, params } = matches[match];
|
|
362
|
+
route.component &&
|
|
363
|
+
route.component.preload &&
|
|
364
|
+
route.component.preload();
|
|
365
|
+
preload &&
|
|
366
|
+
route.load &&
|
|
367
|
+
route.load({
|
|
368
|
+
params,
|
|
369
|
+
location: {
|
|
370
|
+
pathname: url.pathname,
|
|
371
|
+
search: url.search,
|
|
372
|
+
hash: url.hash,
|
|
373
|
+
query: extractSearchParams(url),
|
|
374
|
+
state: null,
|
|
375
|
+
key: ""
|
|
376
|
+
},
|
|
377
|
+
intent
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
intent = prevIntent;
|
|
381
|
+
}
|
|
382
|
+
function handleAnchorPreload(evt) {
|
|
383
|
+
const res = handleAnchor(evt);
|
|
384
|
+
if (!res)
|
|
385
|
+
return;
|
|
386
|
+
const [a, url] = res;
|
|
387
|
+
if (!preloadTimeout[url.pathname])
|
|
388
|
+
doPreload(a, url);
|
|
389
|
+
}
|
|
390
|
+
function handleAnchorIn(evt) {
|
|
391
|
+
const res = handleAnchor(evt);
|
|
392
|
+
if (!res)
|
|
393
|
+
return;
|
|
394
|
+
const [a, url] = res;
|
|
395
|
+
if (preloadTimeout[url.pathname])
|
|
396
|
+
return;
|
|
397
|
+
preloadTimeout[url.pathname] = setTimeout(() => {
|
|
398
|
+
doPreload(a, url);
|
|
399
|
+
delete preloadTimeout[url.pathname];
|
|
400
|
+
}, 200);
|
|
401
|
+
}
|
|
402
|
+
function handleAnchorOut(evt) {
|
|
403
|
+
const res = handleAnchor(evt);
|
|
404
|
+
if (!res)
|
|
405
|
+
return;
|
|
406
|
+
const [, url] = res;
|
|
407
|
+
if (preloadTimeout[url.pathname]) {
|
|
408
|
+
clearTimeout(preloadTimeout[url.pathname]);
|
|
409
|
+
delete preloadTimeout[url.pathname];
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function handleFormSubmit(evt) {
|
|
413
|
+
let actionRef = (evt.submitter && evt.submitter.getAttribute("formaction")) || evt.target.action;
|
|
414
|
+
if (actionRef && actionRef.startsWith("action:")) {
|
|
415
|
+
const data = new FormData(evt.target);
|
|
416
|
+
actions.get(actionRef.slice(7))(data);
|
|
417
|
+
evt.preventDefault();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// ensure delegated event run first
|
|
421
|
+
delegateEvents(["click", "submit"]);
|
|
362
422
|
document.addEventListener("click", handleAnchorClick);
|
|
363
|
-
|
|
423
|
+
document.addEventListener("mouseover", handleAnchorIn);
|
|
424
|
+
document.addEventListener("mouseout", handleAnchorOut);
|
|
425
|
+
document.addEventListener("focusin", handleAnchorPreload);
|
|
426
|
+
document.addEventListener("touchstart", handleAnchorPreload);
|
|
427
|
+
document.addEventListener("submit", handleFormSubmit);
|
|
428
|
+
onCleanup(() => {
|
|
429
|
+
document.removeEventListener("click", handleAnchorClick);
|
|
430
|
+
document.removeEventListener("mouseover", handleAnchorIn);
|
|
431
|
+
document.removeEventListener("mouseout", handleAnchorOut);
|
|
432
|
+
document.removeEventListener("focusin", handleAnchorPreload);
|
|
433
|
+
document.removeEventListener("touchstart", handleAnchorPreload);
|
|
434
|
+
document.removeEventListener("submit", handleFormSubmit);
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
function initFromFlash(params) {
|
|
439
|
+
let param = params.form ? JSON.parse(params.form) : null;
|
|
440
|
+
if (!param || !param.result) {
|
|
441
|
+
return [];
|
|
442
|
+
}
|
|
443
|
+
const input = new Map(param.entries);
|
|
444
|
+
return [
|
|
445
|
+
{
|
|
446
|
+
url: param.url,
|
|
447
|
+
result: param.error ? new Error(param.result.message) : param.result,
|
|
448
|
+
input: input
|
|
449
|
+
}
|
|
450
|
+
];
|
|
451
|
+
}
|
|
452
|
+
submissions = initFromFlash(location.query);
|
|
364
453
|
}
|
|
365
454
|
return {
|
|
366
455
|
base: baseRoute,
|
|
367
|
-
out: output,
|
|
368
456
|
location,
|
|
369
457
|
isRouting,
|
|
370
458
|
renderPath,
|
|
371
459
|
parsePath,
|
|
372
460
|
navigatorFactory,
|
|
373
|
-
beforeLeave
|
|
461
|
+
beforeLeave,
|
|
462
|
+
submissions: createSignal(submissions)
|
|
374
463
|
};
|
|
375
464
|
}
|
|
376
|
-
export function createRouteContext(router, parent,
|
|
377
|
-
const { base, location
|
|
378
|
-
const { pattern,
|
|
465
|
+
export function createRouteContext(router, parent, outlet, match, params) {
|
|
466
|
+
const { base, location } = router;
|
|
467
|
+
const { pattern, component, load } = match().route;
|
|
379
468
|
const path = createMemo(() => match().path);
|
|
380
|
-
preload && preload();
|
|
381
469
|
const route = {
|
|
382
470
|
parent,
|
|
383
471
|
pattern,
|
|
384
|
-
get child() {
|
|
385
|
-
return child();
|
|
386
|
-
},
|
|
387
472
|
path,
|
|
388
473
|
params,
|
|
389
|
-
|
|
390
|
-
|
|
474
|
+
outlet: () => component
|
|
475
|
+
? createComponent(component, {
|
|
476
|
+
params,
|
|
477
|
+
location,
|
|
478
|
+
get children() {
|
|
479
|
+
return outlet();
|
|
480
|
+
}
|
|
481
|
+
})
|
|
482
|
+
: outlet(),
|
|
391
483
|
resolvePath(to) {
|
|
392
484
|
return resolvePath(base.path(), to, path());
|
|
393
485
|
}
|
|
394
486
|
};
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
finally {
|
|
401
|
-
TempRoute = undefined;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
487
|
+
component &&
|
|
488
|
+
component.preload &&
|
|
489
|
+
component.preload();
|
|
490
|
+
load && load({ params, location, intent: intent || "navigate" });
|
|
404
491
|
return route;
|
|
405
492
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Component, JSX } from "solid-js";
|
|
1
|
+
import { Component, JSX, Signal } from "solid-js";
|
|
2
2
|
declare module "solid-js/web" {
|
|
3
3
|
interface RequestEvent {
|
|
4
4
|
response?: Response;
|
|
5
|
+
routerCache?: Map<any, any>;
|
|
5
6
|
}
|
|
6
7
|
}
|
|
7
8
|
export type Params = Record<string, string>;
|
|
@@ -38,26 +39,25 @@ export interface RouterIntegration {
|
|
|
38
39
|
signal: LocationChangeSignal;
|
|
39
40
|
utils?: Partial<RouterUtils>;
|
|
40
41
|
}
|
|
41
|
-
export
|
|
42
|
-
|
|
42
|
+
export type Intent = "native" | "navigate" | "preload";
|
|
43
|
+
export interface RouteLoadFuncArgs {
|
|
43
44
|
params: Params;
|
|
44
45
|
location: Location;
|
|
45
|
-
|
|
46
|
+
intent: Intent;
|
|
47
|
+
}
|
|
48
|
+
export type RouteLoadFunc = (args: RouteLoadFuncArgs) => void;
|
|
49
|
+
export interface RouteSectionProps {
|
|
50
|
+
params: Params;
|
|
51
|
+
location: Location;
|
|
52
|
+
children?: JSX.Element;
|
|
46
53
|
}
|
|
47
|
-
export type RouteDataFunc<T = unknown, R = unknown> = (args: RouteDataFuncArgs<T>) => R;
|
|
48
54
|
export type RouteDefinition<S extends string | string[] = any> = {
|
|
49
|
-
path
|
|
55
|
+
path?: S;
|
|
50
56
|
matchFilters?: MatchFilters<S>;
|
|
51
|
-
|
|
57
|
+
load?: RouteLoadFunc;
|
|
52
58
|
children?: RouteDefinition | RouteDefinition[];
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
component: Component;
|
|
56
|
-
} | {
|
|
57
|
-
component?: never;
|
|
58
|
-
element?: JSX.Element;
|
|
59
|
-
preload?: () => void;
|
|
60
|
-
});
|
|
59
|
+
component?: Component<RouteSectionProps>;
|
|
60
|
+
};
|
|
61
61
|
export type MatchFilter = readonly string[] | RegExp | ((s: string) => boolean);
|
|
62
62
|
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] : [];
|
|
63
63
|
export type MatchFilters<P extends string | readonly string[] = any> = P extends string ? {
|
|
@@ -80,9 +80,8 @@ export interface Route {
|
|
|
80
80
|
key: unknown;
|
|
81
81
|
originalPath: string;
|
|
82
82
|
pattern: string;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
data?: RouteDataFunc;
|
|
83
|
+
component?: Component<RouteSectionProps>;
|
|
84
|
+
load?: RouteLoadFunc;
|
|
86
85
|
matcher: (location: string) => PathMatch | null;
|
|
87
86
|
matchFilters?: MatchFilters;
|
|
88
87
|
}
|
|
@@ -94,7 +93,6 @@ export interface Branch {
|
|
|
94
93
|
export interface RouteContext {
|
|
95
94
|
parent?: RouteContext;
|
|
96
95
|
child?: RouteContext;
|
|
97
|
-
data?: unknown;
|
|
98
96
|
pattern: string;
|
|
99
97
|
params: Params;
|
|
100
98
|
path: () => string;
|
|
@@ -119,13 +117,13 @@ export interface RouterOutput {
|
|
|
119
117
|
}
|
|
120
118
|
export interface RouterContext {
|
|
121
119
|
base: RouteContext;
|
|
122
|
-
out?: RouterOutput;
|
|
123
120
|
location: Location;
|
|
124
121
|
navigatorFactory: NavigatorFactory;
|
|
125
122
|
isRouting: () => boolean;
|
|
126
123
|
renderPath(path: string): string;
|
|
127
124
|
parsePath(str: string): string;
|
|
128
125
|
beforeLeave: BeforeLeaveLifecycle;
|
|
126
|
+
submissions: Signal<Submission<any, any>[]>;
|
|
129
127
|
}
|
|
130
128
|
export interface BeforeLeaveEventArgs {
|
|
131
129
|
from: Location;
|
|
@@ -144,3 +142,11 @@ export interface BeforeLeaveLifecycle {
|
|
|
144
142
|
subscribe(listener: BeforeLeaveListener): () => void;
|
|
145
143
|
confirm(to: string | number, options?: Partial<NavigateOptions>): boolean;
|
|
146
144
|
}
|
|
145
|
+
export type Submission<T, U> = {
|
|
146
|
+
readonly input: T;
|
|
147
|
+
readonly result?: U;
|
|
148
|
+
readonly pending: boolean;
|
|
149
|
+
readonly url: string;
|
|
150
|
+
clear: () => void;
|
|
151
|
+
retry: () => void;
|
|
152
|
+
};
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MatchFilters, Params, PathMatch, Route, SetParams } from "./types";
|
|
2
|
+
export declare const redirectStatusCodes: Set<number>;
|
|
2
3
|
export declare function normalizePath(path: string, omitSlash?: boolean): string;
|
|
3
4
|
export declare function resolvePath(base: string, path: string, from?: string): string | undefined;
|
|
4
5
|
export declare function invariant<T>(value: T | null | undefined, message: string): T;
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createMemo, getOwner, runWithOwner } from "solid-js";
|
|
2
2
|
const hasSchemeRegex = /^(?:[a-z0-9]+:)?\/\//i;
|
|
3
3
|
const trimPathRegex = /^\/+|(\/)\/+$/g;
|
|
4
|
+
export const redirectStatusCodes = new Set([204, 301, 302, 303, 307, 308]);
|
|
4
5
|
export function normalizePath(path, omitSlash = false) {
|
|
5
6
|
const s = path.replace(trimPathRegex, "$1");
|
|
6
7
|
return s ? (omitSlash || /^[?#]/.test(s) ? s : "/" + s) : "";
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"Ryan Turnquist"
|
|
7
7
|
],
|
|
8
8
|
"license": "MIT",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.10.0-beta.1",
|
|
10
10
|
"homepage": "https://github.com/solidjs/solid-router#readme",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@rollup/plugin-node-resolve": "15.0.1",
|
|
36
36
|
"@rollup/plugin-terser": "0.2.0",
|
|
37
37
|
"@types/jest": "^29.0.0",
|
|
38
|
-
"@types/node": "^
|
|
38
|
+
"@types/node": "^20.9.0",
|
|
39
39
|
"babel-jest": "^29.0.1",
|
|
40
40
|
"babel-preset-solid": "^1.6.6",
|
|
41
41
|
"jest": "^29.0.1",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"rollup": "^3.7.5",
|
|
45
45
|
"solid-jest": "^0.2.0",
|
|
46
46
|
"solid-js": "^1.8.4",
|
|
47
|
-
"typescript": "^
|
|
47
|
+
"typescript": "^5.2.2"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"solid-js": "^1.8.4"
|