@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.
Files changed (78) hide show
  1. package/README.md +85 -79
  2. package/dist/components.jsx +22 -16
  3. package/dist/data/action.d.ts +12 -10
  4. package/dist/data/action.js +98 -78
  5. package/dist/data/events.d.ts +8 -1
  6. package/dist/data/events.js +3 -3
  7. package/dist/data/index.d.ts +2 -3
  8. package/dist/data/index.js +2 -3
  9. package/dist/data/query.d.ts +1 -3
  10. package/dist/data/query.js +10 -16
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +212 -261
  13. package/dist/index.jsx +1 -1
  14. package/dist/lifecycle.js +1 -1
  15. package/dist/routers/HashRouter.js +1 -1
  16. package/dist/routers/MemoryRouter.js +1 -1
  17. package/dist/routers/Router.js +2 -2
  18. package/dist/routers/StaticRouter.js +1 -1
  19. package/dist/routers/components.d.ts +0 -4
  20. package/dist/routers/components.jsx +30 -19
  21. package/dist/routing.d.ts +4 -3
  22. package/dist/routing.js +71 -49
  23. package/dist/types.d.ts +3 -18
  24. package/dist/utils.d.ts +1 -0
  25. package/dist/utils.js +8 -0
  26. package/package.json +8 -6
  27. package/dist/data/createAsync.d.ts +0 -32
  28. package/dist/data/createAsync.js +0 -93
  29. package/dist/src/components.d.ts +0 -31
  30. package/dist/src/components.jsx +0 -39
  31. package/dist/src/data/action.d.ts +0 -17
  32. package/dist/src/data/action.js +0 -163
  33. package/dist/src/data/action.spec.d.ts +0 -1
  34. package/dist/src/data/action.spec.js +0 -297
  35. package/dist/src/data/createAsync.d.ts +0 -32
  36. package/dist/src/data/createAsync.js +0 -96
  37. package/dist/src/data/createAsync.spec.d.ts +0 -1
  38. package/dist/src/data/createAsync.spec.js +0 -196
  39. package/dist/src/data/events.d.ts +0 -9
  40. package/dist/src/data/events.js +0 -123
  41. package/dist/src/data/events.spec.d.ts +0 -1
  42. package/dist/src/data/events.spec.js +0 -567
  43. package/dist/src/data/index.d.ts +0 -4
  44. package/dist/src/data/index.js +0 -4
  45. package/dist/src/data/query.d.ts +0 -23
  46. package/dist/src/data/query.js +0 -232
  47. package/dist/src/data/query.spec.d.ts +0 -1
  48. package/dist/src/data/query.spec.js +0 -354
  49. package/dist/src/data/response.d.ts +0 -4
  50. package/dist/src/data/response.js +0 -42
  51. package/dist/src/data/response.spec.d.ts +0 -1
  52. package/dist/src/data/response.spec.js +0 -165
  53. package/dist/src/index.d.ts +0 -7
  54. package/dist/src/index.jsx +0 -6
  55. package/dist/src/lifecycle.d.ts +0 -5
  56. package/dist/src/lifecycle.js +0 -69
  57. package/dist/src/routers/HashRouter.d.ts +0 -9
  58. package/dist/src/routers/HashRouter.js +0 -41
  59. package/dist/src/routers/MemoryRouter.d.ts +0 -24
  60. package/dist/src/routers/MemoryRouter.js +0 -57
  61. package/dist/src/routers/Router.d.ts +0 -9
  62. package/dist/src/routers/Router.js +0 -45
  63. package/dist/src/routers/StaticRouter.d.ts +0 -6
  64. package/dist/src/routers/StaticRouter.js +0 -15
  65. package/dist/src/routers/components.d.ts +0 -27
  66. package/dist/src/routers/components.jsx +0 -118
  67. package/dist/src/routers/createRouter.d.ts +0 -10
  68. package/dist/src/routers/createRouter.js +0 -41
  69. package/dist/src/routers/index.d.ts +0 -11
  70. package/dist/src/routers/index.js +0 -6
  71. package/dist/src/routing.d.ts +0 -175
  72. package/dist/src/routing.js +0 -560
  73. package/dist/src/types.d.ts +0 -200
  74. package/dist/src/types.js +0 -1
  75. package/dist/src/utils.d.ts +0 -13
  76. package/dist/src/utils.js +0 -185
  77. package/dist/test/helpers.d.ts +0 -6
  78. 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
