@solidjs/router 0.12.5 → 0.13.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 CHANGED
@@ -494,6 +494,14 @@ const user = createAsync((currentValue) => getUser(params.id))
494
494
 
495
495
  Using `cache` in `createResource` directly won't work properly as the fetcher is not reactive and it won't invalidate properly.
496
496
 
497
+ ### `createAsyncStore`
498
+
499
+ Similar to `createAsync` except it uses a deeply reactive store. Perfect for applying fine-grained changes to large model data that updates.
500
+
501
+ ```jsx
502
+ const todos = createAsyncStore(() => getTodos());
503
+ ```
504
+
497
505
  ### `action`
498
506
 
499
507
  Actions are data mutations that can trigger invalidations and further routing. A list of prebuilt response helpers can be found below.
@@ -26,21 +26,28 @@ export function useSubmission(fn, filter) {
26
26
  });
27
27
  }
28
28
  export function useAction(action) {
29
- const router = useRouter();
30
- return (...args) => action.apply(router, args);
29
+ const r = useRouter();
30
+ return (...args) => action.apply({ r }, args);
31
31
  }
32
32
  export function action(fn, name) {
33
33
  function mutate(...variables) {
34
- const router = this;
34
+ const router = this.r;
35
+ const form = this.f;
35
36
  const p = (router.singleFlight && fn.withOptions
36
37
  ? fn.withOptions({ headers: { "X-Single-Flight": "true" } })
37
38
  : fn)(...variables);
38
39
  const [result, setResult] = createSignal();
39
40
  let submission;
40
- async function handler(res) {
41
- const data = await handleResponse(res, router.navigatorFactory());
42
- data ? setResult({ data }) : submission.clear();
43
- return data;
41
+ function handler(error) {
42
+ return async (res) => {
43
+ const result = await handleResponse(res, error, router.navigatorFactory());
44
+ if (!result)
45
+ return submission.clear();
46
+ setResult(result);
47
+ if (result.error && !form)
48
+ throw result.error;
49
+ return result.data;
50
+ };
44
51
  }
45
52
  router.submissions[1](s => [
46
53
  ...s,
@@ -50,6 +57,9 @@ export function action(fn, name) {
50
57
  get result() {
51
58
  return result()?.data;
52
59
  },
60
+ get error() {
61
+ return result()?.error;
62
+ },
53
63
  get pending() {
54
64
  return !result();
55
65
  },
@@ -59,11 +69,11 @@ export function action(fn, name) {
59
69
  retry() {
60
70
  setResult(undefined);
61
71
  const p = fn(...variables);
62
- return p.then(handler, handler);
72
+ return p.then(handler(), handler(true));
63
73
  }
64
74
  })
65
75
  ]);
66
- return p.then(handler, handler);
76
+ return p.then(handler(), handler(true));
67
77
  }
68
78
  const url = fn.url ||
69
79
  (name && `https://action/${name}`) ||
@@ -92,7 +102,7 @@ function toAction(fn, url) {
92
102
  return fn;
93
103
  }
94
104
  const hashString = (s) => s.split("").reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0);
95
- async function handleResponse(response, navigate) {
105
+ async function handleResponse(response, error, navigate) {
96
106
  let data;
97
107
  let keys;
98
108
  let invalidateKeys;
@@ -123,11 +133,13 @@ async function handleResponse(response, navigate) {
123
133
  }
124
134
  }
125
135
  }
136
+ else if (error)
137
+ return { error: response };
126
138
  else
127
139
  data = response;
128
140
  // invalidate
129
141
  cacheKeyOp(invalidateKeys, entry => (entry[0] = 0));
130
142
  // trigger revalidation
131
143
  await revalidate(keys, false);
132
- return data;
144
+ return data != null ? { data } : undefined;
133
145
  }
@@ -103,7 +103,7 @@ export function setupNativeEvents(preload = true, explicitLinks = false, actionB
103
103
  const data = new FormData(evt.target);
104
104
  if (evt.submitter && evt.submitter.name)
105
105
  data.append(evt.submitter.name, evt.submitter.value);
106
- handler.call(router, data);
106
+ handler.call({ r: router, f: evt.target }, data);
107
107
  }
108
108
  }
