@solidjs/router 0.17.0-next.0 → 0.17.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -380,7 +380,7 @@ const useCurrentMatches = () => useRouter().matches;
380
380
  * const params = useParams();
381
381
  *
382
382
  * // fetch user based on the id path parameter
383
- * const [user] = createResource(() => params.id, fetchUser);
383
+ * const getUser = query(() => fetchUser(params.id), "user");
384
384
  * ```
385
385
  */
386
386
  const useParams = () => useRouter().params;
@@ -551,7 +551,7 @@ function getRouteMatches(branches, location) {
551
551
  }
552
552
  function createLocation(path, state, queryWrapper) {
553
553
  const origin = new URL(mockBase);
554
- const url = createMemo(prev => {
554
+ const url = createMemo((prev = origin) => {
555
555
  const path_ = path();
556
556
  try {
557
557
  return new URL(path_, origin);
@@ -559,11 +559,11 @@ function createLocation(path, state, queryWrapper) {
559
559
  console.error(`Invalid path ${path_}`);
560
560
  return prev;
561
561
  }
562
- }, origin, {
562
+ }, {
563
563
  equals: (a, b) => a.href === b.href
564
564
  });
565
565
  const pathname = createMemo(() => url().pathname);
566
- const search = createMemo(() => url().search, true);
566
+ const search = createMemo(() => url().search);
567
567
  const hash = createMemo(() => url().hash);
568
568
  const key = () => "";
569
569
  const queryFn = createMemo(() => extractSearchParams(url()));
@@ -606,9 +606,10 @@ function createRouterContext(integration, branches, getContext, options = {}) {
606
606
  const renderPath = utils.renderPath || (p => p);
607
607
  const beforeLeave = utils.beforeLeave || createBeforeLeave();
608
608
  const basePath = resolvePath("", options.base || "");
609
+ const initialSource = untrack(source);
609
610
  if (basePath === undefined) {
610
611
  throw new Error(`${basePath} is not a valid base path`);
611
- } else if (basePath && !source().value) {
612
+ } else if (basePath && !initialSource.value) {
612
613
  setSource({
613
614
  value: basePath,
614
615
  replace: true,
@@ -616,12 +617,12 @@ function createRouterContext(integration, branches, getContext, options = {}) {
616
617
  });
617
618
  }
618
619
  const [isRouting, setIsRouting] = createSignal(false, {
619
- pureWrite: true
620
+ ownedWrite: true
620
621
  });
621
622
 
622
623
  // Navigate override written from event handlers.
623
624
  const [navigateTarget, setNavigateTarget] = createSignal(undefined, {
624
- pureWrite: true
625
+ ownedWrite: true
625
626
  });
626
627
 
627
628
  // Keep track of last target, so that last call to navigate wins
@@ -629,20 +630,11 @@ function createRouterContext(integration, branches, getContext, options = {}) {
629
630
 
630
631
  // source() remains canonical for native history changes; navigateTarget()
631
632
  // temporarily overrides it for in-flight programmatic navigation.
632
- const reference = createMemo(() => {
633
- const nav = navigateTarget();
634
- if (nav !== undefined) return nav.value;
635
- return source().value;
636
- });
637
- const state = createMemo(() => {
638
- const nav = navigateTarget();
639
- if (nav !== undefined) return nav.state;
640
- return source().state;
641
- });
642
- const location = createLocation(reference, state, utils.queryWrapper);
633
+ const effective = createMemo(() => navigateTarget() ?? source());
634
+ const location = createLocation(() => effective().value, () => effective().state, utils.queryWrapper);
643
635
  const referrers = [];
644
636
  const submissions = createSignal(isServer ? initFromFlash() : [], {
645
- pureWrite: true
637
+ ownedWrite: true
646
638
  });
647
639
  const matches = createMemo(() => {
648
640
  if (typeof options.transformUrl === "function") {
@@ -710,8 +702,8 @@ function createRouterContext(integration, branches, getContext, options = {}) {
710
702
  } else if (referrers.length >= MAX_REDIRECTS) {
711
703
  throw new Error("Too many redirects");
712
704
  }
713
- const current = reference();
714
- if (resolvedTo !== current || nextState !== state()) {
705
+ const current = effective();
706
+ if (resolvedTo !== current.value || nextState !== current.state) {
715
707
  if (isServer) {
716
708
  const e = getRequestEvent();
717
709
  e && (e.response = {
@@ -728,10 +720,10 @@ function createRouterContext(integration, branches, getContext, options = {}) {
728
720
  });
729
721
  } else if (beforeLeave.confirm(resolvedTo, options)) {
730
722
  referrers.push({
731
- value: current,
723
+ value: current.value,
732
724
  replace,
733
725
  scroll,
734
- state: state()
726
+ state: current.state
735
727
  });
736
728
  const newTarget = {
737
729
  value: resolvedTo,
@@ -855,17 +847,29 @@ function createRouteContext(router, parent, outlet, match) {
855
847
  return route;
856
848
  }
857
849
 
858
- const createRouterComponent = router => props => {
850
+ const createRouterComponent = router => function IntegratedRouter(props) {
859
851
  const {
860
- base
861
- } = props;
862
- const routeDefs = children(() => props.children);
863
- const branches = createMemo(() => createBranches(routeDefs(), props.base || ""));
852
+ base,
853
+ singleFlight,
854
+ transformUrl,
855
+ root,
856
+ rootPreload,
857
+ routeChildren
858
+ } = untrack(() => ({
859
+ base: props.base,
860
+ singleFlight: props.singleFlight,
861
+ transformUrl: props.transformUrl,
862
+ root: props.root,
863
+ rootPreload: props.rootPreload,
864
+ routeChildren: props.children
865
+ }));
866
+ const routeDefs = children(() => routeChildren);
867
+ const branches = createMemo(() => createBranches(routeDefs(), base || ""));
864
868
  let context;
865
869
  const routerState = createRouterContext(router, branches, () => context, {
866
870
  base,
867
- singleFlight: props.singleFlight,
868
- transformUrl: props.transformUrl
871
+ singleFlight,
872
+ transformUrl
869
873
  });
870
874
  router.create && router.create(routerState);
871
875
  return createComponent$1(RouterContextObj, {
@@ -873,12 +877,8 @@ const createRouterComponent = router => props => {
873
877
  get children() {
874
878
  return createComponent$1(Root, {
875
879
  routerState: routerState,
876
- get root() {
877
- return props.root;
878
- },
879
- get preload() {
880
- return props.rootPreload;
881
- },
880
+ root: root,
881
+ preload: rootPreload,
882
882
  get children() {
883
883
  return [memo(() => (context = getOwner()) && null), createComponent$1(Routes, {
884
884
  routerState: routerState,
@@ -972,8 +972,9 @@ function Routes(props) {
972
972
  root = next[0];
973
973
  prevMatches = nextMatches;
974
974
  return next;
975
- }, undefined);
976
- return createOutlet(() => routeStates() && root)();
975
+ });
976
+ const outlet = createOutlet(() => routeStates() && root);
977
+ return memo(outlet);
977
978
  }
978
979
  const createOutlet = child => {
979
980
  return () => {
@@ -1017,21 +1018,20 @@ function dataOnly(event, routerState, branches) {
1017
1018
  }
1018
1019
  }
1019
1020
 
1020
- function intercept([value, setValue], get, set) {
1021
- return [value, set ? v => setValue(set(v)) : setValue];
1022
- }
1023
1021
  function createRouter(config) {
1024
1022
  let ignore = false;
1025
1023
  const wrap = value => typeof value === "string" ? {
1026
1024
  value
1027
1025
  } : value;
1028
- const signal = intercept(createSignal(wrap(config.get()), {
1029
- equals: (a, b) => a.value === b.value && a.state === b.state
1030
- }), undefined, next => {
1026
+ const [read, write] = createSignal(wrap(config.get()), {
1027
+ equals: (a, b) => a.value === b.value && a.state === b.state,
1028
+ ownedWrite: true
1029
+ });
1030
+ const signal = [read, next => {
1031
1031
  !ignore && config.set(next);
1032
1032
  if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = true;
1033
- return next;
1034
- });
1033
+ write(next);
1034
+ }];
1035
1035
  config.init && onCleanup(config.init((value = config.get()) => {
1036
1036
  ignore = true;
1037
1037
  signal[1](wrap(value));
@@ -1752,7 +1752,7 @@ function A(props) {
1752
1752
  get ["aria-current"]() {
1753
1753
  return isActive()[1] ? "page" : undefined;
1754
1754
  }
1755
- }), false, false);
1755
+ }), false);
1756
1756
  return _el$;
1757
1757
  })();
1758
1758
  }
@@ -2,19 +2,26 @@
2
2
  import { children, createMemo, createRoot, getOwner, merge, untrack } from "solid-js";
3
3
  import { getRequestEvent, isServer } from "@solidjs/web";
4
4
  import { createBranches, createRouteContext, createRouterContext, getIntent, getRouteMatches, RouteContextObj, RouterContextObj, setInPreloadFn } from "../routing.js";
5
- export const createRouterComponent = (router) => (props) => {
6
- const { base } = props;
7
- const routeDefs = children(() => props.children);
8
- const branches = createMemo(() => createBranches(routeDefs(), props.base || ""));
5
+ export const createRouterComponent = (router) => function IntegratedRouter(props) {
6
+ const { base, singleFlight, transformUrl, root, rootPreload, routeChildren } = untrack(() => ({
7
+ base: props.base,
8
+ singleFlight: props.singleFlight,
9
+ transformUrl: props.transformUrl,
10
+ root: props.root,
11
+ rootPreload: props.rootPreload,
12
+ routeChildren: props.children
13
+ }));
14
+ const routeDefs = children(() => routeChildren);
15
+ const branches = createMemo(() => createBranches(routeDefs(), base || ""));
9
16
  let context;
10
17
  const routerState = createRouterContext(router, branches, () => context, {
11
18
  base,
12
- singleFlight: props.singleFlight,
13
- transformUrl: props.transformUrl,
19
+ singleFlight,
20
+ transformUrl,
14
21
  });
15
22
  router.create && router.create(routerState);
16
23
  return (<RouterContextObj value={routerState}>
17
- <Root routerState={routerState} root={props.root} preload={props.rootPreload}>
24
+ <Root routerState={routerState} root={root} preload={rootPreload}>
18
25
  {(context = getOwner()) && null}
19
26
  <Routes routerState={routerState} branches={branches()}/>
20
27
  </Root>
@@ -90,8 +97,9 @@ function Routes(props) {
90
97
  root = next[0];
91
98
  prevMatches = nextMatches;
92
99
  return next;
93
- }, undefined);
94
- return createOutlet(() => routeStates() && root)();
100
+ });
101
+ const outlet = createOutlet(() => routeStates() && root);
102
+ return <>{outlet()}</>;
95
103
  }
96
104
  const createOutlet = (child) => {
97
105
  return () => {
@@ -1,19 +1,18 @@
1
1
  import { createSignal, onCleanup, sharedConfig } from "solid-js";
2
2
  import { createRouterComponent } from "./components.jsx";
3
- function intercept([value, setValue], get, set) {
4
- return [get ? () => get(value()) : value, set ? (v) => setValue(set(v)) : setValue];
5
- }
6
3
  export function createRouter(config) {
7
4
  let ignore = false;
8
5
  const wrap = (value) => (typeof value === "string" ? { value } : value);
9
- const signal = intercept(createSignal(wrap(config.get()), {
10
- equals: (a, b) => a.value === b.value && a.state === b.state
11
- }), undefined, next => {
12
- !ignore && config.set(next);
13
- if (sharedConfig.registry && !sharedConfig.done)
14
- sharedConfig.done = true;
15
- return next;
6
+ const [read, write] = createSignal(wrap(config.get()), {
7
+ equals: (a, b) => a.value === b.value && a.state === b.state,
8
+ ownedWrite: true
16
9
  });
10
+ const signal = [read, (next) => {
11
+ !ignore && config.set(next);
12
+ if (sharedConfig.registry && !sharedConfig.done)
13
+ sharedConfig.done = true;
14
+ write(next);
15
+ }];
17
16
  config.init &&
18
17
  onCleanup(config.init((value = config.get()) => {
19
18
  ignore = true;
package/dist/routing.d.ts CHANGED
@@ -100,7 +100,7 @@ export declare const useCurrentMatches: () => () => RouteMatch[];
100
100
  * const params = useParams();
101
101
  *
102
102
  * // fetch user based on the id path parameter
103
- * const [user] = createResource(() => params.id, fetchUser);
103
+ * const getUser = query(() => fetchUser(params.id), "user");
104
104
  * ```
