@solidjs/router 0.16.0 → 0.17.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -79
- package/dist/components.jsx +22 -16
- package/dist/data/action.d.ts +12 -10
- package/dist/data/action.js +98 -78
- package/dist/data/events.d.ts +8 -1
- package/dist/data/events.js +3 -3
- package/dist/data/index.d.ts +2 -3
- package/dist/data/index.js +2 -3
- package/dist/data/query.d.ts +1 -3
- package/dist/data/query.js +10 -16
- package/dist/index.d.ts +2 -2
- package/dist/index.js +212 -261
- package/dist/index.jsx +1 -1
- package/dist/lifecycle.js +1 -1
- package/dist/routers/HashRouter.js +1 -1
- package/dist/routers/MemoryRouter.js +1 -1
- package/dist/routers/Router.js +2 -2
- package/dist/routers/StaticRouter.js +1 -1
- package/dist/routers/components.d.ts +0 -4
- package/dist/routers/components.jsx +30 -19
- package/dist/routing.d.ts +4 -3
- package/dist/routing.js +71 -49
- package/dist/types.d.ts +3 -18
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +8 -0
- package/package.json +8 -6
- package/dist/data/createAsync.d.ts +0 -32
- package/dist/data/createAsync.js +0 -93
- package/dist/src/components.d.ts +0 -31
- package/dist/src/components.jsx +0 -39
- package/dist/src/data/action.d.ts +0 -17
- package/dist/src/data/action.js +0 -163
- package/dist/src/data/action.spec.d.ts +0 -1
- package/dist/src/data/action.spec.js +0 -297
- package/dist/src/data/createAsync.d.ts +0 -32
- package/dist/src/data/createAsync.js +0 -96
- package/dist/src/data/createAsync.spec.d.ts +0 -1
- package/dist/src/data/createAsync.spec.js +0 -196
- package/dist/src/data/events.d.ts +0 -9
- package/dist/src/data/events.js +0 -123
- package/dist/src/data/events.spec.d.ts +0 -1
- package/dist/src/data/events.spec.js +0 -567
- package/dist/src/data/index.d.ts +0 -4
- package/dist/src/data/index.js +0 -4
- package/dist/src/data/query.d.ts +0 -23
- package/dist/src/data/query.js +0 -232
- package/dist/src/data/query.spec.d.ts +0 -1
- package/dist/src/data/query.spec.js +0 -354
- package/dist/src/data/response.d.ts +0 -4
- package/dist/src/data/response.js +0 -42
- package/dist/src/data/response.spec.d.ts +0 -1
- package/dist/src/data/response.spec.js +0 -165
- package/dist/src/index.d.ts +0 -7
- package/dist/src/index.jsx +0 -6
- package/dist/src/lifecycle.d.ts +0 -5
- package/dist/src/lifecycle.js +0 -69
- package/dist/src/routers/HashRouter.d.ts +0 -9
- package/dist/src/routers/HashRouter.js +0 -41
- package/dist/src/routers/MemoryRouter.d.ts +0 -24
- package/dist/src/routers/MemoryRouter.js +0 -57
- package/dist/src/routers/Router.d.ts +0 -9
- package/dist/src/routers/Router.js +0 -45
- package/dist/src/routers/StaticRouter.d.ts +0 -6
- package/dist/src/routers/StaticRouter.js +0 -15
- package/dist/src/routers/components.d.ts +0 -27
- package/dist/src/routers/components.jsx +0 -118
- package/dist/src/routers/createRouter.d.ts +0 -10
- package/dist/src/routers/createRouter.js +0 -41
- package/dist/src/routers/index.d.ts +0 -11
- package/dist/src/routers/index.js +0 -6
- package/dist/src/routing.d.ts +0 -175
- package/dist/src/routing.js +0 -560
- package/dist/src/types.d.ts +0 -200
- package/dist/src/types.js +0 -1
- package/dist/src/utils.d.ts +0 -13
- package/dist/src/utils.js +0 -185
- package/dist/test/helpers.d.ts +0 -6
- package/dist/test/helpers.js +0 -50
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { isServer, getRequestEvent, createComponent as createComponent$1, memo, delegateEvents, spread, mergeProps
|
|
2
|
-
import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal,
|
|
3
|
-
import { createStore, reconcile, unwrap } from 'solid-js/store';
|
|
1
|
+
import { isServer, getRequestEvent, createComponent as createComponent$1, memo, delegateEvents, spread, mergeProps, template } from '@solidjs/web';
|
|
2
|
+
import { getOwner, runWithOwner, createMemo, createContext, onCleanup, useContext, untrack, createSignal, flush, createComponent, children, merge, createRoot, sharedConfig, getObserver, $TRACK, action as action$1, omit } from 'solid-js';
|
|
4
3
|
|
|
5
4
|
function createBeforeLeave() {
|
|
6
5
|
let listeners = new Set();
|
|
@@ -251,8 +250,15 @@ const MAX_REDIRECTS = 100;
|
|
|
251
250
|
/** Consider this API opaque and internal. It is likely to change in the future. */
|
|
252
251
|
const RouterContextObj = createContext();
|
|
253
252
|
const RouteContextObj = createContext();
|
|
253
|
+
function useOptionalContext(context) {
|
|
254
|
+
try {
|
|
255
|
+
return useContext(context);
|
|
256
|
+
} catch {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
254
260
|
const useRouter = () => invariant(useContext(RouterContextObj), "<A> and 'use' router primitives can be only used inside a Route.");
|
|
255
|
-
const useRoute = () =>
|
|
261
|
+
const useRoute = () => useOptionalContext(RouteContextObj) || useRouter().base;
|
|
256
262
|
const useResolvedPath = path => {
|
|
257
263
|
const route = useRoute();
|
|
258
264
|
return createMemo(() => route.resolvePath(path()));
|
|
@@ -299,8 +305,8 @@ const useNavigate = () => useRouter().navigatorFactory();
|
|
|
299
305
|
const useLocation = () => useRouter().location;
|
|
300
306
|
|
|
301
307
|
/**
|
|
302
|
-
* Retrieves signal that indicates whether the
|
|
303
|
-
* Useful for showing
|
|
308
|
+
* Retrieves a signal that indicates whether the router is currently processing a navigation.
|
|
309
|
+
* Useful for showing pending navigation state while the next route and its data settle.
|
|
304
310
|
*
|
|
305
311
|
* @example
|
|
306
312
|
* ```js
|
|
@@ -459,7 +465,6 @@ function createRoutes(routeDef, base = "") {
|
|
|
459
465
|
const {
|
|
460
466
|
component,
|
|
461
467
|
preload,
|
|
462
|
-
load,
|
|
463
468
|
children,
|
|
464
469
|
info
|
|
465
470
|
} = routeDef;
|
|
@@ -467,7 +472,7 @@ function createRoutes(routeDef, base = "") {
|
|
|
467
472
|
const shared = {
|
|
468
473
|
key: routeDef,
|
|
469
474
|
component,
|
|
470
|
-
preload
|
|
475
|
+
preload,
|
|
471
476
|
info
|
|
472
477
|
};
|
|
473
478
|
return asArray(routeDef.path).reduce((acc, originalPath) => {
|
|
@@ -561,7 +566,7 @@ function createLocation(path, state, queryWrapper) {
|
|
|
561
566
|
const search = createMemo(() => url().search, true);
|
|
562
567
|
const hash = createMemo(() => url().hash);
|
|
563
568
|
const key = () => "";
|
|
564
|
-
const queryFn =
|
|
569
|
+
const queryFn = createMemo(() => extractSearchParams(url()));
|
|
565
570
|
return {
|
|
566
571
|
get pathname() {
|
|
567
572
|
return pathname();
|
|
@@ -610,40 +615,35 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
610
615
|
scroll: false
|
|
611
616
|
});
|
|
612
617
|
}
|
|
613
|
-
const [isRouting, setIsRouting] = createSignal(false
|
|
618
|
+
const [isRouting, setIsRouting] = createSignal(false, {
|
|
619
|
+
pureWrite: true
|
|
620
|
+
});
|
|
614
621
|
|
|
615
|
-
//
|
|
616
|
-
|
|
622
|
+
// Navigate override written from event handlers.
|
|
623
|
+
const [navigateTarget, setNavigateTarget] = createSignal(undefined, {
|
|
624
|
+
pureWrite: true
|
|
625
|
+
});
|
|
617
626
|
|
|
618
|
-
//
|
|
619
|
-
|
|
620
|
-
if (newTarget.value === reference() && newTarget.state === state()) return;
|
|
621
|
-
if (lastTransitionTarget === undefined) setIsRouting(true);
|
|
622
|
-
intent = newIntent;
|
|
623
|
-
lastTransitionTarget = newTarget;
|
|
624
|
-
startTransition(() => {
|
|
625
|
-
if (lastTransitionTarget !== newTarget) return;
|
|
626
|
-
setReference(lastTransitionTarget.value);
|
|
627
|
-
setState(lastTransitionTarget.state);
|
|
628
|
-
resetErrorBoundaries();
|
|
629
|
-
if (!isServer) submissions[1](subs => subs.filter(s => s.pending));
|
|
630
|
-
}).finally(() => {
|
|
631
|
-
if (lastTransitionTarget !== newTarget) return;
|
|
627
|
+
// Keep track of last target, so that last call to navigate wins
|
|
628
|
+
let lastTransitionTarget;
|
|
632
629
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
630
|
+
// source() remains canonical for native history changes; navigateTarget()
|
|
631
|
+
// 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
|
+
});
|
|
644
642
|
const location = createLocation(reference, state, utils.queryWrapper);
|
|
645
643
|
const referrers = [];
|
|
646
|
-
const submissions = createSignal(isServer ? initFromFlash() : []
|
|
644
|
+
const submissions = createSignal(isServer ? initFromFlash() : [], {
|
|
645
|
+
pureWrite: true
|
|
646
|
+
});
|
|
647
647
|
const matches = createMemo(() => {
|
|
648
648
|
if (typeof options.transformUrl === "function") {
|
|
649
649
|
return getRouteMatches(branches(), options.transformUrl(location.pathname));
|
|
@@ -667,11 +667,6 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
667
667
|
return resolvePath(basePath, to);
|
|
668
668
|
}
|
|
669
669
|
};
|
|
670
|
-
|
|
671
|
-
// Create a native transition, when source updates
|
|
672
|
-
createRenderEffect(on(source, source => transition("native", source), {
|
|
673
|
-
defer: true
|
|
674
|
-
}));
|
|
675
670
|
return {
|
|
676
671
|
base: baseRoute,
|
|
677
672
|
location,
|
|
@@ -738,17 +733,36 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
738
733
|
scroll,
|
|
739
734
|
state: state()
|
|
740
735
|
});
|
|
741
|
-
|
|
736
|
+
const newTarget = {
|
|
742
737
|
value: resolvedTo,
|
|
743
738
|
state: nextState
|
|
744
|
-
}
|
|
739
|
+
};
|
|
740
|
+
if (lastTransitionTarget === undefined) {
|
|
741
|
+
setIsRouting(true);
|
|
742
|
+
flush();
|
|
743
|
+
}
|
|
744
|
+
intent = "navigate";
|
|
745
|
+
lastTransitionTarget = newTarget;
|
|
746
|
+
if (lastTransitionTarget === newTarget) {
|
|
747
|
+
setNavigateTarget({
|
|
748
|
+
...lastTransitionTarget
|
|
749
|
+
});
|
|
750
|
+
queueMicrotask(() => {
|
|
751
|
+
if (lastTransitionTarget !== newTarget) return;
|
|
752
|
+
intent = undefined;
|
|
753
|
+
navigateEnd(lastTransitionTarget);
|
|
754
|
+
setNavigateTarget(undefined);
|
|
755
|
+
setIsRouting(false);
|
|
756
|
+
lastTransitionTarget = undefined;
|
|
757
|
+
});
|
|
758
|
+
}
|
|
745
759
|
}
|
|
746
760
|
}
|
|
747
761
|
});
|
|
748
762
|
}
|
|
749
763
|
function navigatorFactory(route) {
|
|
750
764
|
// Workaround for vite issue (https://github.com/vitejs/vite/issues/3803)
|
|
751
|
-
route = route ||
|
|
765
|
+
route = route || useOptionalContext(RouteContextObj) || baseRoute;
|
|
752
766
|
return (to, options) => navigateFromRoute(route, to, options);
|
|
753
767
|
}
|
|
754
768
|
function navigateEnd(next) {
|
|
@@ -794,7 +808,12 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
794
808
|
}
|
|
795
809
|
function initFromFlash() {
|
|
796
810
|
const e = getRequestEvent();
|
|
797
|
-
|
|
811
|
+
if (!(e && e.router && e.router.submission)) return [];
|
|
812
|
+
return [{
|
|
813
|
+
...e.router.submission,
|
|
814
|
+
clear() {},
|
|
815
|
+
retry() {}
|
|
816
|
+
}];
|
|
798
817
|
}
|
|
799
818
|
}
|
|
800
819
|
function createRouteContext(router, parent, outlet, match) {
|
|
@@ -849,7 +868,7 @@ const createRouterComponent = router => props => {
|
|
|
849
868
|
transformUrl: props.transformUrl
|
|
850
869
|
});
|
|
851
870
|
router.create && router.create(routerState);
|
|
852
|
-
return createComponent$1(RouterContextObj
|
|
871
|
+
return createComponent$1(RouterContextObj, {
|
|
853
872
|
value: routerState,
|
|
854
873
|
get children() {
|
|
855
874
|
return createComponent$1(Root, {
|
|
@@ -858,7 +877,7 @@ const createRouterComponent = router => props => {
|
|
|
858
877
|
return props.root;
|
|
859
878
|
},
|
|
860
879
|
get preload() {
|
|
861
|
-
return props.rootPreload
|
|
880
|
+
return props.rootPreload;
|
|
862
881
|
},
|
|
863
882
|
get children() {
|
|
864
883
|
return [memo(() => (context = getOwner()) && null), createComponent$1(Routes, {
|
|
@@ -884,15 +903,9 @@ function Root(props) {
|
|
|
884
903
|
});
|
|
885
904
|
setInPreloadFn(false);
|
|
886
905
|
}));
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
},
|
|
891
|
-
keyed: true,
|
|
892
|
-
get fallback() {
|
|
893
|
-
return props.children;
|
|
894
|
-
},
|
|
895
|
-
children: Root => createComponent$1(Root, {
|
|
906
|
+
const RootComp = props.root;
|
|
907
|
+
if (RootComp) {
|
|
908
|
+
return createComponent$1(RootComp, {
|
|
896
909
|
params: params,
|
|
897
910
|
location: location,
|
|
898
911
|
get data() {
|
|
@@ -901,8 +914,9 @@ function Root(props) {
|
|
|
901
914
|
get children() {
|
|
902
915
|
return props.children;
|
|
903
916
|
}
|
|
904
|
-
})
|
|
905
|
-
}
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
return props.children;
|
|
906
920
|
}
|
|
907
921
|
function Routes(props) {
|
|
908
922
|
if (isServer) {
|
|
@@ -925,11 +939,14 @@ function Routes(props) {
|
|
|
925
939
|
}
|
|
926
940
|
const disposers = [];
|
|
927
941
|
let root;
|
|
928
|
-
|
|
929
|
-
|
|
942
|
+
let prevMatches;
|
|
943
|
+
const routeStates = createMemo(prev => {
|
|
944
|
+
const nextMatches = props.routerState.matches();
|
|
945
|
+
const previousMatches = prevMatches;
|
|
946
|
+
let equal = previousMatches && nextMatches.length === previousMatches.length;
|
|
930
947
|
const next = [];
|
|
931
948
|
for (let i = 0, len = nextMatches.length; i < len; i++) {
|
|
932
|
-
const prevMatch =
|
|
949
|
+
const prevMatch = previousMatches && previousMatches[i];
|
|
933
950
|
const nextMatch = nextMatches[i];
|
|
934
951
|
if (prev && prevMatch && nextMatch.route.key === prevMatch.route.key) {
|
|
935
952
|
next[i] = prev[i];
|
|
@@ -940,7 +957,7 @@ function Routes(props) {
|
|
|
940
957
|
}
|
|
941
958
|
createRoot(dispose => {
|
|
942
959
|
disposers[i] = dispose;
|
|
943
|
-
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => {
|
|
960
|
+
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()?.[i + 1]), () => {
|
|
944
961
|
const routeMatches = props.routerState.matches();
|
|
945
962
|
return routeMatches[i] ?? routeMatches[0];
|
|
946
963
|
});
|
|
@@ -949,30 +966,32 @@ function Routes(props) {
|
|
|
949
966
|
}
|
|
950
967
|
disposers.splice(nextMatches.length).forEach(dispose => dispose());
|
|
951
968
|
if (prev && equal) {
|
|
969
|
+
prevMatches = nextMatches;
|
|
952
970
|
return prev;
|
|
953
971
|
}
|
|
954
972
|
root = next[0];
|
|
973
|
+
prevMatches = nextMatches;
|
|
955
974
|
return next;
|
|
956
|
-
})
|
|
975
|
+
}, undefined);
|
|
957
976
|
return createOutlet(() => routeStates() && root)();
|
|
958
977
|
}
|
|
959
978
|
const createOutlet = child => {
|
|
960
|
-
return () =>
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
}
|
|
979
|
+
return () => {
|
|
980
|
+
const c = child();
|
|
981
|
+
if (c) {
|
|
982
|
+
return createComponent$1(RouteContextObj, {
|
|
983
|
+
value: c,
|
|
984
|
+
get children() {
|
|
985
|
+
return c.outlet();
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
return undefined;
|
|
990
|
+
};
|
|
972
991
|
};
|
|
973
992
|
const Route = props => {
|
|
974
993
|
const childRoutes = children(() => props.children);
|
|
975
|
-
return
|
|
994
|
+
return merge(props, {
|
|
976
995
|
get children() {
|
|
977
996
|
return childRoutes();
|
|
978
997
|
}
|
|
@@ -1078,12 +1097,10 @@ function getCache() {
|
|
|
1078
1097
|
* Revalidates the given cache entry/entries.
|
|
1079
1098
|
*/
|
|
1080
1099
|
function revalidate(key, force = true) {
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
entry[4][1](now); // retrigger live signals
|
|
1086
|
-
});
|
|
1100
|
+
const now = Date.now();
|
|
1101
|
+
cacheKeyOp(key, entry => {
|
|
1102
|
+
force && (entry[0] = 0); //force cache miss
|
|
1103
|
+
entry[4][1](now); // retrigger live signals
|
|
1087
1104
|
});
|
|
1088
1105
|
}
|
|
1089
1106
|
function cacheKeyOp(key, fn) {
|
|
@@ -1119,7 +1136,7 @@ function query(fn, name) {
|
|
|
1119
1136
|
}
|
|
1120
1137
|
}
|
|
1121
1138
|
}
|
|
1122
|
-
if (
|
|
1139
|
+
if (getObserver() && !isServer) {
|
|
1123
1140
|
tracking = true;
|
|
1124
1141
|
onCleanup(() => cached[4].count--);
|
|
1125
1142
|
}
|
|
@@ -1134,7 +1151,7 @@ function query(fn, name) {
|
|
|
1134
1151
|
let res = cached[1];
|
|
1135
1152
|
if (intent !== "preload") {
|
|
1136
1153
|
res = "then" in cached[1] ? cached[1].then(handleResponse(false), handleResponse(true)) : handleResponse(false)(cached[1]);
|
|
1137
|
-
!isServer && intent === "navigate" &&
|
|
1154
|
+
!isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
|
|
1138
1155
|
}
|
|
1139
1156
|
inPreloadFn && "then" in res && res.catch(() => {});
|
|
1140
1157
|
return res;
|
|
@@ -1149,7 +1166,7 @@ function query(fn, name) {
|
|
|
1149
1166
|
cached[0] = now;
|
|
1150
1167
|
cached[1] = res;
|
|
1151
1168
|
cached[3] = intent;
|
|
1152
|
-
!isServer && intent === "navigate" &&
|
|
1169
|
+
!isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
|
|
1153
1170
|
} else {
|
|
1154
1171
|
cache.set(key, cached = [now, res,, intent, createSignal(now)]);
|
|
1155
1172
|
cached[4].count = 0;
|
|
@@ -1184,10 +1201,8 @@ function query(fn, name) {
|
|
|
1184
1201
|
const url = v.headers.get(LocationHeader);
|
|
1185
1202
|
if (url !== null) {
|
|
1186
1203
|
// client + server relative redirect
|
|
1187
|
-
if (navigate && url.startsWith("/"))
|
|
1188
|
-
|
|
1189
|
-
replace: true
|
|
1190
|
-
});
|
|
1204
|
+
if (navigate && url.startsWith("/")) navigate(url, {
|
|
1205
|
+
replace: true
|
|
1191
1206
|
});else if (!isServer) window.location.href = url;else if (e) e.response.status = 302;
|
|
1192
1207
|
return;
|
|
1193
1208
|
}
|
|
@@ -1223,9 +1238,6 @@ query.set = (key, value) => {
|
|
|
1223
1238
|
};
|
|
1224
1239
|
query.delete = key => getCache().delete(key);
|
|
1225
1240
|
query.clear = () => getCache().clear();
|
|
1226
|
-
|
|
1227
|
-
/** @deprecated use query instead */
|
|
1228
|
-
const cache = query;
|
|
1229
1241
|
function matchKey(key, keys) {
|
|
1230
1242
|
for (let k of keys) {
|
|
1231
1243
|
if (k && key.startsWith(k)) return true;
|
|
@@ -1246,6 +1258,9 @@ function isPlainObject(obj) {
|
|
|
1246
1258
|
return obj != null && typeof obj === "object" && (!(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype);
|
|
1247
1259
|
}
|
|
1248
1260
|
|
|
1261
|
+
const submitHooksSymbol = Symbol("routerActionSubmitHooks");
|
|
1262
|
+
const settledHooksSymbol = Symbol("routerActionSettledHooks");
|
|
1263
|
+
const invokeSymbol = Symbol("routerActionInvoke");
|
|
1249
1264
|
const actions = /* #__PURE__ */new Map();
|
|
1250
1265
|
function useSubmissions(fn, filter) {
|
|
1251
1266
|
const router = useRouter();
|
|
@@ -1253,7 +1268,6 @@ function useSubmissions(fn, filter) {
|
|
|
1253
1268
|
return new Proxy([], {
|
|
1254
1269
|
get(_, property) {
|
|
1255
1270
|
if (property === $TRACK) return subs();
|
|
1256
|
-
if (property === "pending") return subs().some(sub => !sub.result);
|
|
1257
1271
|
return subs()[property];
|
|
1258
1272
|
},
|
|
1259
1273
|
has(_, property) {
|
|
@@ -1261,99 +1275,111 @@ function useSubmissions(fn, filter) {
|
|
|
1261
1275
|
}
|
|
1262
1276
|
});
|
|
1263
1277
|
}
|
|
1264
|
-
function useSubmission(fn, filter) {
|
|
1265
|
-
const submissions = useSubmissions(fn, filter);
|
|
1266
|
-
return new Proxy({}, {
|
|
1267
|
-
get(_, property) {
|
|
1268
|
-
if (submissions.length === 0 && property === "clear" || property === "retry") return () => {};
|
|
1269
|
-
return submissions[submissions.length - 1]?.[property];
|
|
1270
|
-
}
|
|
1271
|
-
});
|
|
1272
|
-
}
|
|
1273
1278
|
function useAction(action) {
|
|
1274
1279
|
const r = useRouter();
|
|
1275
1280
|
return (...args) => action.apply({
|
|
1276
1281
|
r
|
|
1277
1282
|
}, args);
|
|
1278
1283
|
}
|
|
1279
|
-
function
|
|
1280
|
-
function
|
|
1284
|
+
function actionImpl(fn, options = {}) {
|
|
1285
|
+
async function invoke(variables, current) {
|
|
1281
1286
|
const router = this.r;
|
|
1282
1287
|
const form = this.f;
|
|
1283
|
-
const
|
|
1288
|
+
const submitHooks = current[submitHooksSymbol];
|
|
1289
|
+
const settledHooks = current[settledHooksSymbol];
|
|
1290
|
+
const runMutation = () => (router.singleFlight && fn.withOptions ? fn.withOptions({
|
|
1284
1291
|
headers: {
|
|
1285
1292
|
"X-Single-Flight": "true"
|
|
1286
1293
|
}
|
|
1287
1294
|
}) : fn)(...variables);
|
|
1288
|
-
const
|
|
1295
|
+
const run = action$1(async function* (context) {
|
|
1296
|
+
context.optimistic?.();
|
|
1297
|
+
try {
|
|
1298
|
+
const value = await context.call();
|
|
1299
|
+
yield;
|
|
1300
|
+
return {
|
|
1301
|
+
error: false,
|
|
1302
|
+
value
|
|
1303
|
+
};
|
|
1304
|
+
} catch (error) {
|
|
1305
|
+
yield;
|
|
1306
|
+
return {
|
|
1307
|
+
error: true,
|
|
1308
|
+
value: error
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
});
|
|
1312
|
+
const settled = await settleActionResult(run({
|
|
1313
|
+
call: runMutation,
|
|
1314
|
+
optimistic: submitHooks.size ? () => {
|
|
1315
|
+
for (const hook of submitHooks.values()) hook(...variables);
|
|
1316
|
+
} : undefined
|
|
1317
|
+
}));
|
|
1318
|
+
const response = await handleResponse(settled.value, settled.error, router.navigatorFactory());
|
|
1319
|
+
if (!response) return undefined;
|
|
1289
1320
|
let submission;
|
|
1290
|
-
|
|
1291
|
-
return async res => {
|
|
1292
|
-
const result = await handleResponse(res, error, router.navigatorFactory());
|
|
1293
|
-
let retry = null;
|
|
1294
|
-
o.onComplete?.({
|
|
1295
|
-
...submission,
|
|
1296
|
-
result: result?.data,
|
|
1297
|
-
error: result?.error,
|
|
1298
|
-
pending: false,
|
|
1299
|
-
retry() {
|
|
1300
|
-
return retry = submission.retry();
|
|
1301
|
-
}
|
|
1302
|
-
});
|
|
1303
|
-
if (retry) return retry;
|
|
1304
|
-
if (!result) return submission.clear();
|
|
1305
|
-
setResult(result);
|
|
1306
|
-
if (result.error && !form) throw result.error;
|
|
1307
|
-
return result.data;
|
|
1308
|
-
};
|
|
1309
|
-
}
|
|
1310
|
-
router.submissions[1](s => [...s, submission = {
|
|
1321
|
+
submission = {
|
|
1311
1322
|
input: variables,
|
|
1312
1323
|
url,
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
},
|
|
1316
|
-
get error() {
|
|
1317
|
-
return result()?.error;
|
|
1318
|
-
},
|
|
1319
|
-
get pending() {
|
|
1320
|
-
return !result();
|
|
1321
|
-
},
|
|
1324
|
+
result: response.data,
|
|
1325
|
+
error: response.error,
|
|
1322
1326
|
clear() {
|
|
1323
|
-
router.submissions[1](
|
|
1327
|
+
router.submissions[1](entries => entries.filter(entry => entry !== submission));
|
|
1324
1328
|
},
|
|
1325
1329
|
retry() {
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1330
|
+
submission.clear();
|
|
1331
|
+
return current[invokeSymbol].call({
|
|
1332
|
+
r: router,
|
|
1333
|
+
f: form
|
|
1334
|
+
}, variables, current);
|
|
1329
1335
|
}
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1336
|
+
};
|
|
1337
|
+
router.submissions[1](entries => [...entries, submission]);
|
|
1338
|
+
for (const hook of settledHooks.values()) hook(submission);
|
|
1339
|
+
if (response.error && !form) throw response.error;
|
|
1340
|
+
return response.data;
|
|
1332
1341
|
}
|
|
1333
1342
|
const o = typeof options === "string" ? {
|
|
1334
1343
|
name: options
|
|
1335
1344
|
} : options;
|
|
1336
1345
|
const name = o.name || (!isServer ? String(hashString(fn.toString())) : undefined);
|
|
1337
1346
|
const url = fn.url || name && `https://action/${name}` || "";
|
|
1338
|
-
|
|
1339
|
-
if (name) setFunctionName(
|
|
1340
|
-
return
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1347
|
+
const wrapped = toAction(invoke, url);
|
|
1348
|
+
if (name) setFunctionName(wrapped, name);
|
|
1349
|
+
return wrapped;
|
|
1350
|
+
}
|
|
1351
|
+
const action = actionImpl;
|
|
1352
|
+
function toAction(invoke, url, boundArgs = [], base = url, submitHooks = new Map(), settledHooks = new Map()) {
|
|
1353
|
+
const fn = function (...args) {
|
|
1354
|
+
return invoke.call(this, [...boundArgs, ...args], fn);
|
|
1355
|
+
};
|
|
1343
1356
|
fn.toString = () => {
|
|
1344
1357
|
if (!url) throw new Error("Client Actions need explicit names if server rendered");
|
|
1345
1358
|
return url;
|
|
1346
1359
|
};
|
|
1347
1360
|
fn.with = function (...args) {
|
|
1348
|
-
const newFn = function (...passedArgs) {
|
|
1349
|
-
return fn.call(this, ...args, ...passedArgs);
|
|
1350
|
-
};
|
|
1351
|
-
newFn.base = fn.base;
|
|
1352
1361
|
const uri = new URL(url, mockBase);
|
|
1353
1362
|
uri.searchParams.set("args", hashKey(args));
|
|
1354
|
-
|
|
1363
|
+
const next = toAction(invoke, (uri.origin === "https://action" ? uri.origin : "") + uri.pathname + uri.search, [...boundArgs, ...args], base, submitHooks, settledHooks);
|
|
1364
|
+
return next;
|
|
1365
|
+
};
|
|
1366
|
+
fn.onSubmit = function (hook) {
|
|
1367
|
+
const id = Symbol("actionOnSubmitHook");
|
|
1368
|
+
submitHooks.set(id, hook);
|
|
1369
|
+
getOwner() && onCleanup(() => submitHooks.delete(id));
|
|
1370
|
+
return this;
|
|
1371
|
+
};
|
|
1372
|
+
fn.onSettled = function (hook) {
|
|
1373
|
+
const id = Symbol("actionOnSettledHook");
|
|
1374
|
+
settledHooks.set(id, hook);
|
|
1375
|
+
getOwner() && onCleanup(() => settledHooks.delete(id));
|
|
1376
|
+
return this;
|
|
1355
1377
|
};
|
|
1356
1378
|
fn.url = url;
|
|
1379
|
+
fn.base = base;
|
|
1380
|
+
fn[submitHooksSymbol] = submitHooks;
|
|
1381
|
+
fn[settledHooksSymbol] = settledHooks;
|
|
1382
|
+
fn[invokeSymbol] = invoke;
|
|
1357
1383
|
if (!isServer) {
|
|
1358
1384
|
actions.set(url, fn);
|
|
1359
1385
|
getOwner() && onCleanup(() => actions.delete(url));
|
|
@@ -1361,6 +1387,21 @@ function toAction(fn, url) {
|
|
|
1361
1387
|
return fn;
|
|
1362
1388
|
}
|
|
1363
1389
|
const hashString = s => s.split("").reduce((a, b) => (a << 5) - a + b.charCodeAt(0) | 0, 0);
|
|
1390
|
+
async function settleActionResult(result) {
|
|
1391
|
+
const value = result;
|
|
1392
|
+
if (value && typeof value.then === "function") {
|
|
1393
|
+
return result.then(value => value);
|
|
1394
|
+
}
|
|
1395
|
+
if (value && typeof value.next === "function") {
|
|
1396
|
+
const iterator = value;
|
|
1397
|
+
let next = await iterator.next();
|
|
1398
|
+
while (!next.done) {
|
|
1399
|
+
next = await iterator.next();
|
|
1400
|
+
}
|
|
1401
|
+
return next.value;
|
|
1402
|
+
}
|
|
1403
|
+
return result;
|
|
1404
|
+
}
|
|
1364
1405
|
async function handleResponse(response, error, navigate) {
|
|
1365
1406
|
let data;
|
|
1366
1407
|
let custom;
|
|
@@ -1669,12 +1710,21 @@ function MemoryRouter(props) {
|
|
|
1669
1710
|
}
|
|
1670
1711
|
|
|
1671
1712
|
var _tmpl$ = /*#__PURE__*/template(`<a>`);
|
|
1713
|
+
function toClassName(value) {
|
|
1714
|
+
if (!value) return "";
|
|
1715
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
1716
|
+
if (Array.isArray(value)) return value.map(toClassName).filter(Boolean).join(" ");
|
|
1717
|
+
if (typeof value === "object") {
|
|
1718
|
+
return Object.entries(value).filter(([, enabled]) => enabled).map(([name]) => name).join(" ");
|
|
1719
|
+
}
|
|
1720
|
+
return "";
|
|
1721
|
+
}
|
|
1672
1722
|
function A(props) {
|
|
1673
|
-
props =
|
|
1723
|
+
props = merge({
|
|
1674
1724
|
inactiveClass: "inactive",
|
|
1675
1725
|
activeClass: "active"
|
|
1676
1726
|
}, props);
|
|
1677
|
-
const
|
|
1727
|
+
const rest = omit(props, "href", "state", "class", "activeClass", "inactiveClass", "end");
|
|
1678
1728
|
const to = useResolvedPath(() => props.href);
|
|
1679
1729
|
const href = useHref(to);
|
|
1680
1730
|
const location = useLocation();
|
|
@@ -1685,26 +1735,20 @@ function A(props) {
|
|
|
1685
1735
|
const loc = decodeURI(normalizePath(location.pathname).toLowerCase());
|
|
1686
1736
|
return [props.end ? path === loc : loc.startsWith(path + "/") || loc === path, path === loc];
|
|
1687
1737
|
});
|
|
1738
|
+
const className = createMemo(() => [toClassName(props.class), isActive()[0] ? props.activeClass : props.inactiveClass].filter(Boolean).join(" "));
|
|
1688
1739
|
return (() => {
|
|
1689
1740
|
var _el$ = _tmpl$();
|
|
1690
|
-
spread(_el$, mergeProps
|
|
1741
|
+
spread(_el$, mergeProps(rest, {
|
|
1691
1742
|
get href() {
|
|
1692
1743
|
return href() || props.href;
|
|
1693
1744
|
},
|
|
1694
1745
|
get state() {
|
|
1695
1746
|
return JSON.stringify(props.state);
|
|
1696
1747
|
},
|
|
1697
|
-
get
|
|
1698
|
-
return
|
|
1699
|
-
...(props.class && {
|
|
1700
|
-
[props.class]: true
|
|
1701
|
-
}),
|
|
1702
|
-
[props.inactiveClass]: !isActive()[0],
|
|
1703
|
-
[props.activeClass]: isActive()[0],
|
|
1704
|
-
...rest.classList
|
|
1705
|
-
};
|
|
1748
|
+
get ["class"]() {
|
|
1749
|
+
return className();
|
|
1706
1750
|
},
|
|
1707
|
-
"link":
|
|
1751
|
+
"link": true,
|
|
1708
1752
|
get ["aria-current"]() {
|
|
1709
1753
|
return isActive()[1] ? "page" : undefined;
|
|
1710
1754
|
}
|
|
@@ -1730,99 +1774,6 @@ function Navigate(props) {
|
|
|
1730
1774
|
return null;
|
|
1731
1775
|
}
|
|
1732
1776
|
|
|
1733
|
-
/**
|
|
1734
|
-
* This is mock of the eventual Solid 2.0 primitive. It is not fully featured.
|
|
1735
|
-
*/
|
|
1736
|
-
|
|
1737
|
-
/**
|
|
1738
|
-
* As `createAsync` and `createAsyncStore` are wrappers for `createResource`,
|
|
1739
|
-
* this type allows to support `latest` field for these primitives.
|
|
1740
|
-
* It will be removed in the future.
|
|
1741
|
-
*/
|
|
1742
|
-
|
|
1743
|
-
function createAsync(fn, options) {
|
|
1744
|
-
let resource;
|
|
1745
|
-
let prev = () => !resource || resource.state === "unresolved" ? undefined : resource.latest;
|
|
1746
|
-
[resource] = createResource(() => subFetch(fn, catchError(() => untrack(prev), () => undefined)), v => v, options);
|
|
1747
|
-
const resultAccessor = () => resource();
|
|
1748
|
-
if (options?.name) setFunctionName(resultAccessor, options.name);
|
|
1749
|
-
Object.defineProperty(resultAccessor, "latest", {
|
|
1750
|
-
get() {
|
|
1751
|
-
return resource.latest;
|
|
1752
|
-
}
|
|
1753
|
-
});
|
|
1754
|
-
return resultAccessor;
|
|
1755
|
-
}
|
|
1756
|
-
function createAsyncStore(fn, options = {}) {
|
|
1757
|
-
let resource;
|
|
1758
|
-
let prev = () => !resource || resource.state === "unresolved" ? undefined : unwrap(resource.latest);
|
|
1759
|
-
[resource] = createResource(() => subFetch(fn, catchError(() => untrack(prev), () => undefined)), v => v, {
|
|
1760
|
-
...options,
|
|
1761
|
-
storage: init => createDeepSignal(init, options.reconcile)
|
|
1762
|
-
});
|
|
1763
|
-
const resultAccessor = () => resource();
|
|
1764
|
-
Object.defineProperty(resultAccessor, "latest", {
|
|
1765
|
-
get() {
|
|
1766
|
-
return resource.latest;
|
|
1767
|
-
}
|
|
1768
|
-
});
|
|
1769
|
-
return resultAccessor;
|
|
1770
|
-
}
|
|
1771
|
-
function createDeepSignal(value, options) {
|
|
1772
|
-
const [store, setStore] = createStore({
|
|
1773
|
-
value: structuredClone(value)
|
|
1774
|
-
});
|
|
1775
|
-
return [() => store.value, v => {
|
|
1776
|
-
typeof v === "function" && (v = v());
|
|
1777
|
-
setStore("value", reconcile(structuredClone(v), options));
|
|
1778
|
-
return store.value;
|
|
1779
|
-
}];
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
// mock promise while hydrating to prevent fetching
|
|
1783
|
-
class MockPromise {
|
|
1784
|
-
static all() {
|
|
1785
|
-
return new MockPromise();
|
|
1786
|
-
}
|
|
1787
|
-
static allSettled() {
|
|
1788
|
-
return new MockPromise();
|
|
1789
|
-
}
|
|
1790
|
-
static any() {
|
|
1791
|
-
return new MockPromise();
|
|
1792
|
-
}
|
|
1793
|
-
static race() {
|
|
1794
|
-
return new MockPromise();
|
|
1795
|
-
}
|
|
1796
|
-
static reject() {
|
|
1797
|
-
return new MockPromise();
|
|
1798
|
-
}
|
|
1799
|
-
static resolve() {
|
|
1800
|
-
return new MockPromise();
|
|
1801
|
-
}
|
|
1802
|
-
catch() {
|
|
1803
|
-
return new MockPromise();
|
|
1804
|
-
}
|
|
1805
|
-
then() {
|
|
1806
|
-
return new MockPromise();
|
|
1807
|
-
}
|
|
1808
|
-
finally() {
|
|
1809
|
-
return new MockPromise();
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
function subFetch(fn, prev) {
|
|
1813
|
-
if (isServer || !sharedConfig.context) return fn(prev);
|
|
1814
|
-
const ogFetch = fetch;
|
|
1815
|
-
const ogPromise = Promise;
|
|
1816
|
-
try {
|
|
1817
|
-
window.fetch = () => new MockPromise();
|
|
1818
|
-
Promise = MockPromise;
|
|
1819
|
-
return fn(prev);
|
|
1820
|
-
} finally {
|
|
1821
|
-
window.fetch = ogFetch;
|
|
1822
|
-
Promise = ogPromise;
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
|
|
1826
1777
|
function redirect(url, init = 302) {
|
|
1827
1778
|
let responseInit;
|
|
1828
1779
|
let revalidate;
|
|
@@ -1876,4 +1827,4 @@ function json(data, init = {}) {
|
|
|
1876
1827
|
return response;
|
|
1877
1828
|
}
|
|
1878
1829
|
|
|
1879
|
-
export { A, HashRouter, MemoryRouter, Navigate, Route, Router, RouterContextObj as RouterContext, StaticRouter, mergeSearchString as _mergeSearchString, action,
|
|
1830
|
+
export { A, HashRouter, MemoryRouter, Navigate, Route, Router, RouterContextObj as RouterContext, StaticRouter, mergeSearchString as _mergeSearchString, action, createBeforeLeave, createMemoryHistory, createRouter, json, keepDepth, notifyIfNotBlocked, query, redirect, reload, revalidate, saveCurrentDepth, useAction, useBeforeLeave, useCurrentMatches, useHref, useIsRouting, useLocation, useMatch, useNavigate, useParams, usePreloadRoute, useResolvedPath, useSearchParams, useSubmissions };
|