109
109
  // ensure delegated event run first
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isServer, getRequestEvent, createComponent as createComponent$1, memo, delegateEvents, spread, mergeProps as mergeProps$1, template } from 'solid-js/web';
2
- import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal, createRenderEffect, on, startTransition, resetErrorBoundaries, createComponent, children, mergeProps, createRoot, Show, getListener, sharedConfig, $TRACK, splitProps, createResource } from 'solid-js';
2
+ import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal, createRenderEffect, on, startTransition, resetErrorBoundaries, createComponent, children, mergeProps, Show, createRoot, getListener, sharedConfig, $TRACK, splitProps, createResource } from 'solid-js';
3
3
  import { createStore, reconcile, unwrap } from 'solid-js/store';
4
4
 
5
5
  function createBeforeLeave() {
@@ -256,7 +256,7 @@ const useMatch = (path, matchFilters) => {
256
256
  }
257
257
  });
258
258
  };
259
- const useParams = () => useRoute().params;
259
+ const useParams = () => useRouter().params;
260
260
  const useSearchParams = () => {
261
261
  const location = useLocation();
262
262
  const navigate = useNavigate();
@@ -406,7 +406,7 @@ let intent;
406
406
  function getIntent() {
407
407
  return intent;
408
408
  }
409
- function createRouterContext(integration, getContext, getBranches, options = {}) {
409
+ function createRouterContext(integration, branches, getContext, options = {}) {
410
410
  const {
411
411
  signal: [source, setSource],
412
412
  utils = {}
@@ -438,9 +438,17 @@ function createRouterContext(integration, getContext, getBranches, options = {})
438
438
  const location = createLocation(reference, state);
439
439
  const referrers = [];
440
440
  const submissions = createSignal(isServer ? initFromFlash() : []);
441
+ const matches = createMemo(() => getRouteMatches(branches(), location.pathname));
442
+ const params = createMemoObject(() => {
443
+ const m = matches();
444
+ const params = {};
445
+ for (let i = 0; i < m.length; i++) {
446
+ Object.assign(params, m[i].params);
447
+ }
448
+ return params;
449
+ });
441
450
  const baseRoute = {
442
451
  pattern: basePath,
443
- params: {},
444
452
  path: () => basePath,
445
453
  outlet: () => null,
446
454
  resolvePath(to) {
@@ -470,10 +478,12 @@ function createRouterContext(integration, getContext, getBranches, options = {})
470
478
  return {
471
479
  base: baseRoute,
472
480
  location,
481
+ params,
473
482
  isRouting,
474
483
  renderPath,
475
484
  parsePath,
476
485
  navigatorFactory,
486
+ matches,
477
487
  beforeLeave,
478
488
  preloadRoute,
479
489
  singleFlight: options.singleFlight === undefined ? true : options.singleFlight,
@@ -568,7 +578,7 @@ function createRouterContext(integration, getContext, getBranches, options = {})
568
578
  }
569
579
  }
570
580
  function preloadRoute(url, preloadData) {
571
- const matches = getRouteMatches(getBranches(), url.pathname);
581
+ const matches = getRouteMatches(branches(), url.pathname);
572
582
  const prevIntent = intent;
573
583
  intent = "preload";
574
584
  for (let match in matches) {
@@ -600,10 +610,11 @@ function createRouterContext(integration, getContext, getBranches, options = {})
600
610
  return e && e.router && e.router.submission ? [e.router.submission] : [];
601
611
  }
602
612
  }
603
- function createRouteContext(router, parent, outlet, match, params) {
613
+ function createRouteContext(router, parent, outlet, match) {
604
614
  const {
605
615
  base,
606
- location
616
+ location,
617
+ params
607
618
  } = router;
608
619
  const {
609
620
  pattern,
@@ -621,7 +632,6 @@ function createRouteContext(router, parent, outlet, match, params) {
621
632
  parent,
622
633
  pattern,
623
634
  path,
624
- params,
625
635
  outlet: () => component ? createComponent(component, {
626
636
  params,
627
637
  location,
@@ -642,13 +652,9 @@ const createRouterComponent = router => props => {
642
652
  base
643
653
  } = props;
644
654
  const routeDefs = children(() => props.children);
645
- const branches = createMemo(() => createBranches(props.root ? {
646
- component: props.root,
647
- load: props.rootLoad,
648
- children: routeDefs()
649
- } : routeDefs(), props.base || ""));
655
+ const branches = createMemo(() => createBranches(routeDefs(), props.base || ""));
650
656
  let context;
651
- const routerState = createRouterContext(router, () => context, branches, {
657
+ const routerState = createRouterContext(router, branches, () => context, {
652
658
  base,
653
659
  singleFlight: props.singleFlight
654
660
  });
@@ -656,24 +662,62 @@ const createRouterComponent = router => props => {
656
662
  return createComponent$1(RouterContextObj.Provider, {
657
663
  value: routerState,
658
664
  get children() {
659
- return [memo(() => (context = getOwner()) && null), createComponent$1(Routes, {
665
+ return createComponent$1(Root, {
660
666
  routerState: routerState,
661
- get branches() {
662
- return branches();
667
+ get root() {
668
+ return props.root;
669
+ },
670
+ get load() {
671
+ return props.rootLoad;
672
+ },
673
+ get children() {
674
+ return [memo(() => (context = getOwner()) && null), createComponent$1(Routes, {
675
+ routerState: routerState,
676
+ get branches() {
677
+ return branches();
678
+ }
679
+ })];
663
680
  }
664
- })];
681
+ });
665
682
  }
666
683
  });
667
684
  };
685
+ function Root(props) {
686
+ const location = props.routerState.location;
687
+ const params = props.routerState.params;
688
+ const data = createMemo(() => props.load && untrack(() => props.load({
689
+ params,
690
+ location,
691
+ intent: "preload"
692
+ })));
693
+ return createComponent$1(Show, {
694
+ get when() {
695
+ return props.root;
696
+ },
697
+ keyed: true,
698
+ get fallback() {
699
+ return props.children;
700
+ },
701
+ children: Root => createComponent$1(Root, {
702
+ params: params,
703
+ location: location,
704
+ get data() {
705
+ return data();
706
+ },
707
+ get children() {
708
+ return props.children;
709
+ }
710
+ })
711
+ });
712
+ }
668
713
  function Routes(props) {
669
- const matches = createMemo(() => getRouteMatches(props.branches, props.routerState.location.pathname));
670
714
  if (isServer) {
671
715
  const e = getRequestEvent();
672
716
  if (e && e.router && e.router.dataOnly) {
673
- dataOnly(e, props.branches);
717
+ dataOnly(e, props.routerState, props.branches);
674
718
  return;
675
719
  }
676
- e && ((e.router || (e.router = {})).matches || (e.router.matches = matches().map(({
720
+ e && ((e.router || (e.router = {})).matches || (e.router.matches = props.routerState.matches().map(({
677
721
  route,
678
722
  path,
679
723
  params
@@ -685,17 +729,9 @@ function Routes(props) {
685
729
  info: route.info
686
730
  }))));
687
731
  }
688
- const params = createMemoObject(() => {
689
- const m = matches();
690
- const params = {};
691
- for (let i = 0; i < m.length; i++) {
692
- Object.assign(params, m[i].params);
693
- }
694
- return params;
695
- });
696
732
  const disposers = [];
697
733
  let root;
698
- const routeStates = createMemo(on(matches, (nextMatches, prevMatches, prev) => {
734
+ const routeStates = createMemo(on(props.routerState.matches, (nextMatches, prevMatches, prev) => {
699
735
  let equal = prevMatches && nextMatches.length === prevMatches.length;
700
736
  const next = [];
701
737
  for (let i = 0, len = nextMatches.length; i < len; i++) {
@@ -710,7 +746,7 @@ function Routes(props) {
710
746
  }
711
747
  createRoot(dispose => {
712
748
  disposers[i] = dispose;
713
- next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => matches()[i], params);
749
+ next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => props.routerState.matches()[i]);
714
750
  });
715
751
  }
716
752
  }
@@ -721,18 +757,7 @@ function Routes(props) {
721
757
  root = next[0];
722
758
  return next;
723
759
  }));
724
- return createComponent$1(Show, {
725
- get when() {
726
- return routeStates() && root;
727
- },
728
- keyed: true,
729
- children: route => createComponent$1(RouteContextObj.Provider, {
730
- value: route,
731
- get children() {
732
- return route.outlet();
733
- }
734
- })
735
- });
760
+ return createOutlet(() => routeStates() && root)();
736
761
  }
737
762
  const createOutlet = child => {
738
763
  return () => createComponent$1(Show, {
@@ -758,7 +783,7 @@ const Route = props => {
758
783
  };
759
784
 
760
785
  // for data only mode with single flight mutations
761
- function dataOnly(event, branches) {
786
+ function dataOnly(event, routerState, branches) {
762
787
  const url = new URL(event.request.url);
763
788
  const prevMatches = getRouteMatches(branches, new URL(event.router.previousUrl || event.request.url).pathname);
764
789
  const matches = getRouteMatches(branches, url.pathname);
@@ -770,14 +795,7 @@ function dataOnly(event, branches) {
770
795
  } = matches[match];
771
796
  route.load && route.load({
772
797
  params,
773
- location: {
774
- pathname: url.pathname,
775
- search: url.search,
776
- hash: url.hash,
777
- query: extractSearchParams(url),
778
- state: null,
779
- key: ""
780
- },
798
+ location: routerState.location,
781
799
  intent: "preload"
782
800
  });
783
801
  }
@@ -1040,12 +1058,15 @@ function useSubmission(fn, filter) {
1040
1058
  });
1041
1059
  }
1042
1060
  function useAction(action) {
1043
- const router = useRouter();
1044
- return (...args) => action.apply(router, args);
1061
+ const r = useRouter();
1062
+ return (...args) => action.apply({
1063
+ r
1064
+ }, args);
1045
1065
  }
1046
1066
  function action(fn, name) {
1047
1067
  function mutate(...variables) {
1048
- const router = this;
1068
+ const router = this.r;
1069
+ const form = this.f;
1049
1070
  const p = (router.singleFlight && fn.withOptions ? fn.withOptions({
1050
1071
  headers: {
1051
1072
  "X-Single-Flight": "true"
@@ -1053,12 +1074,14 @@ function action(fn, name) {
1053
1074
  }) : fn)(...variables);
1054
1075
  const [result, setResult] = createSignal();
1055
1076
  let submission;
1056
- async function handler(res) {
1057
- const data = await handleResponse(res, router.navigatorFactory());
1058
- data ? setResult({
1059
- data
1060
- }) : submission.clear();
1061
- return data;
1077
+ function handler(error) {
1078
+ return async res => {
1079
+ const result = await handleResponse(res, error, router.navigatorFactory());
1080
+ if (!result) return submission.clear();
1081
+ setResult(result);
1082
+ if (result.error && !form) throw result.error;
1083
+ return result.data;
1084
+ };
1062
1085
  }
1063
1086
  router.submissions[1](s => [...s, submission = {
1064
1087
  input: variables,
@@ -1066,6 +1089,9 @@ function action(fn, name) {
1066
1089
  get result() {
1067
1090
  return result()?.data;
1068
1091
  },
1092
+ get error() {
1093
+ return result()?.error;
1094
+ },
1069
1095
  get pending() {
1070
1096
  return !result();
1071
1097
  },
@@ -1075,10 +1101,10 @@ function action(fn, name) {
1075
1101
  retry() {
1076
1102
  setResult(undefined);
1077
1103
  const p = fn(...variables);
1078
- return p.then(handler, handler);
1104
+ return p.then(handler(), handler(true));
1079
1105
  }
1080
1106
  }]);
1081
- return p.then(handler, handler);
1107
+ return p.then(handler(), handler(true));
1082
1108
  }
1083
1109
  const url = fn.url || name && `https://action/${name}` || (!isServer ? `https://action/${hashString(fn.toString())}` : "");
1084
1110
  return toAction(mutate, url);
@@ -1104,7 +1130,7 @@ function toAction(fn, url) {
1104
1130
  return fn;
1105
1131
  }
1106
1132
  const hashString = s => s.split("").reduce((a, b) => (a << 5) - a + b.charCodeAt(0) | 0, 0);
1107
- async function handleResponse(response, navigate) {
1133
+ async function handleResponse(response, error, navigate) {
1108
1134
  let data;
1109
1135
  let keys;
1110
1136
  let invalidateKeys;
@@ -1131,12 +1157,16 @@ async function handleResponse(response, navigate) {
1131
1157
  navigate(locationUrl);
1132
1158
  }
1133
1159
  }
1134
- } else data = response;
1160
+ } else if (error) return {
1161
+ error: response
1162
+ };else data = response;
1135
1163
  // invalidate
1136
1164
  cacheKeyOp(invalidateKeys, entry => entry[0] = 0);
1137
1165
  // trigger revalidation
1138
1166
  await revalidate(keys, false);
1139
- return data;
1167
+ return data != null ? {
1168
+ data
1169
+ } : undefined;
1140
1170
  }
1141
1171
 
1142
1172
  function setupNativeEvents(preload = true, explicitLinks = false, actionBase = "/_server") {
@@ -1215,7 +1245,10 @@ function setupNativeEvents(preload = true, explicitLinks = false, actionBase = "
1215
1245
  evt.preventDefault();
1216
1246
  const data = new FormData(evt.target);
1217
1247
  if (evt.submitter && evt.submitter.name) data.append(evt.submitter.name, evt.submitter.value);
1218
- handler.call(router, data);
1248
+ handler.call({
1249
+ r: router,
1250
+ f: evt.target
1251
+ }, data);
1219
1252
  }
1220
1253
  }
1221
1254
 
@@ -1,31 +1,44 @@
1
1
  /*@refresh skip*/
2
2
  import { getRequestEvent, isServer } from "solid-js/web";
3
- import { children, createMemo, createRoot, getOwner, mergeProps, on, Show } from "solid-js";
3
+ import { children, createMemo, createRoot, getOwner, mergeProps, on, Show, untrack } from "solid-js";
4
4
  import { createBranches, createRouteContext, createRouterContext, getRouteMatches, RouteContextObj, RouterContextObj } from "../routing.js";
5
- import { createMemoObject, extractSearchParams } from "../utils.js";
6
5
  export const createRouterComponent = (router) => (props) => {
7
6
  const { base } = props;
8
7
  const routeDefs = children(() => props.children);
9
- const branches = createMemo(() => createBranches(props.root ? { component: props.root, load: props.rootLoad, children: routeDefs() } : routeDefs(), props.base || ""));
8
+ const branches = createMemo(() => createBranches(routeDefs(), props.base || ""));
10
9
  let context;
11
- const routerState = createRouterContext(router, () => context, branches, { base, singleFlight: props.singleFlight });
10
+ const routerState = createRouterContext(router, branches, () => context, {
11
+ base,
12
+ singleFlight: props.singleFlight
13
+ });
12
14
  router.create && router.create(routerState);
13
15
  return (<RouterContextObj.Provider value={routerState}>
14
- {(context = getOwner()) && null}
15
- <Routes routerState={routerState} branches={branches()}/>
16
+ <Root routerState={routerState} root={props.root} load={props.rootLoad}>
17
+ {(context = getOwner()) && null}
18
+ <Routes routerState={routerState} branches={branches()}/>
19
+ </Root>
16
20
  </RouterContextObj.Provider>);
17
21
  };
22
+ function Root(props) {
23
+ const location = props.routerState.location;
24
+ const params = props.routerState.params;
25
+ const data = createMemo(() => props.load && untrack(() => props.load({ params, location, intent: "preload" })));
26
+ return (<Show when={props.root} keyed fallback={props.children}>
27
+ {Root => (<Root params={params} location={location} data={data()}>
28
+ {props.children}
29
+ </Root>)}
30
+ </Show>);
31
+ }
18
32
  function Routes(props) {
19
- const matches = createMemo(() => getRouteMatches(props.branches, props.routerState.location.pathname));
20
33
  if (isServer) {
21
34
  const e = getRequestEvent();
22
35
  if (e && e.router && e.router.dataOnly) {
23
- dataOnly(e, props.branches);
36
+ dataOnly(e, props.routerState, props.branches);
24
37
  return;
25
38
  }
26
39
  e &&
27
40
  ((e.router || (e.router = {})).matches ||
28
- (e.router.matches = matches().map(({ route, path, params }) => ({
41
+ (e.router.matches = props.routerState.matches().map(({ route, path, params }) => ({
29
42
  path: route.originalPath,
30
43
  pattern: route.pattern,
31
44
  match: path,
@@ -33,17 +46,9 @@ function Routes(props) {
33
46
  info: route.info
34
47
  }))));
35
48
  }
36
- const params = createMemoObject(() => {
37
- const m = matches();
38
- const params = {};
39
- for (let i = 0; i < m.length; i++) {
40
- Object.assign(params, m[i].params);
41
- }
42
- return params;
43
- });
44
49
  const disposers = [];
45
50
  let root;
46
- const routeStates = createMemo(on(matches, (nextMatches, prevMatches, prev) => {
51
+ const routeStates = createMemo(on(props.routerState.matches, (nextMatches, prevMatches, prev) => {
47
52
  let equal = prevMatches && nextMatches.length === prevMatches.length;
48
53
  const next = [];
49
54
  for (let i = 0, len = nextMatches.length; i < len; i++) {
@@ -59,7 +64,7 @@ function Routes(props) {
59
64
  }
60
65
  createRoot(dispose => {
61
66
  disposers[i] = dispose;
62
- next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => matches()[i], params);
67
+ next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => props.routerState.matches()[i]);
63
68
  });
64
69
  }
65
70
  }
@@ -70,9 +75,7 @@ function Routes(props) {
70
75
  root = next[0];
71
76
  return next;
72
77
  }));
73
- return (<Show when={routeStates() && root} keyed>
74
- {route => <RouteContextObj.Provider value={route}>{route.outlet()}</RouteContextObj.Provider>}
75
- </Show>);
78
+ return createOutlet(() => routeStates() && root)();
76
79
  }
77
80
  const createOutlet = (child) => {
78
81
  return () => (<Show when={child()} keyed>
@@ -88,7 +91,7 @@ export const Route = (props) => {
88
91
  });
89
92
  };
90
93
  // for data only mode with single flight mutations
91
- function dataOnly(event, branches) {
94
+ function dataOnly(event, routerState, branches) {
92
95
  const url = new URL(event.request.url);
93
96
  const prevMatches = getRouteMatches(branches, new URL(event.router.previousUrl || event.request.url).pathname);
94
97
  const matches = getRouteMatches(branches, url.pathname);
@@ -99,14 +102,7 @@ function dataOnly(event, branches) {
99
102
  route.load &&
100
103
  route.load({
101
104
  params,
102
- location: {
103
- pathname: url.pathname,
104
- search: url.search,
105
- hash: url.hash,
106
- query: extractSearchParams(url),
107
- state: null,
108
- key: ""
109
- },
105
+ location: routerState.location,
110
106
  intent: "preload"
111
107
  });
112
108
  }
package/dist/routing.d.ts CHANGED
@@ -19,8 +19,8 @@ export declare function createBranches(routeDef: RouteDefinition | RouteDefiniti
19
19
  export declare function getRouteMatches(branches: Branch[], location: string): RouteMatch[];
20
20
  export declare function createLocation(path: Accessor<string>, state: Accessor<any>): Location;
21
21
  export declare function getIntent(): Intent | undefined;
22
- export declare function createRouterContext(integration: RouterIntegration, getContext?: () => any, getBranches?: () => Branch[], options?: {
22
+ export declare function createRouterContext(integration: RouterIntegration, branches: () => Branch[], getContext?: () => any, options?: {
23
23
  base?: string;
24
24
  singleFlight?: boolean;
25
25
  }): RouterContext;
26
- export declare function createRouteContext(router: RouterContext, parent: RouteContext, outlet: () => JSX.Element, match: () => RouteMatch, params: Params): RouteContext;
26
+ export declare function createRouteContext(router: RouterContext, parent: RouteContext, outlet: () => JSX.Element, match: () => RouteMatch): RouteContext;
package/dist/routing.js CHANGED
@@ -34,7 +34,7 @@ export const useMatch = (path, matchFilters) => {
34
34
  }
35
35
  });
36
36
  };
37
- export const useParams = () => useRoute().params;
37
+ export const useParams = () => useRouter().params;
38
38
  export const useSearchParams = () => {
39
39
  const location = useLocation();
40
40
  const navigate = useNavigate();
@@ -184,7 +184,7 @@ let intent;
184
184
  export function getIntent() {
185
185
  return intent;
186
186
  }
187
- export function createRouterContext(integration, getContext, getBranches, options = {}) {
187
+ export function createRouterContext(integration, branches, getContext, options = {}) {
188
188
  const { signal: [source, setSource], utils = {} } = integration;
189
189
  const parsePath = utils.parsePath || (p => p);
190
190
  const renderPath = utils.renderPath || (p => p);
@@ -211,9 +211,17 @@ export function createRouterContext(integration, getContext, getBranches, option
211
211
  const location = createLocation(reference, state);
212
212
  const referrers = [];
213
213
  const submissions = createSignal(isServer ? initFromFlash() : []);
214
+ const matches = createMemo(() => getRouteMatches(branches(), location.pathname));
215
+ const params = createMemoObject(() => {
216
+ const m = matches();
217
+ const params = {};
218
+ for (let i = 0; i < m.length; i++) {
219
+ Object.assign(params, m[i].params);
220
+ }
221
+ return params;
222
+ });
214
223
  const baseRoute = {
215
224
  pattern: basePath,
216
- params: {},
217
225
  path: () => basePath,
218
226
  outlet: () => null,
219
227
  resolvePath(to) {
@@ -240,10 +248,12 @@ export function createRouterContext(integration, getContext, getBranches, option
240
248
  return {
241
249
  base: baseRoute,
242
250
  location,
251
+ params,
243
252
  isRouting,
244
253
  renderPath,
245
254
  parsePath,
246
255
  navigatorFactory,
256
+ matches,
247
257
  beforeLeave,
248
258
  preloadRoute,
249
259
  singleFlight: options.singleFlight === undefined ? true : options.singleFlight,
@@ -324,7 +334,7 @@ export function createRouterContext(integration, getContext, getBranches, option
324
334
  }
325
335
  }
326
336
  function preloadRoute(url, preloadData) {
327
- const matches = getRouteMatches(getBranches(), url.pathname);
337
+ const matches = getRouteMatches(branches(), url.pathname);
328
338
  const prevIntent = intent;
329
339
  intent = "preload";
330
340
  for (let match in matches) {
@@ -352,11 +362,13 @@ export function createRouterContext(integration, getContext, getBranches, option
352
362
  }
353
363
  function initFromFlash() {
354
364
  const e = getRequestEvent();
355
- return e && e.router && e.router.submission ? [e.router.submission] : [];
365
+ return (e && e.router && e.router.submission
366
+ ? [e.router.submission]
367
+ : []);
356
368
  }
357
369
  }
358
- export function createRouteContext(router, parent, outlet, match, params) {
359
- const { base, location } = router;
370
+ export function createRouteContext(router, parent, outlet, match) {
371
+ const { base, location, params } = router;
360
372
  const { pattern, component, load } = match().route;
361
373
  const path = createMemo(() => match().path);
362
374
  component &&
@@ -367,7 +379,6 @@ export function createRouteContext(router, parent, outlet, match, params) {
367
379
  parent,
368
380
  pattern,
369
381
  path,
370
- params,
371
382
  outlet: () => component
372
383
  ? createComponent(component, {
373
384
  params,
package/dist/types.d.ts CHANGED
@@ -9,7 +9,11 @@ declare module "solid-js/web" {
9
9
  router?: {
10
10
  matches?: OutputMatch[];
11
11
  cache?: Map<string, CacheEntry>;
12
- submission?: Submission<any, any>;
12
+ submission?: {
13
+ input: any;
14
+ result: any;
15
+ url: string;
16
+ };
13
17
  dataOnly?: boolean | string[];
14
18
  data?: Record<string, any>;
15
19
  previousUrl?: string;
@@ -110,7 +114,6 @@ export interface RouteContext {
110
114
  parent?: RouteContext;
111
115
  child?: RouteContext;
112
116
  pattern: string;
113
- params: Params;
114
117
  path: () => string;
115
118
  outlet: () => JSX.Element;
116
119
  resolvePath(to: string): string | undefined;
@@ -124,8 +127,10 @@ export interface RouterUtils {
124
127
  export interface RouterContext {
125
128
  base: RouteContext;
126
129
  location: Location;
130
+ params: Params;
127
131
  navigatorFactory: NavigatorFactory;
128
132
  isRouting: () => boolean;
133
+ matches: () => RouteMatch[];
129
134
  renderPath(path: string): string;
130
135
  parsePath(str: string): string;
131
136
  beforeLeave: BeforeLeaveLifecycle;
@@ -153,6 +158,7 @@ export interface BeforeLeaveLifecycle {
153
158
  export type Submission<T, U> = {
154
159
  readonly input: T;
155
160
  readonly result?: U;
161
+ readonly error: any;
156
162
  readonly pending: boolean;
157
163
  readonly url: string;
158
164
  clear: () => void;
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "Ryan Turnquist"
7
7
  ],
8
8
  "license": "MIT",
9
- "version": "0.12.5",
9
+ "version": "0.13.1",
10
10
  "homepage": "https://github.com/solidjs/solid-router#readme",
11
11
  "repository": {
12
12
  "type": "git",