105
105
  */
106
106
  export declare const useParams: <T extends Params>() => T;
package/dist/routing.js CHANGED
@@ -133,7 +133,7 @@ export const useCurrentMatches = () => useRouter().matches;
133
133
  * const params = useParams();
134
134
  *
135
135
  * // fetch user based on the id path parameter
136
- * const [user] = createResource(() => params.id, fetchUser);
136
+ * const getUser = query(() => fetchUser(params.id), "user");
137
137
  * ```
138
138
  */
139
139
  export const useParams = () => useRouter().params;
@@ -301,7 +301,7 @@ export function getRouteMatches(branches, location) {
301
301
  }
302
302
  function createLocation(path, state, queryWrapper) {
303
303
  const origin = new URL(mockBase);
304
- const url = createMemo(prev => {
304
+ const url = createMemo((prev = origin) => {
305
305
  const path_ = path();
306
306
  try {
307
307
  return new URL(path_, origin);
@@ -310,11 +310,11 @@ function createLocation(path, state, queryWrapper) {
310
310
  console.error(`Invalid path ${path_}`);
311
311
  return prev;
312
312
  }
313
- }, origin, {
313
+ }, {
314
314
  equals: (a, b) => a.href === b.href
315
315
  });
316
316
  const pathname = createMemo(() => url().pathname);
317
- const search = createMemo(() => url().search, true);
317
+ const search = createMemo(() => url().search);
318
318
  const hash = createMemo(() => url().hash);
319
319
  const key = () => "";
320
320
  const queryFn = createMemo(() => extractSearchParams(url()));
@@ -354,37 +354,27 @@ export function createRouterContext(integration, branches, getContext, options =
354
354
  const renderPath = utils.renderPath || (p => p);
355
355
  const beforeLeave = utils.beforeLeave || createBeforeLeave();
356
356
  const basePath = resolvePath("", options.base || "");
357
+ const initialSource = untrack(source);
357
358
  if (basePath === undefined) {
358
359
  throw new Error(`${basePath} is not a valid base path`);
359
360
  }
360
- else if (basePath && !source().value) {
361
+ else if (basePath && !initialSource.value) {
361
362
  setSource({ value: basePath, replace: true, scroll: false });
362
363
  }
363
- const [isRouting, setIsRouting] = createSignal(false, { pureWrite: true });
364
+ const [isRouting, setIsRouting] = createSignal(false, { ownedWrite: true });
364
365
  // Navigate override written from event handlers.
365
366
  const [navigateTarget, setNavigateTarget] = createSignal(undefined, {
366
- pureWrite: true
367
+ ownedWrite: true
367
368
  });
368
369
  // Keep track of last target, so that last call to navigate wins
369
370
  let lastTransitionTarget;
370
371
  // source() remains canonical for native history changes; navigateTarget()
371
372
  // 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
- });
384
- const location = createLocation(reference, state, utils.queryWrapper);
373
+ const effective = createMemo(() => navigateTarget() ?? source());
374
+ const location = createLocation(() => effective().value, () => effective().state, utils.queryWrapper);
385
375
  const referrers = [];
386
376
  const submissions = createSignal(isServer ? initFromFlash() : [], {
387
- pureWrite: true
377
+ ownedWrite: true
388
378
  });
389
379
  const matches = createMemo(() => {
390
380
  if (typeof options.transformUrl === "function") {
@@ -456,15 +446,15 @@ export function createRouterContext(integration, branches, getContext, options =
456
446
  else if (referrers.length >= MAX_REDIRECTS) {
457
447
  throw new Error("Too many redirects");
458
448
  }
459
- const current = reference();
460
- if (resolvedTo !== current || nextState !== state()) {
449
+ const current = effective();
450
+ if (resolvedTo !== current.value || nextState !== current.state) {
461
451
  if (isServer) {
462
452
  const e = getRequestEvent();
463
453
  e && (e.response = { status: 302, headers: new Headers({ Location: resolvedTo }) });
464
454
  setSource({ value: resolvedTo, replace, scroll, state: nextState });
465
455
  }
466
456
  else if (beforeLeave.confirm(resolvedTo, options)) {
467
- referrers.push({ value: current, replace, scroll, state: state() });
457
+ referrers.push({ value: current.value, replace, scroll, state: current.state });
468
458
  const newTarget = {
469
459
  value: resolvedTo,
470
460
  state: nextState
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "Ryan Turnquist"
7
7
  ],
8
8
  "license": "MIT",
9
- "version": "0.17.0-next.0",
9
+ "version": "0.17.0-next.2",
10
10
  "homepage": "https://github.com/solidjs/solid-router#readme",
11
11
  "repository": {
12
12
  "type": "git",
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "sideEffects": false,
31
31
  "devDependencies": {
32
- "@solidjs/web": "2.0.0-beta.3",
32
+ "@solidjs/web": "2.0.0-beta.7",
33
33
  "@babel/core": "^7.26.0",
34
34
  "@babel/preset-typescript": "^7.26.0",
35
35
  "@changesets/cli": "^2.27.10",
@@ -38,19 +38,19 @@
38
38
  "@rollup/plugin-terser": "0.4.4",
39
39
  "@types/jest": "^29.5.14",
40
40
  "@types/node": "^22.10.0",
41
- "babel-preset-solid": "2.0.0-beta.3",
41
+ "babel-preset-solid": "2.0.0-beta.7",
42
42
  "jsdom": "^25.0.1",
43
43
  "prettier": "^3.4.1",
44
44
  "rollup": "^4.27.4",
45
- "solid-js": "2.0.0-beta.3",
45
+ "solid-js": "2.0.0-beta.7",
46
46
  "typescript": "^5.7.2",
47
47
  "vite": "^6.0.0",
48
- "vite-plugin-solid": "3.0.0-next.2",
48
+ "vite-plugin-solid": "3.0.0-next.4",
49
49
  "vitest": "^2.1.6"
50
50
  },
51
51
  "peerDependencies": {
52
- "@solidjs/web": "^2.0.0-beta.3",
53
- "solid-js": "^2.0.0-beta.3"
52
+ "@solidjs/web": ">=2.0.0-beta.7 <2.0.0-experimental.0",
53
+ "solid-js": ">=2.0.0-beta.7 <2.0.0-experimental.0"
54
54
  },
55
55
  "scripts": {
56
56
  "build": "rm -rf dist && tsc && rollup -c",