@solidjs/router 0.16.1 → 0.17.0-next.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 +85 -79
- package/dist/components.jsx +22 -16
- package/dist/data/action.d.ts +12 -10
- package/dist/data/action.js +94 -75
- package/dist/data/events.js +1 -1
- 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 +1 -1
- package/dist/index.js +236 -275
- package/dist/lifecycle.js +1 -1
- package/dist/routers/Router.js +1 -1
- package/dist/routers/StaticRouter.js +1 -1
- package/dist/routers/components.d.ts +0 -4
- package/dist/routers/components.jsx +45 -26
- package/dist/routing.d.ts +2 -2
- package/dist/routing.js +72 -50
- package/dist/types.d.ts +2 -17
- package/package.json +7 -5
- package/dist/data/createAsync.d.ts +0 -32
- package/dist/data/createAsync.js +0 -96
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();
|
|
@@ -601,49 +606,45 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
601
606
|
const renderPath = utils.renderPath || (p => p);
|
|
602
607
|
const beforeLeave = utils.beforeLeave || createBeforeLeave();
|
|
603
608
|
const basePath = resolvePath("", options.base || "");
|
|
609
|
+
const initialSource = untrack(source);
|
|
604
610
|
if (basePath === undefined) {
|
|
605
611
|
throw new Error(`${basePath} is not a valid base path`);
|
|
606
|
-
} else if (basePath && !
|
|
612
|
+
} else if (basePath && !initialSource.value) {
|
|
607
613
|
setSource({
|
|
608
614
|
value: basePath,
|
|
609
615
|
replace: true,
|
|
610
616
|
scroll: false
|
|
611
617
|
});
|
|
612
618
|
}
|
|
613
|
-
const [isRouting, setIsRouting] = createSignal(false
|
|
619
|
+
const [isRouting, setIsRouting] = createSignal(false, {
|
|
620
|
+
pureWrite: true
|
|
621
|
+
});
|
|
614
622
|
|
|
615
|
-
//
|
|
616
|
-
|
|
623
|
+
// Navigate override written from event handlers.
|
|
624
|
+
const [navigateTarget, setNavigateTarget] = createSignal(undefined, {
|
|
625
|
+
pureWrite: true
|
|
626
|
+
});
|
|
617
627
|
|
|
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;
|
|
628
|
+
// Keep track of last target, so that last call to navigate wins
|
|
629
|
+
let lastTransitionTarget;
|
|
632
630
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
631
|
+
// source() remains canonical for native history changes; navigateTarget()
|
|
632
|
+
// temporarily overrides it for in-flight programmatic navigation.
|
|
633
|
+
const reference = createMemo(() => {
|
|
634
|
+
const nav = navigateTarget();
|
|
635
|
+
if (nav !== undefined) return nav.value;
|
|
636
|
+
return source().value;
|
|
637
|
+
});
|
|
638
|
+
const state = createMemo(() => {
|
|
639
|
+
const nav = navigateTarget();
|
|
640
|
+
if (nav !== undefined) return nav.state;
|
|
641
|
+
return source().state;
|
|
642
|
+
});
|
|
644
643
|
const location = createLocation(reference, state, utils.queryWrapper);
|
|
645
644
|
const referrers = [];
|
|
646
|
-
const submissions = createSignal(isServer ? initFromFlash() : []
|
|
645
|
+
const submissions = createSignal(isServer ? initFromFlash() : [], {
|
|
646
|
+
pureWrite: true
|
|
647
|
+
});
|
|
647
648
|
const matches = createMemo(() => {
|
|
648
649
|
if (typeof options.transformUrl === "function") {
|
|
649
650
|
return getRouteMatches(branches(), options.transformUrl(location.pathname));
|
|
@@ -667,11 +668,6 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
667
668
|
return resolvePath(basePath, to);
|
|
668
669
|
}
|
|
669
670
|
};
|
|
670
|
-
|
|
671
|
-
// Create a native transition, when source updates
|
|
672
|
-
createRenderEffect(on(source, source => transition("native", source), {
|
|
673
|
-
defer: true
|
|
674
|
-
}));
|
|
675
671
|
return {
|
|
676
672
|
base: baseRoute,
|
|
677
673
|
location,
|
|
@@ -738,17 +734,36 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
738
734
|
scroll,
|
|
739
735
|
state: state()
|
|
740
736
|
});
|
|
741
|
-
|
|
737
|
+
const newTarget = {
|
|
742
738
|
value: resolvedTo,
|
|
743
739
|
state: nextState
|
|
744
|
-
}
|
|
740
|
+
};
|
|
741
|
+
if (lastTransitionTarget === undefined) {
|
|
742
|
+
setIsRouting(true);
|
|
743
|
+
flush();
|
|
744
|
+
}
|
|
745
|
+
intent = "navigate";
|
|
746
|
+
lastTransitionTarget = newTarget;
|
|
747
|
+
if (lastTransitionTarget === newTarget) {
|
|
748
|
+
setNavigateTarget({
|
|
749
|
+
...lastTransitionTarget
|
|
750
|
+
});
|
|
751
|
+
queueMicrotask(() => {
|
|
752
|
+
if (lastTransitionTarget !== newTarget) return;
|
|
753
|
+
intent = undefined;
|
|
754
|
+
navigateEnd(lastTransitionTarget);
|
|
755
|
+
setNavigateTarget(undefined);
|
|
756
|
+
setIsRouting(false);
|
|
757
|
+
lastTransitionTarget = undefined;
|
|
758
|
+
});
|
|
759
|
+
}
|
|
745
760
|
}
|
|
746
761
|
}
|
|
747
762
|
});
|
|
748
763
|
}
|
|
749
764
|
function navigatorFactory(route) {
|
|
750
765
|
// Workaround for vite issue (https://github.com/vitejs/vite/issues/3803)
|
|
751
|
-
route = route ||
|
|
766
|
+
route = route || useOptionalContext(RouteContextObj) || baseRoute;
|
|
752
767
|
return (to, options) => navigateFromRoute(route, to, options);
|
|
753
768
|
}
|
|
754
769
|
function navigateEnd(next) {
|
|
@@ -794,7 +809,12 @@ function createRouterContext(integration, branches, getContext, options = {}) {
|
|
|
794
809
|
}
|
|
795
810
|
function initFromFlash() {
|
|
796
811
|
const e = getRequestEvent();
|
|
797
|
-
|
|
812
|
+
if (!(e && e.router && e.router.submission)) return [];
|
|
813
|
+
return [{
|
|
814
|
+
...e.router.submission,
|
|
815
|
+
clear() {},
|
|
816
|
+
retry() {}
|
|
817
|
+
}];
|
|
798
818
|
}
|
|
799
819
|
}
|
|
800
820
|
function createRouteContext(router, parent, outlet, match) {
|
|
@@ -836,30 +856,38 @@ function createRouteContext(router, parent, outlet, match) {
|
|
|
836
856
|
return route;
|
|
837
857
|
}
|
|
838
858
|
|
|
839
|
-
const createRouterComponent = router => props
|
|
859
|
+
const createRouterComponent = router => function IntegratedRouter(props) {
|
|
840
860
|
const {
|
|
841
|
-
base
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
861
|
+
base,
|
|
862
|
+
singleFlight,
|
|
863
|
+
transformUrl,
|
|
864
|
+
root,
|
|
865
|
+
rootPreload,
|
|
866
|
+
routeChildren
|
|
867
|
+
} = untrack(() => ({
|
|
868
|
+
base: props.base,
|
|
869
|
+
singleFlight: props.singleFlight,
|
|
870
|
+
transformUrl: props.transformUrl,
|
|
871
|
+
root: props.root,
|
|
872
|
+
rootPreload: props.rootPreload,
|
|
873
|
+
routeChildren: props.children
|
|
874
|
+
}));
|
|
875
|
+
const routeDefs = children(() => routeChildren);
|
|
876
|
+
const branches = createMemo(() => createBranches(routeDefs(), base || ""));
|
|
845
877
|
let context;
|
|
846
878
|
const routerState = createRouterContext(router, branches, () => context, {
|
|
847
879
|
base,
|
|
848
|
-
singleFlight
|
|
849
|
-
transformUrl
|
|
880
|
+
singleFlight,
|
|
881
|
+
transformUrl
|
|
850
882
|
});
|
|
851
883
|
router.create && router.create(routerState);
|
|
852
|
-
return createComponent$1(RouterContextObj
|
|
884
|
+
return createComponent$1(RouterContextObj, {
|
|
853
885
|
value: routerState,
|
|
854
886
|
get children() {
|
|
855
887
|
return createComponent$1(Root, {
|
|
856
888
|
routerState: routerState,
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
},
|
|
860
|
-
get preload() {
|
|
861
|
-
return props.rootPreload || props.rootLoad;
|
|
862
|
-
},
|
|
889
|
+
root: root,
|
|
890
|
+
preload: rootPreload,
|
|
863
891
|
get children() {
|
|
864
892
|
return [memo(() => (context = getOwner()) && null), createComponent$1(Routes, {
|
|
865
893
|
routerState: routerState,
|
|
@@ -884,15 +912,9 @@ function Root(props) {
|
|
|
884
912
|
});
|
|
885
913
|
setInPreloadFn(false);
|
|
886
914
|
}));
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
},
|
|
891
|
-
keyed: true,
|
|
892
|
-
get fallback() {
|
|
893
|
-
return props.children;
|
|
894
|
-
},
|
|
895
|
-
children: Root => createComponent$1(Root, {
|
|
915
|
+
const RootComp = props.root;
|
|
916
|
+
if (RootComp) {
|
|
917
|
+
return createComponent$1(RootComp, {
|
|
896
918
|
params: params,
|
|
897
919
|
location: location,
|
|
898
920
|
get data() {
|
|
@@ -901,8 +923,9 @@ function Root(props) {
|
|
|
901
923
|
get children() {
|
|
902
924
|
return props.children;
|
|
903
925
|
}
|
|
904
|
-
})
|
|
905
|
-
}
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
return props.children;
|
|
906
929
|
}
|
|
907
930
|
function Routes(props) {
|
|
908
931
|
if (isServer) {
|
|
@@ -925,11 +948,14 @@ function Routes(props) {
|
|
|
925
948
|
}
|
|
926
949
|
const disposers = [];
|
|
927
950
|
let root;
|
|
928
|
-
|
|
929
|
-
|
|
951
|
+
let prevMatches;
|
|
952
|
+
const routeStates = createMemo(prev => {
|
|
953
|
+
const nextMatches = props.routerState.matches();
|
|
954
|
+
const previousMatches = prevMatches;
|
|
955
|
+
let equal = previousMatches && nextMatches.length === previousMatches.length;
|
|
930
956
|
const next = [];
|
|
931
957
|
for (let i = 0, len = nextMatches.length; i < len; i++) {
|
|
932
|
-
const prevMatch =
|
|
958
|
+
const prevMatch = previousMatches && previousMatches[i];
|
|
933
959
|
const nextMatch = nextMatches[i];
|
|
934
960
|
if (prev && prevMatch && nextMatch.route.key === prevMatch.route.key) {
|
|
935
961
|
next[i] = prev[i];
|
|
@@ -940,7 +966,7 @@ function Routes(props) {
|
|
|
940
966
|
}
|
|
941
967
|
createRoot(dispose => {
|
|
942
968
|
disposers[i] = dispose;
|
|
943
|
-
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()[i + 1]), () => {
|
|
969
|
+
next[i] = createRouteContext(props.routerState, next[i - 1] || props.routerState.base, createOutlet(() => routeStates()?.[i + 1]), () => {
|
|
944
970
|
const routeMatches = props.routerState.matches();
|
|
945
971
|
return routeMatches[i] ?? routeMatches[0];
|
|
946
972
|
});
|
|
@@ -949,30 +975,33 @@ function Routes(props) {
|
|
|
949
975
|
}
|
|
950
976
|
disposers.splice(nextMatches.length).forEach(dispose => dispose());
|
|
951
977
|
if (prev && equal) {
|
|
978
|
+
prevMatches = nextMatches;
|
|
952
979
|
return prev;
|
|
953
980
|
}
|
|
954
981
|
root = next[0];
|
|
982
|
+
prevMatches = nextMatches;
|
|
955
983
|
return next;
|
|
956
|
-
})
|
|
957
|
-
|
|
984
|
+
}, undefined);
|
|
985
|
+
const outlet = createOutlet(() => routeStates() && root);
|
|
986
|
+
return memo(outlet);
|
|
958
987
|
}
|
|
959
988
|
const createOutlet = child => {
|
|
960
|
-
return () =>
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
}
|
|
989
|
+
return () => {
|
|
990
|
+
const c = child();
|
|
991
|
+
if (c) {
|
|
992
|
+
return createComponent$1(RouteContextObj, {
|
|
993
|
+
value: c,
|
|
994
|
+
get children() {
|
|
995
|
+
return c.outlet();
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
return undefined;
|
|
1000
|
+
};
|
|
972
1001
|
};
|
|
973
1002
|
const Route = props => {
|
|
974
1003
|
const childRoutes = children(() => props.children);
|
|
975
|
-
return
|
|
1004
|
+
return merge(props, {
|
|
976
1005
|
get children() {
|
|
977
1006
|
return childRoutes();
|
|
978
1007
|
}
|
|
@@ -1078,12 +1107,10 @@ function getCache() {
|
|
|
1078
1107
|
* Revalidates the given cache entry/entries.
|
|
1079
1108
|
*/
|
|
1080
1109
|
function revalidate(key, force = true) {
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
entry[4][1](now); // retrigger live signals
|
|
1086
|
-
});
|
|
1110
|
+
const now = Date.now();
|
|
1111
|
+
cacheKeyOp(key, entry => {
|
|
1112
|
+
force && (entry[0] = 0); //force cache miss
|
|
1113
|
+
entry[4][1](now); // retrigger live signals
|
|
1087
1114
|
});
|
|
1088
1115
|
}
|
|
1089
1116
|
function cacheKeyOp(key, fn) {
|
|
@@ -1119,7 +1146,7 @@ function query(fn, name) {
|
|
|
1119
1146
|
}
|
|
1120
1147
|
}
|
|
1121
1148
|
}
|
|
1122
|
-
if (
|
|
1149
|
+
if (getObserver() && !isServer) {
|
|
1123
1150
|
tracking = true;
|
|
1124
1151
|
onCleanup(() => cached[4].count--);
|
|
1125
1152
|
}
|
|
@@ -1134,7 +1161,7 @@ function query(fn, name) {
|
|
|
1134
1161
|
let res = cached[1];
|
|
1135
1162
|
if (intent !== "preload") {
|
|
1136
1163
|
res = "then" in cached[1] ? cached[1].then(handleResponse(false), handleResponse(true)) : handleResponse(false)(cached[1]);
|
|
1137
|
-
!isServer && intent === "navigate" &&
|
|
1164
|
+
!isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
|
|
1138
1165
|
}
|
|
1139
1166
|
inPreloadFn && "then" in res && res.catch(() => {});
|
|
1140
1167
|
return res;
|
|
@@ -1149,7 +1176,7 @@ function query(fn, name) {
|
|
|
1149
1176
|
cached[0] = now;
|
|
1150
1177
|
cached[1] = res;
|
|
1151
1178
|
cached[3] = intent;
|
|
1152
|
-
!isServer && intent === "navigate" &&
|
|
1179
|
+
!isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
|
|
1153
1180
|
} else {
|
|
1154
1181
|
cache.set(key, cached = [now, res,, intent, createSignal(now)]);
|
|
1155
1182
|
cached[4].count = 0;
|
|
@@ -1184,10 +1211,8 @@ function query(fn, name) {
|
|
|
1184
1211
|
const url = v.headers.get(LocationHeader);
|
|
1185
1212
|
if (url !== null) {
|
|
1186
1213
|
// client + server relative redirect
|
|
1187
|
-
if (navigate && url.startsWith("/"))
|
|
1188
|
-
|
|
1189
|
-
replace: true
|
|
1190
|
-
});
|
|
1214
|
+
if (navigate && url.startsWith("/")) navigate(url, {
|
|
1215
|
+
replace: true
|
|
1191
1216
|
});else if (!isServer) window.location.href = url;else if (e) e.response.status = 302;
|
|
1192
1217
|
return;
|
|
1193
1218
|
}
|
|
@@ -1223,9 +1248,6 @@ query.set = (key, value) => {
|
|
|
1223
1248
|
};
|
|
1224
1249
|
query.delete = key => getCache().delete(key);
|
|
1225
1250
|
query.clear = () => getCache().clear();
|
|
1226
|
-
|
|
1227
|
-
/** @deprecated use query instead */
|
|
1228
|
-
const cache = query;
|
|
1229
1251
|
function matchKey(key, keys) {
|
|
1230
1252
|
for (let k of keys) {
|
|
1231
1253
|
if (k && key.startsWith(k)) return true;
|
|
@@ -1246,6 +1268,9 @@ function isPlainObject(obj) {
|
|
|
1246
1268
|
return obj != null && typeof obj === "object" && (!(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype);
|
|
1247
1269
|
}
|
|
1248
1270
|
|
|
1271
|
+
const submitHooksSymbol = Symbol("routerActionSubmitHooks");
|
|
1272
|
+
const settledHooksSymbol = Symbol("routerActionSettledHooks");
|
|
1273
|
+
const invokeSymbol = Symbol("routerActionInvoke");
|
|
1249
1274
|
const actions = /* #__PURE__ */new Map();
|
|
1250
1275
|
function useSubmissions(fn, filter) {
|
|
1251
1276
|
const router = useRouter();
|
|
@@ -1253,7 +1278,6 @@ function useSubmissions(fn, filter) {
|
|
|
1253
1278
|
return new Proxy([], {
|
|
1254
1279
|
get(_, property) {
|
|
1255
1280
|
if (property === $TRACK) return subs();
|
|
1256
|
-
if (property === "pending") return subs().some(sub => !sub.result);
|
|
1257
1281
|
return subs()[property];
|
|
1258
1282
|
},
|
|
1259
1283
|
has(_, property) {
|
|
@@ -1261,99 +1285,111 @@ function useSubmissions(fn, filter) {
|
|
|
1261
1285
|
}
|
|
1262
1286
|
});
|
|
1263
1287
|
}
|
|
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
1288
|
function useAction(action) {
|
|
1274
1289
|
const r = useRouter();
|
|
1275
1290
|
return (...args) => action.apply({
|
|
1276
1291
|
r
|
|
1277
1292
|
}, args);
|
|
1278
1293
|
}
|
|
1279
|
-
function
|
|
1280
|
-
function
|
|
1294
|
+
function actionImpl(fn, options = {}) {
|
|
1295
|
+
async function invoke(variables, current) {
|
|
1281
1296
|
const router = this.r;
|
|
1282
1297
|
const form = this.f;
|
|
1283
|
-
const
|
|
1298
|
+
const submitHooks = current[submitHooksSymbol];
|
|
1299
|
+
const settledHooks = current[settledHooksSymbol];
|
|
1300
|
+
const runMutation = () => (router.singleFlight && fn.withOptions ? fn.withOptions({
|
|
1284
1301
|
headers: {
|
|
1285
1302
|
"X-Single-Flight": "true"
|
|
1286
1303
|
}
|
|
1287
1304
|
}) : fn)(...variables);
|
|
1288
|
-
const
|
|
1305
|
+
const run = action$1(async function* (context) {
|
|
1306
|
+
context.optimistic?.();
|
|
1307
|
+
try {
|
|
1308
|
+
const value = await context.call();
|
|
1309
|
+
yield;
|
|
1310
|
+
return {
|
|
1311
|
+
error: false,
|
|
1312
|
+
value
|
|
1313
|
+
};
|
|
1314
|
+
} catch (error) {
|
|
1315
|
+
yield;
|
|
1316
|
+
return {
|
|
1317
|
+
error: true,
|
|
1318
|
+
value: error
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
});
|
|
1322
|
+
const settled = await settleActionResult(run({
|
|
1323
|
+
call: runMutation,
|
|
1324
|
+
optimistic: submitHooks.size ? () => {
|
|
1325
|
+
for (const hook of submitHooks.values()) hook(...variables);
|
|
1326
|
+
} : undefined
|
|
1327
|
+
}));
|
|
1328
|
+
const response = await handleResponse(settled.value, settled.error, router.navigatorFactory());
|
|
1329
|
+
if (!response) return undefined;
|
|
1289
1330
|
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 = {
|
|
1331
|
+
submission = {
|
|
1311
1332
|
input: variables,
|
|
1312
1333
|
url,
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
},
|
|
1316
|
-
get error() {
|
|
1317
|
-
return result()?.error;
|
|
1318
|
-
},
|
|
1319
|
-
get pending() {
|
|
1320
|
-
return !result();
|
|
1321
|
-
},
|
|
1334
|
+
result: response.data,
|
|
1335
|
+
error: response.error,
|
|
1322
1336
|
clear() {
|
|
1323
|
-
router.submissions[1](
|
|
1337
|
+
router.submissions[1](entries => entries.filter(entry => entry !== submission));
|
|
1324
1338
|
},
|
|
1325
1339
|
retry() {
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1340
|
+
submission.clear();
|
|
1341
|
+
return current[invokeSymbol].call({
|
|
1342
|
+
r: router,
|
|
1343
|
+
f: form
|
|
1344
|
+
}, variables, current);
|
|
1329
1345
|
}
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1346
|
+
};
|
|
1347
|
+
router.submissions[1](entries => [...entries, submission]);
|
|
1348
|
+
for (const hook of settledHooks.values()) hook(submission);
|
|
1349
|
+
if (response.error && !form) throw response.error;
|
|
1350
|
+
return response.data;
|
|
1332
1351
|
}
|
|
1333
1352
|
const o = typeof options === "string" ? {
|
|
1334
1353
|
name: options
|
|
1335
1354
|
} : options;
|
|
1336
1355
|
const name = o.name || (!isServer ? String(hashString(fn.toString())) : undefined);
|
|
1337
1356
|
const url = fn.url || name && `https://action/${name}` || "";
|
|
1338
|
-
|
|
1339
|
-
if (name) setFunctionName(
|
|
1340
|
-
return
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1357
|
+
const wrapped = toAction(invoke, url);
|
|
1358
|
+
if (name) setFunctionName(wrapped, name);
|
|
1359
|
+
return wrapped;
|
|
1360
|
+
}
|
|
1361
|
+
const action = actionImpl;
|
|
1362
|
+
function toAction(invoke, url, boundArgs = [], base = url, submitHooks = new Map(), settledHooks = new Map()) {
|
|
1363
|
+
const fn = function (...args) {
|
|
1364
|
+
return invoke.call(this, [...boundArgs, ...args], fn);
|
|
1365
|
+
};
|
|
1343
1366
|
fn.toString = () => {
|
|
1344
1367
|
if (!url) throw new Error("Client Actions need explicit names if server rendered");
|
|
1345
1368
|
return url;
|
|
1346
1369
|
};
|
|
1347
1370
|
fn.with = function (...args) {
|
|
1348
|
-
const newFn = function (...passedArgs) {
|
|
1349
|
-
return fn.call(this, ...args, ...passedArgs);
|
|
1350
|
-
};
|
|
1351
|
-
newFn.base = fn.base;
|
|
1352
1371
|
const uri = new URL(url, mockBase);
|
|
1353
1372
|
uri.searchParams.set("args", hashKey(args));
|
|
1354
|
-
|
|
1373
|
+
const next = toAction(invoke, (uri.origin === "https://action" ? uri.origin : "") + uri.pathname + uri.search, [...boundArgs, ...args], base, submitHooks, settledHooks);
|
|
1374
|
+
return next;
|
|
1375
|
+
};
|
|
1376
|
+
fn.onSubmit = function (hook) {
|
|
1377
|
+
const id = Symbol("actionOnSubmitHook");
|
|
1378
|
+
submitHooks.set(id, hook);
|
|
1379
|
+
getOwner() && onCleanup(() => submitHooks.delete(id));
|
|
1380
|
+
return this;
|
|
1381
|
+
};
|
|
1382
|
+
fn.onSettled = function (hook) {
|
|
1383
|
+
const id = Symbol("actionOnSettledHook");
|
|
1384
|
+
settledHooks.set(id, hook);
|
|
1385
|
+
getOwner() && onCleanup(() => settledHooks.delete(id));
|
|
1386
|
+
return this;
|
|
1355
1387
|
};
|
|
1356
1388
|
fn.url = url;
|
|
1389
|
+
fn.base = base;
|
|
1390
|
+
fn[submitHooksSymbol] = submitHooks;
|
|
1391
|
+
fn[settledHooksSymbol] = settledHooks;
|
|
1392
|
+
fn[invokeSymbol] = invoke;
|
|
1357
1393
|
if (!isServer) {
|
|
1358
1394
|
actions.set(url, fn);
|
|
1359
1395
|
getOwner() && onCleanup(() => actions.delete(url));
|
|
@@ -1361,6 +1397,21 @@ function toAction(fn, url) {
|
|
|
1361
1397
|
return fn;
|
|
1362
1398
|
}
|
|
1363
1399
|
const hashString = s => s.split("").reduce((a, b) => (a << 5) - a + b.charCodeAt(0) | 0, 0);
|
|
1400
|
+
async function settleActionResult(result) {
|
|
1401
|
+
const value = result;
|
|
1402
|
+
if (value && typeof value.then === "function") {
|
|
1403
|
+
return result.then(value => value);
|
|
1404
|
+
}
|
|
1405
|
+
if (value && typeof value.next === "function") {
|
|
1406
|
+
const iterator = value;
|
|
1407
|
+
let next = await iterator.next();
|
|
1408
|
+
while (!next.done) {
|
|
1409
|
+
next = await iterator.next();
|
|
1410
|
+
}
|
|
1411
|
+
return next.value;
|
|
1412
|
+
}
|
|
1413
|
+
return result;
|
|
1414
|
+
}
|
|
1364
1415
|
async function handleResponse(response, error, navigate) {
|
|
1365
1416
|
let data;
|
|
1366
1417
|
let custom;
|
|
@@ -1669,12 +1720,21 @@ function MemoryRouter(props) {
|
|
|
1669
1720
|
}
|
|
1670
1721
|
|
|
1671
1722
|
var _tmpl$ = /*#__PURE__*/template(`<a>`);
|
|
1723
|
+
function toClassName(value) {
|
|
1724
|
+
if (!value) return "";
|
|
1725
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
1726
|
+
if (Array.isArray(value)) return value.map(toClassName).filter(Boolean).join(" ");
|
|
1727
|
+
if (typeof value === "object") {
|
|
1728
|
+
return Object.entries(value).filter(([, enabled]) => enabled).map(([name]) => name).join(" ");
|
|
1729
|
+
}
|
|
1730
|
+
return "";
|
|
1731
|
+
}
|
|
1672
1732
|
function A(props) {
|
|
1673
|
-
props =
|
|
1733
|
+
props = merge({
|
|
1674
1734
|
inactiveClass: "inactive",
|
|
1675
1735
|
activeClass: "active"
|
|
1676
1736
|
}, props);
|
|
1677
|
-
const
|
|
1737
|
+
const rest = omit(props, "href", "state", "class", "activeClass", "inactiveClass", "end");
|
|
1678
1738
|
const to = useResolvedPath(() => props.href);
|
|
1679
1739
|
const href = useHref(to);
|
|
1680
1740
|
const location = useLocation();
|
|
@@ -1685,26 +1745,20 @@ function A(props) {
|
|
|
1685
1745
|
const loc = decodeURI(normalizePath(location.pathname).toLowerCase());
|
|
1686
1746
|
return [props.end ? path === loc : loc.startsWith(path + "/") || loc === path, path === loc];
|
|
1687
1747
|
});
|
|
1748
|
+
const className = createMemo(() => [toClassName(props.class), isActive()[0] ? props.activeClass : props.inactiveClass].filter(Boolean).join(" "));
|
|
1688
1749
|
return (() => {
|
|
1689
1750
|
var _el$ = _tmpl$();
|
|
1690
|
-
spread(_el$, mergeProps
|
|
1751
|
+
spread(_el$, mergeProps(rest, {
|
|
1691
1752
|
get href() {
|
|
1692
1753
|
return href() || props.href;
|
|
1693
1754
|
},
|
|
1694
1755
|
get state() {
|
|
1695
1756
|
return JSON.stringify(props.state);
|
|
1696
1757
|
},
|
|
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
|
-
};
|
|
1758
|
+
get ["class"]() {
|
|
1759
|
+
return className();
|
|
1706
1760
|
},
|
|
1707
|
-
"link":
|
|
1761
|
+
"link": true,
|
|
1708
1762
|
get ["aria-current"]() {
|
|
1709
1763
|
return isActive()[1] ? "page" : undefined;
|
|
1710
1764
|
}
|
|
@@ -1730,99 +1784,6 @@ function Navigate(props) {
|
|
|
1730
1784
|
return null;
|
|
1731
1785
|
}
|
|
1732
1786
|
|
|
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
1787
|
function redirect(url, init = 302) {
|
|
1827
1788
|
let responseInit;
|
|
1828
1789
|
let revalidate;
|
|
@@ -1876,4 +1837,4 @@ function json(data, init = {}) {
|
|
|
1876
1837
|
return response;
|
|
1877
1838
|
}
|
|
1878
1839
|
|
|
1879
|
-
export { A, HashRouter, MemoryRouter, Navigate, Route, Router, RouterContextObj as RouterContext, StaticRouter, mergeSearchString as _mergeSearchString, action,
|
|
1840
|
+
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 };
|