tanstack-router-cache 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/cached-outlet.cjs +12 -0
- package/dist/components/cached-outlet.js +12 -0
- package/dist/components/off-screen-in.cjs +130 -0
- package/dist/components/off-screen-in.js +130 -0
- package/dist/components/off-screen.cjs +8 -0
- package/dist/components/off-screen.js +8 -0
- package/dist/components/restore-cached-href.cjs +28 -0
- package/dist/components/restore-cached-href.d.ts +0 -1
- package/dist/components/restore-cached-href.js +28 -0
- package/dist/components/route-cache-manager.cjs +485 -0
- package/dist/components/route-cache-manager.js +485 -0
- package/dist/components/router-cache-outlet.cjs +9 -0
- package/dist/components/router-cache-outlet.js +9 -0
- package/dist/contexts/router-cache.cjs +237 -0
- package/dist/contexts/router-cache.d.ts +40 -0
- package/dist/contexts/router-cache.js +235 -0
- package/dist/dom/dismiss-transient-ui.cjs +230 -0
- package/dist/dom/dismiss-transient-ui.js +228 -0
- package/dist/hooks/use-event-listener.cjs +76 -0
- package/dist/hooks/use-event-listener.js +76 -0
- package/dist/hooks/use-route-cache-active.cjs +19 -0
- package/dist/hooks/use-route-cache-active.js +19 -0
- package/dist/hooks/use-route-cache-activity.cjs +12 -0
- package/dist/hooks/use-route-cache-activity.js +12 -0
- package/dist/hooks/use-route-cache-effect.cjs +38 -0
- package/dist/hooks/use-route-cache-effect.js +38 -0
- package/dist/hooks/use-route-cache-error-boundary.cjs +23 -0
- package/dist/hooks/use-route-cache-error-boundary.js +23 -0
- package/dist/hooks/use-route-cache-navigation.cjs +36 -0
- package/dist/hooks/use-route-cache-navigation.js +36 -0
- package/dist/hooks/use-router-cache-debug.cjs +85 -0
- package/dist/hooks/use-router-cache-debug.js +85 -0
- package/dist/hooks/use-router-cache.cjs +32 -0
- package/dist/hooks/use-router-cache.js +32 -0
- package/dist/hooks/use-update.cjs +8 -0
- package/dist/hooks/use-update.js +8 -0
- package/dist/index.cjs +18 -1402
- package/dist/index.d.ts +9 -1
- package/dist/index.js +10 -1395
- package/dist/pathname.cjs +8 -0
- package/dist/pathname.js +8 -0
- package/dist/route-cache-static-data.cjs +43 -0
- package/dist/route-cache-static-data.d.ts +25 -0
- package/dist/route-cache-static-data.js +41 -0
- package/dist/types.d.ts +50 -0
- package/docs/architecture.md +8 -5
- package/docs/cache-behavior.md +17 -0
- package/docs/components.md +1 -2
- package/docs/getting-started.md +38 -3
- package/docs/releases.md +0 -9
- package/docs/types.md +12 -0
- package/package.json +4 -6
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
let _tanstack_react_router = require("@tanstack/react-router");
|
|
2
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
3
|
+
//#region src/components/cached-outlet.tsx
|
|
4
|
+
function CachedOutlet(props) {
|
|
5
|
+
const { matchId, routerSnapshot } = props;
|
|
6
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tanstack_react_router.RouterContextProvider, {
|
|
7
|
+
router: routerSnapshot,
|
|
8
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_tanstack_react_router.Match, { matchId })
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
exports.default = CachedOutlet;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Match, RouterContextProvider } from "@tanstack/react-router";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/cached-outlet.tsx
|
|
4
|
+
function CachedOutlet(props) {
|
|
5
|
+
const { matchId, routerSnapshot } = props;
|
|
6
|
+
return /* @__PURE__ */ jsx(RouterContextProvider, {
|
|
7
|
+
router: routerSnapshot,
|
|
8
|
+
children: /* @__PURE__ */ jsx(Match, { matchId })
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { CachedOutlet as default };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const require_dismiss_transient_ui = require("../dom/dismiss-transient-ui.cjs");
|
|
2
|
+
let react = require("react");
|
|
3
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
4
|
+
//#region src/components/off-screen-in.tsx
|
|
5
|
+
const windowScrollPositions = /* @__PURE__ */ new Map();
|
|
6
|
+
const IMMEDIATE_SCROLL_RESTORE_DELAY = 0;
|
|
7
|
+
const EARLY_SCROLL_RESTORE_DELAY = 80;
|
|
8
|
+
const MIDDLE_SCROLL_RESTORE_DELAY = 240;
|
|
9
|
+
const LATE_SCROLL_RESTORE_DELAY = 600;
|
|
10
|
+
const FINAL_SCROLL_RESTORE_DELAY = 1e3;
|
|
11
|
+
const SCROLL_TRACKING_INTERVAL_MS = 200;
|
|
12
|
+
const SCROLL_KEYS = /* @__PURE__ */ new Set([
|
|
13
|
+
" ",
|
|
14
|
+
"ArrowDown",
|
|
15
|
+
"ArrowLeft",
|
|
16
|
+
"ArrowRight",
|
|
17
|
+
"ArrowUp",
|
|
18
|
+
"End",
|
|
19
|
+
"Home",
|
|
20
|
+
"PageDown",
|
|
21
|
+
"PageUp"
|
|
22
|
+
]);
|
|
23
|
+
const SCROLL_RESTORE_DELAYS = [
|
|
24
|
+
IMMEDIATE_SCROLL_RESTORE_DELAY,
|
|
25
|
+
EARLY_SCROLL_RESTORE_DELAY,
|
|
26
|
+
MIDDLE_SCROLL_RESTORE_DELAY,
|
|
27
|
+
LATE_SCROLL_RESTORE_DELAY,
|
|
28
|
+
FINAL_SCROLL_RESTORE_DELAY
|
|
29
|
+
];
|
|
30
|
+
function OffScreenIn(props) {
|
|
31
|
+
const { mode, children, containerRef, pathname } = props;
|
|
32
|
+
const localContainerRef = (0, react.useRef)(null);
|
|
33
|
+
const attachContainerRef = (node) => {
|
|
34
|
+
localContainerRef.current = node;
|
|
35
|
+
if (containerRef) containerRef.current = node;
|
|
36
|
+
};
|
|
37
|
+
(0, react.useLayoutEffect)(() => {
|
|
38
|
+
if (typeof document === "undefined") return;
|
|
39
|
+
require_dismiss_transient_ui.initializeTransientUiTracking(document);
|
|
40
|
+
}, []);
|
|
41
|
+
(0, react.useLayoutEffect)(() => {
|
|
42
|
+
if (!pathname) return;
|
|
43
|
+
require_dismiss_transient_ui.syncTransientUiRouteActivity(pathname, mode);
|
|
44
|
+
}, [mode, pathname]);
|
|
45
|
+
(0, react.useLayoutEffect)(() => {
|
|
46
|
+
const visibleContainer = localContainerRef.current;
|
|
47
|
+
return () => {
|
|
48
|
+
if (!pathname || mode !== "visible") return;
|
|
49
|
+
require_dismiss_transient_ui.dismissTransientUi(visibleContainer, pathname);
|
|
50
|
+
};
|
|
51
|
+
}, [mode, pathname]);
|
|
52
|
+
(0, react.useLayoutEffect)(() => {
|
|
53
|
+
if (typeof globalThis === "undefined" || !pathname) return;
|
|
54
|
+
const saveScrollPosition = () => {
|
|
55
|
+
windowScrollPositions.set(pathname, {
|
|
56
|
+
x: globalThis.scrollX,
|
|
57
|
+
y: globalThis.scrollY
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
if (mode === "hidden") return;
|
|
61
|
+
const savedPosition = windowScrollPositions.get(pathname);
|
|
62
|
+
let userRequestedScroll = false;
|
|
63
|
+
let scrollTrackingIntervalId;
|
|
64
|
+
const startScrollTracking = () => {
|
|
65
|
+
scrollTrackingIntervalId ??= globalThis.setInterval(saveScrollPosition, SCROLL_TRACKING_INTERVAL_MS);
|
|
66
|
+
};
|
|
67
|
+
const handleScroll = () => {
|
|
68
|
+
if (!savedPosition || userRequestedScroll) saveScrollPosition();
|
|
69
|
+
};
|
|
70
|
+
const markUserRequestedScroll = () => {
|
|
71
|
+
userRequestedScroll = true;
|
|
72
|
+
};
|
|
73
|
+
const handleKeyDown = (event) => {
|
|
74
|
+
if (SCROLL_KEYS.has(event.key)) markUserRequestedScroll();
|
|
75
|
+
};
|
|
76
|
+
globalThis.addEventListener("scroll", handleScroll, { passive: true });
|
|
77
|
+
globalThis.addEventListener("wheel", markUserRequestedScroll, { passive: true });
|
|
78
|
+
globalThis.addEventListener("touchstart", markUserRequestedScroll, { passive: true });
|
|
79
|
+
globalThis.addEventListener("pointerdown", markUserRequestedScroll, { passive: true });
|
|
80
|
+
globalThis.addEventListener("keydown", handleKeyDown);
|
|
81
|
+
if (!savedPosition) {
|
|
82
|
+
startScrollTracking();
|
|
83
|
+
saveScrollPosition();
|
|
84
|
+
return () => {
|
|
85
|
+
if (scrollTrackingIntervalId !== void 0) globalThis.clearInterval(scrollTrackingIntervalId);
|
|
86
|
+
globalThis.removeEventListener("scroll", handleScroll);
|
|
87
|
+
globalThis.removeEventListener("wheel", markUserRequestedScroll);
|
|
88
|
+
globalThis.removeEventListener("touchstart", markUserRequestedScroll);
|
|
89
|
+
globalThis.removeEventListener("pointerdown", markUserRequestedScroll);
|
|
90
|
+
globalThis.removeEventListener("keydown", handleKeyDown);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const restoreScrollPosition = () => {
|
|
94
|
+
if (userRequestedScroll) return;
|
|
95
|
+
globalThis.scrollTo(savedPosition.x, savedPosition.y);
|
|
96
|
+
saveScrollPosition();
|
|
97
|
+
startScrollTracking();
|
|
98
|
+
};
|
|
99
|
+
const timeoutIds = [];
|
|
100
|
+
let rafId = globalThis.requestAnimationFrame(() => {
|
|
101
|
+
rafId = globalThis.requestAnimationFrame(() => {
|
|
102
|
+
restoreScrollPosition();
|
|
103
|
+
for (const delay of SCROLL_RESTORE_DELAYS) timeoutIds.push(globalThis.setTimeout(restoreScrollPosition, delay));
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
return () => {
|
|
107
|
+
globalThis.cancelAnimationFrame(rafId);
|
|
108
|
+
for (const timeoutId of timeoutIds) globalThis.clearTimeout(timeoutId);
|
|
109
|
+
if (scrollTrackingIntervalId !== void 0) globalThis.clearInterval(scrollTrackingIntervalId);
|
|
110
|
+
globalThis.removeEventListener("scroll", handleScroll);
|
|
111
|
+
globalThis.removeEventListener("wheel", markUserRequestedScroll);
|
|
112
|
+
globalThis.removeEventListener("touchstart", markUserRequestedScroll);
|
|
113
|
+
globalThis.removeEventListener("pointerdown", markUserRequestedScroll);
|
|
114
|
+
globalThis.removeEventListener("keydown", handleKeyDown);
|
|
115
|
+
};
|
|
116
|
+
}, [mode, pathname]);
|
|
117
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Activity, {
|
|
118
|
+
mode,
|
|
119
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
120
|
+
className: "flex min-h-full w-full flex-1 flex-col",
|
|
121
|
+
"data-router-cache-container": "true",
|
|
122
|
+
"data-router-cache-mode": mode,
|
|
123
|
+
"data-router-cache-pathname": pathname,
|
|
124
|
+
ref: attachContainerRef,
|
|
125
|
+
children
|
|
126
|
+
})
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
exports.default = OffScreenIn;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { dismissTransientUi, initializeTransientUiTracking, syncTransientUiRouteActivity } from "../dom/dismiss-transient-ui.js";
|
|
2
|
+
import { Activity, useLayoutEffect, useRef } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/off-screen-in.tsx
|
|
5
|
+
const windowScrollPositions = /* @__PURE__ */ new Map();
|
|
6
|
+
const IMMEDIATE_SCROLL_RESTORE_DELAY = 0;
|
|
7
|
+
const EARLY_SCROLL_RESTORE_DELAY = 80;
|
|
8
|
+
const MIDDLE_SCROLL_RESTORE_DELAY = 240;
|
|
9
|
+
const LATE_SCROLL_RESTORE_DELAY = 600;
|
|
10
|
+
const FINAL_SCROLL_RESTORE_DELAY = 1e3;
|
|
11
|
+
const SCROLL_TRACKING_INTERVAL_MS = 200;
|
|
12
|
+
const SCROLL_KEYS = /* @__PURE__ */ new Set([
|
|
13
|
+
" ",
|
|
14
|
+
"ArrowDown",
|
|
15
|
+
"ArrowLeft",
|
|
16
|
+
"ArrowRight",
|
|
17
|
+
"ArrowUp",
|
|
18
|
+
"End",
|
|
19
|
+
"Home",
|
|
20
|
+
"PageDown",
|
|
21
|
+
"PageUp"
|
|
22
|
+
]);
|
|
23
|
+
const SCROLL_RESTORE_DELAYS = [
|
|
24
|
+
IMMEDIATE_SCROLL_RESTORE_DELAY,
|
|
25
|
+
EARLY_SCROLL_RESTORE_DELAY,
|
|
26
|
+
MIDDLE_SCROLL_RESTORE_DELAY,
|
|
27
|
+
LATE_SCROLL_RESTORE_DELAY,
|
|
28
|
+
FINAL_SCROLL_RESTORE_DELAY
|
|
29
|
+
];
|
|
30
|
+
function OffScreenIn(props) {
|
|
31
|
+
const { mode, children, containerRef, pathname } = props;
|
|
32
|
+
const localContainerRef = useRef(null);
|
|
33
|
+
const attachContainerRef = (node) => {
|
|
34
|
+
localContainerRef.current = node;
|
|
35
|
+
if (containerRef) containerRef.current = node;
|
|
36
|
+
};
|
|
37
|
+
useLayoutEffect(() => {
|
|
38
|
+
if (typeof document === "undefined") return;
|
|
39
|
+
initializeTransientUiTracking(document);
|
|
40
|
+
}, []);
|
|
41
|
+
useLayoutEffect(() => {
|
|
42
|
+
if (!pathname) return;
|
|
43
|
+
syncTransientUiRouteActivity(pathname, mode);
|
|
44
|
+
}, [mode, pathname]);
|
|
45
|
+
useLayoutEffect(() => {
|
|
46
|
+
const visibleContainer = localContainerRef.current;
|
|
47
|
+
return () => {
|
|
48
|
+
if (!pathname || mode !== "visible") return;
|
|
49
|
+
dismissTransientUi(visibleContainer, pathname);
|
|
50
|
+
};
|
|
51
|
+
}, [mode, pathname]);
|
|
52
|
+
useLayoutEffect(() => {
|
|
53
|
+
if (typeof globalThis === "undefined" || !pathname) return;
|
|
54
|
+
const saveScrollPosition = () => {
|
|
55
|
+
windowScrollPositions.set(pathname, {
|
|
56
|
+
x: globalThis.scrollX,
|
|
57
|
+
y: globalThis.scrollY
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
if (mode === "hidden") return;
|
|
61
|
+
const savedPosition = windowScrollPositions.get(pathname);
|
|
62
|
+
let userRequestedScroll = false;
|
|
63
|
+
let scrollTrackingIntervalId;
|
|
64
|
+
const startScrollTracking = () => {
|
|
65
|
+
scrollTrackingIntervalId ??= globalThis.setInterval(saveScrollPosition, SCROLL_TRACKING_INTERVAL_MS);
|
|
66
|
+
};
|
|
67
|
+
const handleScroll = () => {
|
|
68
|
+
if (!savedPosition || userRequestedScroll) saveScrollPosition();
|
|
69
|
+
};
|
|
70
|
+
const markUserRequestedScroll = () => {
|
|
71
|
+
userRequestedScroll = true;
|
|
72
|
+
};
|
|
73
|
+
const handleKeyDown = (event) => {
|
|
74
|
+
if (SCROLL_KEYS.has(event.key)) markUserRequestedScroll();
|
|
75
|
+
};
|
|
76
|
+
globalThis.addEventListener("scroll", handleScroll, { passive: true });
|
|
77
|
+
globalThis.addEventListener("wheel", markUserRequestedScroll, { passive: true });
|
|
78
|
+
globalThis.addEventListener("touchstart", markUserRequestedScroll, { passive: true });
|
|
79
|
+
globalThis.addEventListener("pointerdown", markUserRequestedScroll, { passive: true });
|
|
80
|
+
globalThis.addEventListener("keydown", handleKeyDown);
|
|
81
|
+
if (!savedPosition) {
|
|
82
|
+
startScrollTracking();
|
|
83
|
+
saveScrollPosition();
|
|
84
|
+
return () => {
|
|
85
|
+
if (scrollTrackingIntervalId !== void 0) globalThis.clearInterval(scrollTrackingIntervalId);
|
|
86
|
+
globalThis.removeEventListener("scroll", handleScroll);
|
|
87
|
+
globalThis.removeEventListener("wheel", markUserRequestedScroll);
|
|
88
|
+
globalThis.removeEventListener("touchstart", markUserRequestedScroll);
|
|
89
|
+
globalThis.removeEventListener("pointerdown", markUserRequestedScroll);
|
|
90
|
+
globalThis.removeEventListener("keydown", handleKeyDown);
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
const restoreScrollPosition = () => {
|
|
94
|
+
if (userRequestedScroll) return;
|
|
95
|
+
globalThis.scrollTo(savedPosition.x, savedPosition.y);
|
|
96
|
+
saveScrollPosition();
|
|
97
|
+
startScrollTracking();
|
|
98
|
+
};
|
|
99
|
+
const timeoutIds = [];
|
|
100
|
+
let rafId = globalThis.requestAnimationFrame(() => {
|
|
101
|
+
rafId = globalThis.requestAnimationFrame(() => {
|
|
102
|
+
restoreScrollPosition();
|
|
103
|
+
for (const delay of SCROLL_RESTORE_DELAYS) timeoutIds.push(globalThis.setTimeout(restoreScrollPosition, delay));
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
return () => {
|
|
107
|
+
globalThis.cancelAnimationFrame(rafId);
|
|
108
|
+
for (const timeoutId of timeoutIds) globalThis.clearTimeout(timeoutId);
|
|
109
|
+
if (scrollTrackingIntervalId !== void 0) globalThis.clearInterval(scrollTrackingIntervalId);
|
|
110
|
+
globalThis.removeEventListener("scroll", handleScroll);
|
|
111
|
+
globalThis.removeEventListener("wheel", markUserRequestedScroll);
|
|
112
|
+
globalThis.removeEventListener("touchstart", markUserRequestedScroll);
|
|
113
|
+
globalThis.removeEventListener("pointerdown", markUserRequestedScroll);
|
|
114
|
+
globalThis.removeEventListener("keydown", handleKeyDown);
|
|
115
|
+
};
|
|
116
|
+
}, [mode, pathname]);
|
|
117
|
+
return /* @__PURE__ */ jsx(Activity, {
|
|
118
|
+
mode,
|
|
119
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
120
|
+
className: "flex min-h-full w-full flex-1 flex-col",
|
|
121
|
+
"data-router-cache-container": "true",
|
|
122
|
+
"data-router-cache-mode": mode,
|
|
123
|
+
"data-router-cache-pathname": pathname,
|
|
124
|
+
ref: attachContainerRef,
|
|
125
|
+
children
|
|
126
|
+
})
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
export { OffScreenIn as default };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const require_off_screen_in = require("./off-screen-in.cjs");
|
|
2
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
3
|
+
//#region src/components/off-screen.tsx
|
|
4
|
+
function OffScreen(props) {
|
|
5
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_off_screen_in.default, { ...props });
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
exports.default = OffScreen;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import OffScreenIn from "./off-screen-in.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/off-screen.tsx
|
|
4
|
+
function OffScreen(props) {
|
|
5
|
+
return /* @__PURE__ */ jsx(OffScreenIn, { ...props });
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { OffScreen as default };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/components/restore-cached-href.ts
|
|
2
|
+
const FALLBACK_ORIGIN = "http://tanstack-router-cache.local";
|
|
3
|
+
function parseHref(href) {
|
|
4
|
+
try {
|
|
5
|
+
const url = new URL(href, FALLBACK_ORIGIN);
|
|
6
|
+
return {
|
|
7
|
+
hasHash: url.hash.length > 0,
|
|
8
|
+
hasSearch: url.search.length > 0,
|
|
9
|
+
pathname: url.pathname
|
|
10
|
+
};
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function isBareRouteHref(href, currentPathname) {
|
|
16
|
+
const candidateHref = href ?? currentPathname;
|
|
17
|
+
const parsedHref = parseHref(candidateHref);
|
|
18
|
+
if (!parsedHref) return candidateHref === currentPathname;
|
|
19
|
+
return parsedHref.pathname === currentPathname && !parsedHref.hasSearch && !parsedHref.hasHash;
|
|
20
|
+
}
|
|
21
|
+
function shouldRestoreCachedHref({ cachedHref, currentHref, currentPathname, isRouteCacheEnabled, previousPathname }) {
|
|
22
|
+
if (!(isRouteCacheEnabled && cachedHref)) return false;
|
|
23
|
+
if (!previousPathname || previousPathname === currentPathname) return false;
|
|
24
|
+
if (!isBareRouteHref(currentHref, currentPathname)) return false;
|
|
25
|
+
return cachedHref !== (currentHref ?? currentPathname);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
exports.shouldRestoreCachedHref = shouldRestoreCachedHref;
|
|
@@ -5,6 +5,5 @@ type RestoreCachedHrefInput = {
|
|
|
5
5
|
isRouteCacheEnabled?: boolean;
|
|
6
6
|
previousPathname?: string;
|
|
7
7
|
};
|
|
8
|
-
export declare function isBareRouteHref(href: string | undefined, currentPathname: string): boolean;
|
|
9
8
|
export declare function shouldRestoreCachedHref({ cachedHref, currentHref, currentPathname, isRouteCacheEnabled, previousPathname, }: RestoreCachedHrefInput): boolean;
|
|
10
9
|
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/components/restore-cached-href.ts
|
|
2
|
+
const FALLBACK_ORIGIN = "http://tanstack-router-cache.local";
|
|
3
|
+
function parseHref(href) {
|
|
4
|
+
try {
|
|
5
|
+
const url = new URL(href, FALLBACK_ORIGIN);
|
|
6
|
+
return {
|
|
7
|
+
hasHash: url.hash.length > 0,
|
|
8
|
+
hasSearch: url.search.length > 0,
|
|
9
|
+
pathname: url.pathname
|
|
10
|
+
};
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function isBareRouteHref(href, currentPathname) {
|
|
16
|
+
const candidateHref = href ?? currentPathname;
|
|
17
|
+
const parsedHref = parseHref(candidateHref);
|
|
18
|
+
if (!parsedHref) return candidateHref === currentPathname;
|
|
19
|
+
return parsedHref.pathname === currentPathname && !parsedHref.hasSearch && !parsedHref.hasHash;
|
|
20
|
+
}
|
|
21
|
+
function shouldRestoreCachedHref({ cachedHref, currentHref, currentPathname, isRouteCacheEnabled, previousPathname }) {
|
|
22
|
+
if (!(isRouteCacheEnabled && cachedHref)) return false;
|
|
23
|
+
if (!previousPathname || previousPathname === currentPathname) return false;
|
|
24
|
+
if (!isBareRouteHref(currentHref, currentPathname)) return false;
|
|
25
|
+
return cachedHref !== (currentHref ?? currentPathname);
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { shouldRestoreCachedHref };
|