@tanstack/history 1.130.12 → 1.132.0-alpha.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/dist/cjs/index.cjs +16 -26
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +16 -26
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -19,13 +19,12 @@ function createHistory(opts) {
|
|
|
19
19
|
navigateOpts,
|
|
20
20
|
...actionInfo
|
|
21
21
|
}) => {
|
|
22
|
-
|
|
23
|
-
const ignoreBlocker = (navigateOpts == null ? void 0 : navigateOpts.ignoreBlocker) ?? false;
|
|
22
|
+
const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false;
|
|
24
23
|
if (ignoreBlocker) {
|
|
25
24
|
task();
|
|
26
25
|
return;
|
|
27
26
|
}
|
|
28
|
-
const blockers =
|
|
27
|
+
const blockers = opts.getBlockers?.() ?? [];
|
|
29
28
|
const isPushOrReplace = actionInfo.type === "PUSH" || actionInfo.type === "REPLACE";
|
|
30
29
|
if (typeof document !== "undefined" && blockers.length && isPushOrReplace) {
|
|
31
30
|
for (const blocker of blockers) {
|
|
@@ -36,7 +35,7 @@ function createHistory(opts) {
|
|
|
36
35
|
action: actionInfo.type
|
|
37
36
|
});
|
|
38
37
|
if (isBlocked) {
|
|
39
|
-
|
|
38
|
+
opts.onBlocked?.();
|
|
40
39
|
return;
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -98,7 +97,7 @@ function createHistory(opts) {
|
|
|
98
97
|
back: (navigateOpts) => {
|
|
99
98
|
tryNavigation({
|
|
100
99
|
task: () => {
|
|
101
|
-
opts.back(
|
|
100
|
+
opts.back(navigateOpts?.ignoreBlocker ?? false);
|
|
102
101
|
handleIndexChange({ type: "BACK" });
|
|
103
102
|
},
|
|
104
103
|
navigateOpts,
|
|
@@ -108,7 +107,7 @@ function createHistory(opts) {
|
|
|
108
107
|
forward: (navigateOpts) => {
|
|
109
108
|
tryNavigation({
|
|
110
109
|
task: () => {
|
|
111
|
-
opts.forward(
|
|
110
|
+
opts.forward(navigateOpts?.ignoreBlocker ?? false);
|
|
112
111
|
handleIndexChange({ type: "FORWARD" });
|
|
113
112
|
},
|
|
114
113
|
navigateOpts,
|
|
@@ -118,25 +117,17 @@ function createHistory(opts) {
|
|
|
118
117
|
canGoBack: () => location.state[stateIndexKey] !== 0,
|
|
119
118
|
createHref: (str) => opts.createHref(str),
|
|
120
119
|
block: (blocker) => {
|
|
121
|
-
var _a;
|
|
122
120
|
if (!opts.setBlockers) return () => {
|
|
123
121
|
};
|
|
124
|
-
const blockers =
|
|
122
|
+
const blockers = opts.getBlockers?.() ?? [];
|
|
125
123
|
opts.setBlockers([...blockers, blocker]);
|
|
126
124
|
return () => {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
(_b = opts.setBlockers) == null ? void 0 : _b.call(opts, blockers2.filter((b) => b !== blocker));
|
|
125
|
+
const blockers2 = opts.getBlockers?.() ?? [];
|
|
126
|
+
opts.setBlockers?.(blockers2.filter((b) => b !== blocker));
|
|
130
127
|
};
|
|
131
128
|
},
|
|
132
|
-
flush: () =>
|
|
133
|
-
|
|
134
|
-
return (_a = opts.flush) == null ? void 0 : _a.call(opts);
|
|
135
|
-
},
|
|
136
|
-
destroy: () => {
|
|
137
|
-
var _a;
|
|
138
|
-
return (_a = opts.destroy) == null ? void 0 : _a.call(opts);
|
|
139
|
-
},
|
|
129
|
+
flush: () => opts.flush?.(),
|
|
130
|
+
destroy: () => opts.destroy?.(),
|
|
140
131
|
notify
|
|
141
132
|
};
|
|
142
133
|
}
|
|
@@ -154,19 +145,18 @@ function assignKeyAndIndex(index, state) {
|
|
|
154
145
|
};
|
|
155
146
|
}
|
|
156
147
|
function createBrowserHistory(opts) {
|
|
157
|
-
|
|
158
|
-
const win = (opts == null ? void 0 : opts.window) ?? (typeof document !== "undefined" ? window : void 0);
|
|
148
|
+
const win = opts?.window ?? (typeof document !== "undefined" ? window : void 0);
|
|
159
149
|
const originalPushState = win.history.pushState;
|
|
160
150
|
const originalReplaceState = win.history.replaceState;
|
|
161
151
|
let blockers = [];
|
|
162
152
|
const _getBlockers = () => blockers;
|
|
163
153
|
const _setBlockers = (newBlockers) => blockers = newBlockers;
|
|
164
|
-
const createHref =
|
|
165
|
-
const parseLocation =
|
|
154
|
+
const createHref = opts?.createHref ?? ((path) => path);
|
|
155
|
+
const parseLocation = opts?.parseLocation ?? (() => parseHref(
|
|
166
156
|
`${win.location.pathname}${win.location.search}${win.location.hash}`,
|
|
167
157
|
win.history.state
|
|
168
158
|
));
|
|
169
|
-
if (!
|
|
159
|
+
if (!win.history.state?.__TSR_key && !win.history.state?.key) {
|
|
170
160
|
const addedKey = createRandomKey();
|
|
171
161
|
win.history.replaceState(
|
|
172
162
|
{
|
|
@@ -211,7 +201,7 @@ function createBrowserHistory(opts) {
|
|
|
211
201
|
next = {
|
|
212
202
|
href,
|
|
213
203
|
state,
|
|
214
|
-
isPush:
|
|
204
|
+
isPush: next?.isPush || type === "push"
|
|
215
205
|
};
|
|
216
206
|
if (!scheduled) {
|
|
217
207
|
scheduled = Promise.resolve().then(() => flush());
|
|
@@ -341,7 +331,7 @@ function createBrowserHistory(opts) {
|
|
|
341
331
|
return history;
|
|
342
332
|
}
|
|
343
333
|
function createHashHistory(opts) {
|
|
344
|
-
const win =
|
|
334
|
+
const win = opts?.window ?? (typeof document !== "undefined" ? window : void 0);
|
|
345
335
|
return createBrowserHistory({
|
|
346
336
|
window: win,
|
|
347
337
|
parseLocation: () => {
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {} as HistoryState\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n })\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const hashIndex = href.indexOf('#')\n const searchIndex = href.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href,\n pathname: href.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : href.length,\n ),\n hash: hashIndex > -1 ? href.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex)\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["blockers","_a","index"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {} as HistoryState\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n })\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const hashIndex = href.indexOf('#')\n const searchIndex = href.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href,\n pathname: href.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : href.length,\n ),\n hash: hashIndex > -1 ? href.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex)\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["blockers","index"],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -17,13 +17,12 @@ function createHistory(opts) {
|
|
|
17
17
|
navigateOpts,
|
|
18
18
|
...actionInfo
|
|
19
19
|
}) => {
|
|
20
|
-
|
|
21
|
-
const ignoreBlocker = (navigateOpts == null ? void 0 : navigateOpts.ignoreBlocker) ?? false;
|
|
20
|
+
const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false;
|
|
22
21
|
if (ignoreBlocker) {
|
|
23
22
|
task();
|
|
24
23
|
return;
|
|
25
24
|
}
|
|
26
|
-
const blockers =
|
|
25
|
+
const blockers = opts.getBlockers?.() ?? [];
|
|
27
26
|
const isPushOrReplace = actionInfo.type === "PUSH" || actionInfo.type === "REPLACE";
|
|
28
27
|
if (typeof document !== "undefined" && blockers.length && isPushOrReplace) {
|
|
29
28
|
for (const blocker of blockers) {
|
|
@@ -34,7 +33,7 @@ function createHistory(opts) {
|
|
|
34
33
|
action: actionInfo.type
|
|
35
34
|
});
|
|
36
35
|
if (isBlocked) {
|
|
37
|
-
|
|
36
|
+
opts.onBlocked?.();
|
|
38
37
|
return;
|
|
39
38
|
}
|
|
40
39
|
}
|
|
@@ -96,7 +95,7 @@ function createHistory(opts) {
|
|
|
96
95
|
back: (navigateOpts) => {
|
|
97
96
|
tryNavigation({
|
|
98
97
|
task: () => {
|
|
99
|
-
opts.back(
|
|
98
|
+
opts.back(navigateOpts?.ignoreBlocker ?? false);
|
|
100
99
|
handleIndexChange({ type: "BACK" });
|
|
101
100
|
},
|
|
102
101
|
navigateOpts,
|
|
@@ -106,7 +105,7 @@ function createHistory(opts) {
|
|
|
106
105
|
forward: (navigateOpts) => {
|
|
107
106
|
tryNavigation({
|
|
108
107
|
task: () => {
|
|
109
|
-
opts.forward(
|
|
108
|
+
opts.forward(navigateOpts?.ignoreBlocker ?? false);
|
|
110
109
|
handleIndexChange({ type: "FORWARD" });
|
|
111
110
|
},
|
|
112
111
|
navigateOpts,
|
|
@@ -116,25 +115,17 @@ function createHistory(opts) {
|
|
|
116
115
|
canGoBack: () => location.state[stateIndexKey] !== 0,
|
|
117
116
|
createHref: (str) => opts.createHref(str),
|
|
118
117
|
block: (blocker) => {
|
|
119
|
-
var _a;
|
|
120
118
|
if (!opts.setBlockers) return () => {
|
|
121
119
|
};
|
|
122
|
-
const blockers =
|
|
120
|
+
const blockers = opts.getBlockers?.() ?? [];
|
|
123
121
|
opts.setBlockers([...blockers, blocker]);
|
|
124
122
|
return () => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
(_b = opts.setBlockers) == null ? void 0 : _b.call(opts, blockers2.filter((b) => b !== blocker));
|
|
123
|
+
const blockers2 = opts.getBlockers?.() ?? [];
|
|
124
|
+
opts.setBlockers?.(blockers2.filter((b) => b !== blocker));
|
|
128
125
|
};
|
|
129
126
|
},
|
|
130
|
-
flush: () =>
|
|
131
|
-
|
|
132
|
-
return (_a = opts.flush) == null ? void 0 : _a.call(opts);
|
|
133
|
-
},
|
|
134
|
-
destroy: () => {
|
|
135
|
-
var _a;
|
|
136
|
-
return (_a = opts.destroy) == null ? void 0 : _a.call(opts);
|
|
137
|
-
},
|
|
127
|
+
flush: () => opts.flush?.(),
|
|
128
|
+
destroy: () => opts.destroy?.(),
|
|
138
129
|
notify
|
|
139
130
|
};
|
|
140
131
|
}
|
|
@@ -152,19 +143,18 @@ function assignKeyAndIndex(index, state) {
|
|
|
152
143
|
};
|
|
153
144
|
}
|
|
154
145
|
function createBrowserHistory(opts) {
|
|
155
|
-
|
|
156
|
-
const win = (opts == null ? void 0 : opts.window) ?? (typeof document !== "undefined" ? window : void 0);
|
|
146
|
+
const win = opts?.window ?? (typeof document !== "undefined" ? window : void 0);
|
|
157
147
|
const originalPushState = win.history.pushState;
|
|
158
148
|
const originalReplaceState = win.history.replaceState;
|
|
159
149
|
let blockers = [];
|
|
160
150
|
const _getBlockers = () => blockers;
|
|
161
151
|
const _setBlockers = (newBlockers) => blockers = newBlockers;
|
|
162
|
-
const createHref =
|
|
163
|
-
const parseLocation =
|
|
152
|
+
const createHref = opts?.createHref ?? ((path) => path);
|
|
153
|
+
const parseLocation = opts?.parseLocation ?? (() => parseHref(
|
|
164
154
|
`${win.location.pathname}${win.location.search}${win.location.hash}`,
|
|
165
155
|
win.history.state
|
|
166
156
|
));
|
|
167
|
-
if (!
|
|
157
|
+
if (!win.history.state?.__TSR_key && !win.history.state?.key) {
|
|
168
158
|
const addedKey = createRandomKey();
|
|
169
159
|
win.history.replaceState(
|
|
170
160
|
{
|
|
@@ -209,7 +199,7 @@ function createBrowserHistory(opts) {
|
|
|
209
199
|
next = {
|
|
210
200
|
href,
|
|
211
201
|
state,
|
|
212
|
-
isPush:
|
|
202
|
+
isPush: next?.isPush || type === "push"
|
|
213
203
|
};
|
|
214
204
|
if (!scheduled) {
|
|
215
205
|
scheduled = Promise.resolve().then(() => flush());
|
|
@@ -339,7 +329,7 @@ function createBrowserHistory(opts) {
|
|
|
339
329
|
return history;
|
|
340
330
|
}
|
|
341
331
|
function createHashHistory(opts) {
|
|
342
|
-
const win =
|
|
332
|
+
const win = opts?.window ?? (typeof document !== "undefined" ? window : void 0);
|
|
343
333
|
return createBrowserHistory({
|
|
344
334
|
window: win,
|
|
345
335
|
parseLocation: () => {
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {} as HistoryState\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n })\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const hashIndex = href.indexOf('#')\n const searchIndex = href.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href,\n pathname: href.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : href.length,\n ),\n hash: hashIndex > -1 ? href.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex)\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["_a","blockers","index"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["// While the public API was clearly inspired by the \"history\" npm package,\n// This implementation attempts to be more lightweight by\n// making assumptions about the way TanStack Router works\n\nexport interface NavigateOptions {\n ignoreBlocker?: boolean\n}\n\ntype SubscriberHistoryAction =\n | {\n type: Exclude<HistoryAction, 'GO'>\n }\n | {\n type: 'GO'\n index: number\n }\n\ntype SubscriberArgs = {\n location: HistoryLocation\n action: SubscriberHistoryAction\n}\n\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: SubscriberArgs) => void>\n subscribe: (cb: (opts: SubscriberArgs) => void) => () => void\n push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void\n go: (index: number, navigateOpts?: NavigateOptions) => void\n back: (navigateOpts?: NavigateOptions) => void\n forward: (navigateOpts?: NavigateOptions) => void\n canGoBack: () => boolean\n createHref: (href: string) => string\n block: (blocker: NavigationBlocker) => () => void\n flush: () => void\n destroy: () => void\n notify: (action: SubscriberHistoryAction) => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: ParsedHistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {}\n\nexport type ParsedHistoryState = HistoryState & {\n key?: string // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key?: string\n __TSR_index: number\n}\n\ntype ShouldAllowNavigation = any\n\nexport type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO'\n\nexport type BlockerFnArgs = {\n currentLocation: HistoryLocation\n nextLocation: HistoryLocation\n action: HistoryAction\n}\n\nexport type BlockerFn = (\n args: BlockerFnArgs,\n) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation\n\nexport type NavigationBlocker = {\n blockerFn: BlockerFn\n enableBeforeUnload?: (() => boolean) | boolean\n}\n\ntype TryNavigateArgs = {\n task: () => void\n type: 'PUSH' | 'REPLACE' | 'BACK' | 'FORWARD' | 'GO'\n navigateOpts?: NavigateOptions\n} & (\n | {\n type: 'PUSH' | 'REPLACE'\n path: string\n state: any\n }\n | {\n type: 'BACK' | 'FORWARD' | 'GO'\n }\n)\n\nconst stateIndexKey = '__TSR_index'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nexport function createHistory(opts: {\n getLocation: () => HistoryLocation\n getLength: () => number\n pushState: (path: string, state: any) => void\n replaceState: (path: string, state: any) => void\n go: (n: number) => void\n back: (ignoreBlocker: boolean) => void\n forward: (ignoreBlocker: boolean) => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: () => void\n getBlockers?: () => Array<NavigationBlocker>\n setBlockers?: (blockers: Array<NavigationBlocker>) => void\n // Avoid notifying on forward/back/go, used for browser history as we already get notified by the popstate event\n notifyOnIndexChange?: boolean\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: SubscriberArgs) => void>()\n\n const notify = (action: SubscriberHistoryAction) => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location, action }))\n }\n\n const handleIndexChange = (action: SubscriberHistoryAction) => {\n if (opts.notifyOnIndexChange ?? true) notify(action)\n else location = opts.getLocation()\n }\n\n const tryNavigation = async ({\n task,\n navigateOpts,\n ...actionInfo\n }: TryNavigateArgs) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (ignoreBlocker) {\n task()\n return\n }\n\n const blockers = opts.getBlockers?.() ?? []\n const isPushOrReplace =\n actionInfo.type === 'PUSH' || actionInfo.type === 'REPLACE'\n if (typeof document !== 'undefined' && blockers.length && isPushOrReplace) {\n for (const blocker of blockers) {\n const nextLocation = parseHref(actionInfo.path, actionInfo.state)\n const isBlocked = await blocker.blockerFn({\n currentLocation: location,\n nextLocation,\n action: actionInfo.type,\n })\n if (isBlocked) {\n opts.onBlocked?.()\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n get length() {\n return opts.getLength()\n },\n subscribers,\n subscribe: (cb: (opts: SubscriberArgs) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex + 1, state)\n tryNavigation({\n task: () => {\n opts.pushState(path, state)\n notify({ type: 'PUSH' })\n },\n navigateOpts,\n type: 'PUSH',\n path,\n state,\n })\n },\n replace: (path, state, navigateOpts) => {\n const currentIndex = location.state[stateIndexKey]\n state = assignKeyAndIndex(currentIndex, state)\n tryNavigation({\n task: () => {\n opts.replaceState(path, state)\n notify({ type: 'REPLACE' })\n },\n navigateOpts,\n type: 'REPLACE',\n path,\n state,\n })\n },\n go: (index, navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.go(index)\n handleIndexChange({ type: 'GO', index })\n },\n navigateOpts,\n type: 'GO',\n })\n },\n back: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.back(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'BACK' })\n },\n navigateOpts,\n type: 'BACK',\n })\n },\n forward: (navigateOpts) => {\n tryNavigation({\n task: () => {\n opts.forward(navigateOpts?.ignoreBlocker ?? false)\n handleIndexChange({ type: 'FORWARD' })\n },\n navigateOpts,\n type: 'FORWARD',\n })\n },\n canGoBack: () => location.state[stateIndexKey] !== 0,\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n if (!opts.setBlockers) return () => {}\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers([...blockers, blocker])\n\n return () => {\n const blockers = opts.getBlockers?.() ?? []\n opts.setBlockers?.(blockers.filter((b) => b !== blocker))\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKeyAndIndex(index: number, state: HistoryState | undefined) {\n if (!state) {\n state = {} as HistoryState\n }\n const key = createRandomKey()\n return {\n ...state,\n key, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: key,\n [stateIndexKey]: index,\n } as ParsedHistoryState\n}\n\n/**\n * Creates a history object that can be used to interact with the browser's\n * navigation. This is a lightweight API wrapping the browser's native methods.\n * It is designed to work with TanStack Router, but could be used as a standalone API as well.\n * IMPORTANT: This API implements history throttling via a microtask to prevent\n * excessive calls to the history API. In some browsers, calling history.pushState or\n * history.replaceState in quick succession can cause the browser to ignore subsequent\n * calls. This API smooths out those differences and ensures that your application\n * state will *eventually* match the browser state. In most cases, this is not a problem,\n * but if you need to ensure that the browser state is up to date, you can use the\n * `history.flush` method to immediately flush all pending state changes to the browser URL.\n * @param opts\n * @param opts.getHref A function that returns the current href (path + search + hash)\n * @param opts.createHref A function that takes a path and returns a href (path + search + hash)\n * @returns A history instance\n */\nexport function createBrowserHistory(opts?: {\n parseLocation?: () => HistoryLocation\n createHref?: (path: string) => string\n window?: any\n}): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n\n const originalPushState = win.history.pushState\n const originalReplaceState = win.history.replaceState\n\n let blockers: Array<NavigationBlocker> = []\n const _getBlockers = () => blockers\n const _setBlockers = (newBlockers: Array<NavigationBlocker>) =>\n (blockers = newBlockers)\n\n const createHref = opts?.createHref ?? ((path) => path)\n const parseLocation =\n opts?.parseLocation ??\n (() =>\n parseHref(\n `${win.location.pathname}${win.location.search}${win.location.hash}`,\n win.history.state,\n ))\n\n // Ensure there is always a key to start\n if (!win.history.state?.__TSR_key && !win.history.state?.key) {\n const addedKey = createRandomKey()\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: addedKey, // TODO: Remove in v2 - use __TSR_key instead\n __TSR_key: addedKey,\n },\n '',\n )\n }\n\n let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\n\n let nextPopIsGo = false\n let ignoreNextPop = false\n let skipBlockerNextPop = false\n let ignoreNextBeforeUnload = false\n\n const getLocation = () => currentLocation\n\n let next:\n | undefined\n | {\n // This is the latest location that we were attempting to push/replace\n href: string\n // This is the latest state that we were attempting to push/replace\n state: any\n // This is the latest type that we were attempting to push/replace\n isPush: boolean\n }\n\n // We need to track the current scheduled update to prevent\n // multiple updates from being scheduled at the same time.\n let scheduled: Promise<void> | undefined\n\n // This function flushes the next update to the browser history\n const flush = () => {\n if (!next) {\n return\n }\n\n // We need to ignore any updates to the subscribers while we update the browser history\n history._ignoreSubscribers = true\n\n // Update the browser history\n ;(next.isPush ? win.history.pushState : win.history.replaceState)(\n next.state,\n '',\n next.href,\n )\n\n // Stop ignoring subscriber updates\n history._ignoreSubscribers = false\n\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n }\n\n // This function queues up a call to update the browser history\n const queueHistoryAction = (\n type: 'push' | 'replace',\n destHref: string,\n state: any,\n ) => {\n const href = createHref(destHref)\n\n if (!scheduled) {\n rollbackLocation = currentLocation\n }\n\n // Update the location in memory\n currentLocation = parseHref(destHref, state)\n\n // Keep track of the next location we need to flush to the URL\n next = {\n href,\n state,\n isPush: next?.isPush || type === 'push',\n }\n\n if (!scheduled) {\n // Schedule an update to the browser history\n scheduled = Promise.resolve().then(() => flush())\n }\n }\n\n // NOTE: this function can probably be removed\n const onPushPop = (type: 'PUSH' | 'REPLACE') => {\n currentLocation = parseLocation()\n history.notify({ type })\n }\n\n const onPushPopEvent = async () => {\n if (ignoreNextPop) {\n ignoreNextPop = false\n return\n }\n\n const nextLocation = parseLocation()\n const delta =\n nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey]\n const isForward = delta === 1\n const isBack = delta === -1\n const isGo = (!isForward && !isBack) || nextPopIsGo\n nextPopIsGo = false\n\n const action = isGo ? 'GO' : isBack ? 'BACK' : 'FORWARD'\n const notify: SubscriberHistoryAction = isGo\n ? {\n type: 'GO',\n index: delta,\n }\n : {\n type: isBack ? 'BACK' : 'FORWARD',\n }\n\n if (skipBlockerNextPop) {\n skipBlockerNextPop = false\n } else {\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const isBlocked = await blocker.blockerFn({\n currentLocation,\n nextLocation,\n action,\n })\n if (isBlocked) {\n ignoreNextPop = true\n win.history.go(1)\n history.notify(notify)\n return\n }\n }\n }\n }\n\n currentLocation = parseLocation()\n history.notify(notify)\n }\n\n const onBeforeUnload = (e: BeforeUnloadEvent) => {\n if (ignoreNextBeforeUnload) {\n ignoreNextBeforeUnload = false\n return\n }\n\n let shouldBlock = false\n\n // If one blocker has a non-disabled beforeUnload, we should block\n const blockers = _getBlockers()\n if (typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true\n if (shouldHaveBeforeUnload === true) {\n shouldBlock = true\n break\n }\n\n if (\n typeof shouldHaveBeforeUnload === 'function' &&\n shouldHaveBeforeUnload() === true\n ) {\n shouldBlock = true\n break\n }\n }\n }\n\n if (shouldBlock) {\n e.preventDefault()\n return (e.returnValue = '')\n }\n return\n }\n\n const history = createHistory({\n getLocation,\n getLength: () => win.history.length,\n pushState: (href, state) => queueHistoryAction('push', href, state),\n replaceState: (href, state) => queueHistoryAction('replace', href, state),\n back: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n return win.history.back()\n },\n forward: (ignoreBlocker) => {\n if (ignoreBlocker) skipBlockerNextPop = true\n ignoreNextBeforeUnload = true\n win.history.forward()\n },\n go: (n) => {\n nextPopIsGo = true\n win.history.go(n)\n },\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {\n capture: true,\n })\n win.removeEventListener(popStateEvent, onPushPopEvent)\n },\n onBlocked: () => {\n // If a navigation is blocked, we need to rollback the location\n // that we optimistically updated in memory.\n if (rollbackLocation && currentLocation !== rollbackLocation) {\n currentLocation = rollbackLocation\n }\n },\n getBlockers: _getBlockers,\n setBlockers: _setBlockers,\n notifyOnIndexChange: false,\n })\n\n win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true })\n win.addEventListener(popStateEvent, onPushPopEvent)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('PUSH')\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args as any)\n if (!history._ignoreSubscribers) onPushPop('REPLACE')\n return res\n }\n\n return history\n}\n\nexport function createHashHistory(opts?: { window?: any }): RouterHistory {\n const win =\n opts?.window ??\n (typeof document !== 'undefined' ? window : (undefined as any))\n return createBrowserHistory({\n window: win,\n parseLocation: () => {\n const hashSplit = win.location.hash.split('#').slice(1)\n const pathPart = hashSplit[0] ?? '/'\n const searchPart = win.location.search\n const hashEntries = hashSplit.slice(1)\n const hashPart =\n hashEntries.length === 0 ? '' : `#${hashEntries.join('#')}`\n const hashHref = `${pathPart}${searchPart}${hashPart}`\n return parseHref(hashHref, win.history.state)\n },\n createHref: (href) =>\n `${win.location.pathname}${win.location.search}#${href}`,\n })\n}\n\nexport function createMemoryHistory(\n opts: {\n initialEntries: Array<string>\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex\n ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)\n : entries.length - 1\n const states = entries.map((_entry, index) =>\n assignKeyAndIndex(index, undefined),\n )\n\n const getLocation = () => parseHref(entries[index]!, states[index])\n\n return createHistory({\n getLocation,\n getLength: () => entries.length,\n pushState: (path, state) => {\n // Removes all subsequent entries after the current index to start a new branch\n if (index < entries.length - 1) {\n entries.splice(index + 1)\n states.splice(index + 1)\n }\n states.push(state)\n entries.push(path)\n index = Math.max(entries.length - 1, 0)\n },\n replaceState: (path, state) => {\n states[index] = state\n entries[index] = path\n },\n back: () => {\n index = Math.max(index - 1, 0)\n },\n forward: () => {\n index = Math.min(index + 1, entries.length - 1)\n },\n go: (n) => {\n index = Math.min(Math.max(index + n, 0), entries.length - 1)\n },\n createHref: (path) => path,\n })\n}\n\nexport function parseHref(\n href: string,\n state: ParsedHistoryState | undefined,\n): HistoryLocation {\n const hashIndex = href.indexOf('#')\n const searchIndex = href.indexOf('?')\n\n const addedKey = createRandomKey()\n\n return {\n href,\n pathname: href.substring(\n 0,\n hashIndex > 0\n ? searchIndex > 0\n ? Math.min(hashIndex, searchIndex)\n : hashIndex\n : searchIndex > 0\n ? searchIndex\n : href.length,\n ),\n hash: hashIndex > -1 ? href.substring(hashIndex) : '',\n search:\n searchIndex > -1\n ? href.slice(searchIndex, hashIndex === -1 ? undefined : hashIndex)\n : '',\n state: state || { [stateIndexKey]: 0, key: addedKey, __TSR_key: addedKey },\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":["blockers","index"],"mappings":"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"}
|