@tanstack/history 1.87.6 → 1.95.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.
@@ -1,33 +1,42 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const pushStateEvent = "pushstate";
3
+ const stateIndexKey = "__TSR_index";
4
4
  const popStateEvent = "popstate";
5
5
  const beforeUnloadEvent = "beforeunload";
6
- const beforeUnloadListener = (event) => {
7
- event.preventDefault();
8
- return event.returnValue = "";
9
- };
10
- const stopBlocking = () => {
11
- removeEventListener(beforeUnloadEvent, beforeUnloadListener, {
12
- capture: true
13
- });
14
- };
15
6
  function createHistory(opts) {
16
7
  let location = opts.getLocation();
17
8
  const subscribers = /* @__PURE__ */ new Set();
18
- let blockers = [];
19
- const notify = () => {
9
+ const notify = (action) => {
20
10
  location = opts.getLocation();
21
- subscribers.forEach((subscriber) => subscriber({ location }));
11
+ subscribers.forEach((subscriber) => subscriber({ location, action }));
12
+ };
13
+ const handleIndexChange = (action) => {
14
+ if (opts.notifyOnIndexChange ?? true) notify(action);
15
+ else location = opts.getLocation();
22
16
  };
23
- const tryNavigation = async (task, navigateOpts) => {
24
- var _a;
17
+ const tryNavigation = async ({
18
+ task,
19
+ navigateOpts,
20
+ ...actionInfo
21
+ }) => {
22
+ var _a, _b;
25
23
  const ignoreBlocker = (navigateOpts == null ? void 0 : navigateOpts.ignoreBlocker) ?? false;
26
- if (!ignoreBlocker && typeof document !== "undefined" && blockers.length) {
24
+ if (ignoreBlocker) {
25
+ task();
26
+ return;
27
+ }
28
+ const blockers = ((_a = opts.getBlockers) == null ? void 0 : _a.call(opts)) ?? [];
29
+ const isPushOrReplace = actionInfo.type === "PUSH" || actionInfo.type === "REPLACE";
30
+ if (typeof document !== "undefined" && blockers.length && isPushOrReplace) {
27
31
  for (const blocker of blockers) {
28
- const allowed = await blocker();
29
- if (!allowed) {
30
- (_a = opts.onBlocked) == null ? void 0 : _a.call(opts, notify);
32
+ const nextLocation = parseHref(actionInfo.path, actionInfo.state);
33
+ const isBlocked = await blocker.blockerFn({
34
+ currentLocation: location,
35
+ nextLocation,
36
+ action: actionInfo.type
37
+ });
38
+ if (isBlocked) {
39
+ (_b = opts.onBlocked) == null ? void 0 : _b.call(opts);
31
40
  return;
32
41
  }
33
42
  }
@@ -49,50 +58,75 @@ function createHistory(opts) {
49
58
  };
50
59
  },
51
60
  push: (path, state, navigateOpts) => {
52
- state = assignKey(state);
53
- tryNavigation(() => {
54
- opts.pushState(path, state);
55
- notify();
56
- }, navigateOpts);
61
+ const currentIndex = location.state[stateIndexKey];
62
+ state = assignKeyAndIndex(currentIndex + 1, state);
63
+ tryNavigation({
64
+ task: () => {
65
+ opts.pushState(path, state);
66
+ notify({ type: "PUSH" });
67
+ },
68
+ navigateOpts,
69
+ type: "PUSH",
70
+ path,
71
+ state
72
+ });
57
73
  },
58
74
  replace: (path, state, navigateOpts) => {
59
- state = assignKey(state);
60
- tryNavigation(() => {
61
- opts.replaceState(path, state);
62
- notify();
63
- }, navigateOpts);
75
+ const currentIndex = location.state[stateIndexKey];
76
+ state = assignKeyAndIndex(currentIndex, state);
77
+ tryNavigation({
78
+ task: () => {
79
+ opts.replaceState(path, state);
80
+ notify({ type: "REPLACE" });
81
+ },
82
+ navigateOpts,
83
+ type: "REPLACE",
84
+ path,
85
+ state
86
+ });
64
87
  },
65
88
  go: (index, navigateOpts) => {
66
- tryNavigation(() => {
67
- opts.go(index);
68
- notify();
69
- }, navigateOpts);
89
+ tryNavigation({
90
+ task: () => {
91
+ opts.go(index);
92
+ handleIndexChange({ type: "GO", index });
93
+ },
94
+ navigateOpts,
95
+ type: "GO"
96
+ });
70
97
  },
71
98
  back: (navigateOpts) => {
72
- tryNavigation(() => {
73
- opts.back();
74
- notify();
75
- }, navigateOpts);
99
+ tryNavigation({
100
+ task: () => {
101
+ opts.back((navigateOpts == null ? void 0 : navigateOpts.ignoreBlocker) ?? false);
102
+ handleIndexChange({ type: "BACK" });
103
+ },
104
+ navigateOpts,
105
+ type: "BACK"
106
+ });
76
107
  },
77
108
  forward: (navigateOpts) => {
78
- tryNavigation(() => {
79
- opts.forward();
80
- notify();
81
- }, navigateOpts);
109
+ tryNavigation({
110
+ task: () => {
111
+ opts.forward((navigateOpts == null ? void 0 : navigateOpts.ignoreBlocker) ?? false);
112
+ handleIndexChange({ type: "FORWARD" });
113
+ },
114
+ navigateOpts,
115
+ type: "FORWARD"
116
+ });
82
117
  },
118
+ canGoBack: () => location.state[stateIndexKey] !== 0,
83
119
  createHref: (str) => opts.createHref(str),
84
120
  block: (blocker) => {
85
- blockers.push(blocker);
86
- if (blockers.length === 1) {
87
- addEventListener(beforeUnloadEvent, beforeUnloadListener, {
88
- capture: true
89
- });
90
- }
121
+ var _a;
122
+ if (!opts.setBlockers) return () => {
123
+ };
124
+ const blockers = ((_a = opts.getBlockers) == null ? void 0 : _a.call(opts)) ?? [];
125
+ opts.setBlockers([...blockers, blocker]);
91
126
  return () => {
92
- blockers = blockers.filter((b) => b !== blocker);
93
- if (!blockers.length) {
94
- stopBlocking();
95
- }
127
+ var _a2, _b;
128
+ const blockers2 = ((_a2 = opts.getBlockers) == null ? void 0 : _a2.call(opts)) ?? [];
129
+ (_b = opts.setBlockers) == null ? void 0 : _b.call(opts, blockers2.filter((b) => b !== blocker));
96
130
  };
97
131
  },
98
132
  flush: () => {
@@ -106,19 +140,23 @@ function createHistory(opts) {
106
140
  notify
107
141
  };
108
142
  }
109
- function assignKey(state) {
143
+ function assignKeyAndIndex(index, state) {
110
144
  if (!state) {
111
145
  state = {};
112
146
  }
113
147
  return {
114
148
  ...state,
115
- key: createRandomKey()
149
+ key: createRandomKey(),
150
+ [stateIndexKey]: index
116
151
  };
117
152
  }
118
153
  function createBrowserHistory(opts) {
119
154
  const win = (opts == null ? void 0 : opts.window) ?? (typeof document !== "undefined" ? window : void 0);
120
155
  const originalPushState = win.history.pushState;
121
156
  const originalReplaceState = win.history.replaceState;
157
+ let blockers = [];
158
+ const _getBlockers = () => blockers;
159
+ const _setBlockers = (newBlockers) => blockers = newBlockers;
122
160
  const createHref = (opts == null ? void 0 : opts.createHref) ?? ((path) => path);
123
161
  const parseLocation = (opts == null ? void 0 : opts.parseLocation) ?? (() => parseHref(
124
162
  `${win.location.pathname}${win.location.search}${win.location.hash}`,
@@ -126,6 +164,10 @@ function createBrowserHistory(opts) {
126
164
  ));
127
165
  let currentLocation = parseLocation();
128
166
  let rollbackLocation;
167
+ let nextPopIsGo = false;
168
+ let ignoreNextPop = false;
169
+ let skipBlockerNextPop = false;
170
+ let ignoreNextBeforeUnload = false;
129
171
  const getLocation = () => currentLocation;
130
172
  let next;
131
173
  let scheduled;
@@ -159,43 +201,125 @@ function createBrowserHistory(opts) {
159
201
  scheduled = Promise.resolve().then(() => flush());
160
202
  }
161
203
  };
162
- const onPushPop = () => {
204
+ const onPushPop = (type) => {
205
+ currentLocation = parseLocation();
206
+ history.notify({ type });
207
+ };
208
+ const onPushPopEvent = async () => {
209
+ if (ignoreNextPop) {
210
+ ignoreNextPop = false;
211
+ return;
212
+ }
213
+ const nextLocation = parseLocation();
214
+ const delta = nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey];
215
+ const isForward = delta === 1;
216
+ const isBack = delta === -1;
217
+ const isGo = !isForward && !isBack || nextPopIsGo;
218
+ nextPopIsGo = false;
219
+ const action = isGo ? "GO" : isBack ? "BACK" : "FORWARD";
220
+ const notify = isGo ? {
221
+ type: "GO",
222
+ index: delta
223
+ } : {
224
+ type: isBack ? "BACK" : "FORWARD"
225
+ };
226
+ if (skipBlockerNextPop) {
227
+ skipBlockerNextPop = false;
228
+ } else {
229
+ const blockers2 = _getBlockers();
230
+ if (typeof document !== "undefined" && blockers2.length) {
231
+ for (const blocker of blockers2) {
232
+ const isBlocked = await blocker.blockerFn({
233
+ currentLocation,
234
+ nextLocation,
235
+ action
236
+ });
237
+ if (isBlocked) {
238
+ ignoreNextPop = true;
239
+ win.history.go(1);
240
+ history.notify(notify);
241
+ return;
242
+ }
243
+ }
244
+ }
245
+ }
163
246
  currentLocation = parseLocation();
164
- history.notify();
247
+ history.notify(notify);
248
+ };
249
+ const onBeforeUnload = (e) => {
250
+ if (ignoreNextBeforeUnload) {
251
+ ignoreNextBeforeUnload = false;
252
+ return;
253
+ }
254
+ let shouldBlock = false;
255
+ const blockers2 = _getBlockers();
256
+ if (typeof document !== "undefined" && blockers2.length) {
257
+ for (const blocker of blockers2) {
258
+ const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true;
259
+ if (shouldHaveBeforeUnload === true) {
260
+ shouldBlock = true;
261
+ break;
262
+ }
263
+ if (typeof shouldHaveBeforeUnload === "function" && shouldHaveBeforeUnload() === true) {
264
+ shouldBlock = true;
265
+ break;
266
+ }
267
+ }
268
+ }
269
+ if (shouldBlock) {
270
+ e.preventDefault();
271
+ return e.returnValue = "";
272
+ }
273
+ return;
165
274
  };
166
275
  const history = createHistory({
167
276
  getLocation,
168
277
  getLength: () => win.history.length,
169
278
  pushState: (href, state) => queueHistoryAction("push", href, state),
170
279
  replaceState: (href, state) => queueHistoryAction("replace", href, state),
171
- back: () => win.history.back(),
172
- forward: () => win.history.forward(),
173
- go: (n) => win.history.go(n),
280
+ back: (ignoreBlocker) => {
281
+ if (ignoreBlocker) skipBlockerNextPop = true;
282
+ ignoreNextBeforeUnload = true;
283
+ return win.history.back();
284
+ },
285
+ forward: (ignoreBlocker) => {
286
+ if (ignoreBlocker) skipBlockerNextPop = true;
287
+ ignoreNextBeforeUnload = true;
288
+ win.history.forward();
289
+ },
290
+ go: (n) => {
291
+ nextPopIsGo = true;
292
+ win.history.go(n);
293
+ },
174
294
  createHref: (href) => createHref(href),
175
295
  flush,
176
296
  destroy: () => {
177
297
  win.history.pushState = originalPushState;
178
298
  win.history.replaceState = originalReplaceState;
179
- win.removeEventListener(pushStateEvent, onPushPop);
180
- win.removeEventListener(popStateEvent, onPushPop);
299
+ win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {
300
+ capture: true
301
+ });
302
+ win.removeEventListener(popStateEvent, onPushPopEvent);
181
303
  },
182
- onBlocked: (onUpdate) => {
304
+ onBlocked: () => {
183
305
  if (rollbackLocation && currentLocation !== rollbackLocation) {
184
306
  currentLocation = rollbackLocation;
185
- onUpdate();
186
307
  }
187
- }
308
+ },
309
+ getBlockers: _getBlockers,
310
+ setBlockers: _setBlockers,
311
+ notifyOnIndexChange: false
188
312
  });
189
- win.addEventListener(pushStateEvent, onPushPop);
190
- win.addEventListener(popStateEvent, onPushPop);
313
+ win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true });
314
+ win.addEventListener(popStateEvent, onPushPopEvent);
191
315
  win.history.pushState = function(...args) {
192
316
  const res = originalPushState.apply(win.history, args);
193
- if (!history._ignoreSubscribers) onPushPop();
317
+ if (!history._ignoreSubscribers) onPushPop("PUSH");
194
318
  return res;
195
319
  };
196
320
  win.history.replaceState = function(...args) {
197
321
  const res = originalReplaceState.apply(win.history, args);
198
- if (!history._ignoreSubscribers) onPushPop();
322
+ if (!history._ignoreSubscribers) onPushPop("REPLACE");
199
323
  return res;
200
324
  };
201
325
  return history;
@@ -215,8 +339,10 @@ function createMemoryHistory(opts = {
215
339
  initialEntries: ["/"]
216
340
  }) {
217
341
  const entries = opts.initialEntries;
218
- let index = opts.initialIndex ?? entries.length - 1;
219
- const states = entries.map(() => ({}));
342
+ let index = opts.initialIndex ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1) : entries.length - 1;
343
+ const states = entries.map(
344
+ (_entry, index2) => assignKeyAndIndex(index2, void 0)
345
+ );
220
346
  const getLocation = () => parseHref(entries[index], states[index]);
221
347
  return createHistory({
222
348
  getLocation,
@@ -257,7 +383,7 @@ function parseHref(href, state) {
257
383
  ),
258
384
  hash: hashIndex > -1 ? href.substring(hashIndex) : "",
259
385
  search: searchIndex > -1 ? href.slice(searchIndex, hashIndex === -1 ? void 0 : hashIndex) : "",
260
- state: state || {}
386
+ state: state || { [stateIndexKey]: 0 }
261
387
  };
262
388
  }
263
389
  function createRandomKey() {
@@ -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}\nexport interface RouterHistory {\n location: HistoryLocation\n length: number\n subscribers: Set<(opts: { location: HistoryLocation }) => void>\n subscribe: (cb: (opts: { location: HistoryLocation }) => 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 createHref: (href: string) => string\n block: (blocker: BlockerFn) => () => void\n flush: () => void\n destroy: () => void\n notify: () => void\n _ignoreSubscribers?: boolean\n}\n\nexport interface HistoryLocation extends ParsedPath {\n state: HistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {\n key?: string\n}\n\ntype ShouldAllowNavigation = any\n\nexport type BlockerFn = () =>\n | Promise<ShouldAllowNavigation>\n | ShouldAllowNavigation\n\nconst pushStateEvent = 'pushstate'\nconst popStateEvent = 'popstate'\nconst beforeUnloadEvent = 'beforeunload'\n\nconst beforeUnloadListener = (event: Event) => {\n event.preventDefault()\n // @ts-expect-error\n return (event.returnValue = '')\n}\n\nconst stopBlocking = () => {\n removeEventListener(beforeUnloadEvent, beforeUnloadListener, {\n capture: true,\n })\n}\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: () => void\n forward: () => void\n createHref: (path: string) => string\n flush?: () => void\n destroy?: () => void\n onBlocked?: (onUpdate: () => void) => void\n}): RouterHistory {\n let location = opts.getLocation()\n const subscribers = new Set<(opts: { location: HistoryLocation }) => void>()\n let blockers: Array<BlockerFn> = []\n\n const notify = () => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber({ location }))\n }\n\n const tryNavigation = async (\n task: () => void,\n navigateOpts?: NavigateOptions,\n ) => {\n const ignoreBlocker = navigateOpts?.ignoreBlocker ?? false\n if (!ignoreBlocker && typeof document !== 'undefined' && blockers.length) {\n for (const blocker of blockers) {\n const allowed = await blocker()\n if (!allowed) {\n opts.onBlocked?.(notify)\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: { location: HistoryLocation }) => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path, state, navigateOpts) => {\n state = assignKey(state)\n tryNavigation(() => {\n opts.pushState(path, state)\n notify()\n }, navigateOpts)\n },\n replace: (path, state, navigateOpts) => {\n state = assignKey(state)\n tryNavigation(() => {\n opts.replaceState(path, state)\n notify()\n }, navigateOpts)\n },\n go: (index, navigateOpts) => {\n tryNavigation(() => {\n opts.go(index)\n notify()\n }, navigateOpts)\n },\n back: (navigateOpts) => {\n tryNavigation(() => {\n opts.back()\n notify()\n }, navigateOpts)\n },\n forward: (navigateOpts) => {\n tryNavigation(() => {\n opts.forward()\n notify()\n }, navigateOpts)\n },\n createHref: (str) => opts.createHref(str),\n block: (blocker) => {\n blockers.push(blocker)\n\n if (blockers.length === 1) {\n addEventListener(beforeUnloadEvent, beforeUnloadListener, {\n capture: true,\n })\n }\n\n return () => {\n blockers = blockers.filter((b) => b !== blocker)\n\n if (!blockers.length) {\n stopBlocking()\n }\n }\n },\n flush: () => opts.flush?.(),\n destroy: () => opts.destroy?.(),\n notify,\n }\n}\n\nfunction assignKey(state: HistoryState | undefined) {\n if (!state) {\n state = {} as HistoryState\n }\n return {\n ...state,\n key: createRandomKey(),\n }\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 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 let currentLocation = parseLocation()\n let rollbackLocation: HistoryLocation | undefined\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 const onPushPop = () => {\n currentLocation = parseLocation()\n history.notify()\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: () => win.history.back(),\n forward: () => win.history.forward(),\n go: (n) => win.history.go(n),\n createHref: (href) => createHref(href),\n flush,\n destroy: () => {\n win.history.pushState = originalPushState\n win.history.replaceState = originalReplaceState\n win.removeEventListener(pushStateEvent, onPushPop)\n win.removeEventListener(popStateEvent, onPushPop)\n },\n onBlocked: (onUpdate) => {\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 // Notify subscribers\n onUpdate()\n }\n },\n })\n\n win.addEventListener(pushStateEvent, onPushPop)\n win.addEventListener(popStateEvent, onPushPop)\n\n win.history.pushState = function (...args: Array<any>) {\n const res = originalPushState.apply(win.history, args)\n if (!history._ignoreSubscribers) onPushPop()\n return res\n }\n\n win.history.replaceState = function (...args: Array<any>) {\n const res = originalReplaceState.apply(win.history, args)\n if (!history._ignoreSubscribers) onPushPop()\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 hashHref = win.location.hash.split('#').slice(1).join('#') ?? '/'\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 ?? entries.length - 1\n const states = entries.map(() => ({}) as HistoryState)\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: HistoryState | undefined,\n): HistoryLocation {\n const hashIndex = href.indexOf('#')\n const searchIndex = href.indexOf('?')\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 || {},\n }\n}\n\n// Thanks co-pilot!\nfunction createRandomKey() {\n return (Math.random() + 1).toString(36).substring(7)\n}\n"],"names":[],"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: HistoryAction\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: HistoryState\n}\n\nexport interface ParsedPath {\n href: string\n pathname: string\n search: string\n hash: string\n}\n\nexport interface HistoryState {\n 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 return {\n ...state,\n key: createRandomKey(),\n [stateIndexKey]: index,\n }\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 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 hashHref = win.location.hash.split('#').slice(1).join('#') ?? '/'\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<HistoryState>((_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: HistoryState | undefined,\n): HistoryLocation {\n const hashIndex = href.indexOf('#')\n const searchIndex = href.indexOf('?')\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 },\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,25 +1,32 @@
1
1
  export interface NavigateOptions {
2
2
  ignoreBlocker?: boolean;
3
3
  }
4
+ type SubscriberHistoryAction = {
5
+ type: HistoryAction;
6
+ } | {
7
+ type: 'GO';
8
+ index: number;
9
+ };
10
+ type SubscriberArgs = {
11
+ location: HistoryLocation;
12
+ action: SubscriberHistoryAction;
13
+ };
4
14
  export interface RouterHistory {
5
15
  location: HistoryLocation;
6
16
  length: number;
7
- subscribers: Set<(opts: {
8
- location: HistoryLocation;
9
- }) => void>;
10
- subscribe: (cb: (opts: {
11
- location: HistoryLocation;
12
- }) => void) => () => void;
17
+ subscribers: Set<(opts: SubscriberArgs) => void>;
18
+ subscribe: (cb: (opts: SubscriberArgs) => void) => () => void;
13
19
  push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void;
14
20
  replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void;
15
21
  go: (index: number, navigateOpts?: NavigateOptions) => void;
16
22
  back: (navigateOpts?: NavigateOptions) => void;
17
23
  forward: (navigateOpts?: NavigateOptions) => void;
24
+ canGoBack: () => boolean;
18
25
  createHref: (href: string) => string;
19
- block: (blocker: BlockerFn) => () => void;
26
+ block: (blocker: NavigationBlocker) => () => void;
20
27
  flush: () => void;
21
28
  destroy: () => void;
22
- notify: () => void;
29
+ notify: (action: SubscriberHistoryAction) => void;
23
30
  _ignoreSubscribers?: boolean;
24
31
  }
25
32
  export interface HistoryLocation extends ParsedPath {
@@ -33,21 +40,35 @@ export interface ParsedPath {
33
40
  }
34
41
  export interface HistoryState {
35
42
  key?: string;
43
+ __TSR_index: number;
36
44
  }
37
45
  type ShouldAllowNavigation = any;
38
- export type BlockerFn = () => Promise<ShouldAllowNavigation> | ShouldAllowNavigation;
46
+ export type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO';
47
+ export type BlockerFnArgs = {
48
+ currentLocation: HistoryLocation;
49
+ nextLocation: HistoryLocation;
50
+ action: HistoryAction;
51
+ };
52
+ export type BlockerFn = (args: BlockerFnArgs) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation;
53
+ export type NavigationBlocker = {
54
+ blockerFn: BlockerFn;
55
+ enableBeforeUnload?: (() => boolean) | boolean;
56
+ };
39
57
  export declare function createHistory(opts: {
40
58
  getLocation: () => HistoryLocation;
41
59
  getLength: () => number;
42
60
  pushState: (path: string, state: any) => void;
43
61
  replaceState: (path: string, state: any) => void;
44
62
  go: (n: number) => void;
45
- back: () => void;
46
- forward: () => void;
63
+ back: (ignoreBlocker: boolean) => void;
64
+ forward: (ignoreBlocker: boolean) => void;
47
65
  createHref: (path: string) => string;
48
66
  flush?: () => void;
49
67
  destroy?: () => void;
50
- onBlocked?: (onUpdate: () => void) => void;
68
+ onBlocked?: () => void;
69
+ getBlockers?: () => Array<NavigationBlocker>;
70
+ setBlockers?: (blockers: Array<NavigationBlocker>) => void;
71
+ notifyOnIndexChange?: boolean;
51
72
  }): RouterHistory;
52
73
  /**
53
74
  * Creates a history object that can be used to interact with the browser's
@@ -1,25 +1,32 @@
1
1
  export interface NavigateOptions {
2
2
  ignoreBlocker?: boolean;
3
3
  }
4
+ type SubscriberHistoryAction = {
5
+ type: HistoryAction;
6
+ } | {
7
+ type: 'GO';
8
+ index: number;
9
+ };
10
+ type SubscriberArgs = {
11
+ location: HistoryLocation;
12
+ action: SubscriberHistoryAction;
13
+ };
4
14
  export interface RouterHistory {
5
15
  location: HistoryLocation;
6
16
  length: number;
7
- subscribers: Set<(opts: {
8
- location: HistoryLocation;
9
- }) => void>;
10
- subscribe: (cb: (opts: {
11
- location: HistoryLocation;
12
- }) => void) => () => void;
17
+ subscribers: Set<(opts: SubscriberArgs) => void>;
18
+ subscribe: (cb: (opts: SubscriberArgs) => void) => () => void;
13
19
  push: (path: string, state?: any, navigateOpts?: NavigateOptions) => void;
14
20
  replace: (path: string, state?: any, navigateOpts?: NavigateOptions) => void;
15
21
  go: (index: number, navigateOpts?: NavigateOptions) => void;
16
22
  back: (navigateOpts?: NavigateOptions) => void;
17
23
  forward: (navigateOpts?: NavigateOptions) => void;
24
+ canGoBack: () => boolean;
18
25
  createHref: (href: string) => string;
19
- block: (blocker: BlockerFn) => () => void;
26
+ block: (blocker: NavigationBlocker) => () => void;
20
27
  flush: () => void;
21
28
  destroy: () => void;
22
- notify: () => void;
29
+ notify: (action: SubscriberHistoryAction) => void;
23
30
  _ignoreSubscribers?: boolean;
24
31
  }
25
32
  export interface HistoryLocation extends ParsedPath {
@@ -33,21 +40,35 @@ export interface ParsedPath {
33
40
  }
34
41
  export interface HistoryState {
35
42
  key?: string;
43
+ __TSR_index: number;
36
44
  }
37
45
  type ShouldAllowNavigation = any;
38
- export type BlockerFn = () => Promise<ShouldAllowNavigation> | ShouldAllowNavigation;
46
+ export type HistoryAction = 'PUSH' | 'REPLACE' | 'FORWARD' | 'BACK' | 'GO';
47
+ export type BlockerFnArgs = {
48
+ currentLocation: HistoryLocation;
49
+ nextLocation: HistoryLocation;
50
+ action: HistoryAction;
51
+ };
52
+ export type BlockerFn = (args: BlockerFnArgs) => Promise<ShouldAllowNavigation> | ShouldAllowNavigation;
53
+ export type NavigationBlocker = {
54
+ blockerFn: BlockerFn;
55
+ enableBeforeUnload?: (() => boolean) | boolean;
56
+ };
39
57
  export declare function createHistory(opts: {
40
58
  getLocation: () => HistoryLocation;
41
59
  getLength: () => number;
42
60
  pushState: (path: string, state: any) => void;
43
61
  replaceState: (path: string, state: any) => void;
44
62
  go: (n: number) => void;
45
- back: () => void;
46
- forward: () => void;
63
+ back: (ignoreBlocker: boolean) => void;
64
+ forward: (ignoreBlocker: boolean) => void;
47
65
  createHref: (path: string) => string;
48
66
  flush?: () => void;
49
67
  destroy?: () => void;
50
- onBlocked?: (onUpdate: () => void) => void;
68
+ onBlocked?: () => void;
69
+ getBlockers?: () => Array<NavigationBlocker>;
70
+ setBlockers?: (blockers: Array<NavigationBlocker>) => void;
71
+ notifyOnIndexChange?: boolean;
51
72
  }): RouterHistory;
52
73
  /**
53
74
  * Creates a history object that can be used to interact with the browser's