@@ -1,4 +1,4 @@
1
- import { isServer } from "solid-js/web";
1
+ import { isServer } from "@solidjs/web";
2
2
  export function createBeforeLeave() {
3
3
  let listeners = new Set();
4
4
  function subscribe(listener) {
@@ -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
  }
@@ -1,4 +1,4 @@
1
- import { isServer } from "solid-js/web";
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
@@ -1,4 +1,4 @@
1
- import { getRequestEvent } from "solid-js/web";
1
+ import { getRequestEvent } from "@solidjs/web";
2
2
  import { createRouterComponent } from "./components.jsx";
3
3
  function getPath(url) {
4
4
  const u = new URL(url);
@@ -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, mergeProps, on, Show, untrack } from "solid-js";
3
- import { getRequestEvent, isServer } from "solid-js/web";
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.Provider value={routerState}>
17
- <Root routerState={routerState} root={props.root} preload={props.rootPreload || props.rootLoad}>
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.Provider>);
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
- return (<Show when={props.root} keyed fallback={props.children}>
33
- {Root => (<Root params={params} location={location} data={data()}>
34
- {props.children}
35
- </Root>)}
36
- </Show>);
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
- const routeStates = createMemo(on(props.routerState.matches, (nextMatches, prevMatches, prev) => {
58
- let equal = prevMatches && nextMatches.length === prevMatches.length;
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 = prevMatches && prevMatches[i];
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 () => (<Show when={child()} keyed>
91
- {child => <RouteContextObj.Provider value={child}>{child.outlet()}</RouteContextObj.Provider>}
92
- </Show>);
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 mergeProps(props, {
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: () => string | undefined) => Accessor<string | undefined>;
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 route is currently in a *Transition*.
42
- * Useful for showing stale/pending state when the route resolution is *Suspended* during concurrent rendering.
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 { runWithOwner, batch } from "solid-js";
2
- import { createComponent, createContext, createMemo, createRenderEffect, createSignal, on, onCleanup, untrack, useContext, startTransition, resetErrorBoundaries } from "solid-js";
3
- import { isServer, getRequestEvent } from "solid-js/web";
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 || useContext(RouteContextObj) || useRouter().base;
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 route is currently in a *Transition*.
56
- * Useful for showing stale/pending state when the route resolution is *Suspended* during concurrent rendering.
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, load, children, info } = routeDef;
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: preload || load,
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 = on(search, () => extractSearchParams(url()));
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
- // Keep track of last target, so that last call to transition wins
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
- // Transition the location to a new value
358
- const transition = (newIntent, newTarget) => {
359
- if (newTarget.value === reference() && newTarget.state === state())
360
- return;
361
- if (lastTransitionTarget === undefined)
362
- setIsRouting(true);
363
- intent = newIntent;
364
- lastTransitionTarget = newTarget;
365
- startTransition(() => {
366
- if (lastTransitionTarget !== newTarget)
367
- return;
368
- setReference(lastTransitionTarget.value);
369
- setState(lastTransitionTarget.state);
370
- resetErrorBoundaries();
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
- transition("navigate", {
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 || useContext(RouteContextObj) || baseRoute;
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
- return (e && e.router && e.router.submission ? [e.router.submission] : []);
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 "solid-js/web" {
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.16.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": "^1.9.3",
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": "^1.9.3",
45
+ "solid-js": "2.0.0-beta.3",
45
46
  "typescript": "^5.7.2",
46
47
  "vite": "^6.0.0",
47
- "vite-plugin-solid": "^2.11.0",
48
+ "vite-plugin-solid": "3.0.0-next.2",
48
49
  "vitest": "^2.1.6"
49
50
  },
50
51
  "peerDependencies": {
51
- "solid-js": "^1.8.6"
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>;
@@ -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
- }