@tanstack/history 1.15.10 → 1.20.3-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +253 -106
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +50 -15
- package/dist/esm/index.d.ts +50 -15
- package/dist/esm/index.js +254 -107
- package/dist/esm/index.js.map +1 -1
- package/package.json +11 -16
- package/src/index.ts +364 -137
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
const onUpdate = () => {
|
|
8
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
9
|
+
const notify = (action) => {
|
|
20
10
|
location = opts.getLocation();
|
|
21
|
-
subscribers.forEach((subscriber) => subscriber());
|
|
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 (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
const tryNavigation = async ({
|
|
18
|
+
task,
|
|
19
|
+
navigateOpts,
|
|
20
|
+
...actionInfo
|
|
21
|
+
}) => {
|
|
22
|
+
var _a, _b;
|
|
23
|
+
const ignoreBlocker = (navigateOpts == null ? void 0 : navigateOpts.ignoreBlocker) ?? false;
|
|
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) {
|
|
31
|
+
for (const blocker of blockers) {
|
|
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);
|
|
30
40
|
return;
|
|
31
41
|
}
|
|
32
42
|
}
|
|
@@ -37,54 +47,86 @@ function createHistory(opts) {
|
|
|
37
47
|
get location() {
|
|
38
48
|
return location;
|
|
39
49
|
},
|
|
50
|
+
get length() {
|
|
51
|
+
return opts.getLength();
|
|
52
|
+
},
|
|
53
|
+
subscribers,
|
|
40
54
|
subscribe: (cb) => {
|
|
41
55
|
subscribers.add(cb);
|
|
42
56
|
return () => {
|
|
43
57
|
subscribers.delete(cb);
|
|
44
58
|
};
|
|
45
59
|
},
|
|
46
|
-
push: (path, state) => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
push: (path, state, 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
|
|
51
72
|
});
|
|
52
73
|
},
|
|
53
|
-
replace: (path, state) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
replace: (path, state, 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
|
|
58
86
|
});
|
|
59
87
|
},
|
|
60
|
-
go: (index) => {
|
|
61
|
-
tryNavigation(
|
|
62
|
-
|
|
88
|
+
go: (index, navigateOpts) => {
|
|
89
|
+
tryNavigation({
|
|
90
|
+
task: () => {
|
|
91
|
+
opts.go(index);
|
|
92
|
+
handleIndexChange({ type: "GO", index });
|
|
93
|
+
},
|
|
94
|
+
navigateOpts,
|
|
95
|
+
type: "GO"
|
|
63
96
|
});
|
|
64
97
|
},
|
|
65
|
-
back: () => {
|
|
66
|
-
tryNavigation(
|
|
67
|
-
|
|
98
|
+
back: (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"
|
|
68
106
|
});
|
|
69
107
|
},
|
|
70
|
-
forward: () => {
|
|
71
|
-
tryNavigation(
|
|
72
|
-
|
|
108
|
+
forward: (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"
|
|
73
116
|
});
|
|
74
117
|
},
|
|
118
|
+
canGoBack: () => location.state[stateIndexKey] !== 0,
|
|
75
119
|
createHref: (str) => opts.createHref(str),
|
|
76
120
|
block: (blocker) => {
|
|
77
|
-
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
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]);
|
|
83
126
|
return () => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
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));
|
|
88
130
|
};
|
|
89
131
|
},
|
|
90
132
|
flush: () => {
|
|
@@ -95,49 +137,64 @@ function createHistory(opts) {
|
|
|
95
137
|
var _a;
|
|
96
138
|
return (_a = opts.destroy) == null ? void 0 : _a.call(opts);
|
|
97
139
|
},
|
|
98
|
-
notify
|
|
140
|
+
notify
|
|
99
141
|
};
|
|
100
142
|
}
|
|
101
|
-
function
|
|
143
|
+
function assignKeyAndIndex(index, state) {
|
|
102
144
|
if (!state) {
|
|
103
145
|
state = {};
|
|
104
146
|
}
|
|
105
147
|
return {
|
|
106
148
|
...state,
|
|
107
|
-
key: createRandomKey()
|
|
149
|
+
key: createRandomKey(),
|
|
150
|
+
[stateIndexKey]: index
|
|
108
151
|
};
|
|
109
152
|
}
|
|
110
153
|
function createBrowserHistory(opts) {
|
|
154
|
+
var _a;
|
|
111
155
|
const win = (opts == null ? void 0 : opts.window) ?? (typeof document !== "undefined" ? window : void 0);
|
|
156
|
+
const originalPushState = win.history.pushState;
|
|
157
|
+
const originalReplaceState = win.history.replaceState;
|
|
158
|
+
let blockers = [];
|
|
159
|
+
const _getBlockers = () => blockers;
|
|
160
|
+
const _setBlockers = (newBlockers) => blockers = newBlockers;
|
|
112
161
|
const createHref = (opts == null ? void 0 : opts.createHref) ?? ((path) => path);
|
|
113
162
|
const parseLocation = (opts == null ? void 0 : opts.parseLocation) ?? (() => parseHref(
|
|
114
163
|
`${win.location.pathname}${win.location.search}${win.location.hash}`,
|
|
115
164
|
win.history.state
|
|
116
165
|
));
|
|
166
|
+
if (!((_a = win.history.state) == null ? void 0 : _a.key)) {
|
|
167
|
+
win.history.replaceState(
|
|
168
|
+
{
|
|
169
|
+
[stateIndexKey]: 0,
|
|
170
|
+
key: createRandomKey()
|
|
171
|
+
},
|
|
172
|
+
""
|
|
173
|
+
);
|
|
174
|
+
}
|
|
117
175
|
let currentLocation = parseLocation();
|
|
118
176
|
let rollbackLocation;
|
|
177
|
+
let nextPopIsGo = false;
|
|
178
|
+
let ignoreNextPop = false;
|
|
179
|
+
let skipBlockerNextPop = false;
|
|
180
|
+
let ignoreNextBeforeUnload = false;
|
|
119
181
|
const getLocation = () => currentLocation;
|
|
120
182
|
let next;
|
|
121
|
-
let tracking = true;
|
|
122
183
|
let scheduled;
|
|
123
|
-
const untrack = (fn) => {
|
|
124
|
-
tracking = false;
|
|
125
|
-
fn();
|
|
126
|
-
tracking = true;
|
|
127
|
-
};
|
|
128
184
|
const flush = () => {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
185
|
+
if (!next) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
history._ignoreSubscribers = true;
|
|
189
|
+
(next.isPush ? win.history.pushState : win.history.replaceState)(
|
|
190
|
+
next.state,
|
|
191
|
+
"",
|
|
192
|
+
next.href
|
|
193
|
+
);
|
|
194
|
+
history._ignoreSubscribers = false;
|
|
195
|
+
next = void 0;
|
|
196
|
+
scheduled = void 0;
|
|
197
|
+
rollbackLocation = void 0;
|
|
141
198
|
};
|
|
142
199
|
const queueHistoryAction = (type, destHref, state) => {
|
|
143
200
|
const href = createHref(destHref);
|
|
@@ -154,46 +211,125 @@ function createBrowserHistory(opts) {
|
|
|
154
211
|
scheduled = Promise.resolve().then(() => flush());
|
|
155
212
|
}
|
|
156
213
|
};
|
|
157
|
-
const onPushPop = () => {
|
|
214
|
+
const onPushPop = (type) => {
|
|
215
|
+
currentLocation = parseLocation();
|
|
216
|
+
history.notify({ type });
|
|
217
|
+
};
|
|
218
|
+
const onPushPopEvent = async () => {
|
|
219
|
+
if (ignoreNextPop) {
|
|
220
|
+
ignoreNextPop = false;
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const nextLocation = parseLocation();
|
|
224
|
+
const delta = nextLocation.state[stateIndexKey] - currentLocation.state[stateIndexKey];
|
|
225
|
+
const isForward = delta === 1;
|
|
226
|
+
const isBack = delta === -1;
|
|
227
|
+
const isGo = !isForward && !isBack || nextPopIsGo;
|
|
228
|
+
nextPopIsGo = false;
|
|
229
|
+
const action = isGo ? "GO" : isBack ? "BACK" : "FORWARD";
|
|
230
|
+
const notify = isGo ? {
|
|
231
|
+
type: "GO",
|
|
232
|
+
index: delta
|
|
233
|
+
} : {
|
|
234
|
+
type: isBack ? "BACK" : "FORWARD"
|
|
235
|
+
};
|
|
236
|
+
if (skipBlockerNextPop) {
|
|
237
|
+
skipBlockerNextPop = false;
|
|
238
|
+
} else {
|
|
239
|
+
const blockers2 = _getBlockers();
|
|
240
|
+
if (typeof document !== "undefined" && blockers2.length) {
|
|
241
|
+
for (const blocker of blockers2) {
|
|
242
|
+
const isBlocked = await blocker.blockerFn({
|
|
243
|
+
currentLocation,
|
|
244
|
+
nextLocation,
|
|
245
|
+
action
|
|
246
|
+
});
|
|
247
|
+
if (isBlocked) {
|
|
248
|
+
ignoreNextPop = true;
|
|
249
|
+
win.history.go(1);
|
|
250
|
+
history.notify(notify);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
158
256
|
currentLocation = parseLocation();
|
|
159
|
-
history.notify();
|
|
257
|
+
history.notify(notify);
|
|
258
|
+
};
|
|
259
|
+
const onBeforeUnload = (e) => {
|
|
260
|
+
if (ignoreNextBeforeUnload) {
|
|
261
|
+
ignoreNextBeforeUnload = false;
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
let shouldBlock = false;
|
|
265
|
+
const blockers2 = _getBlockers();
|
|
266
|
+
if (typeof document !== "undefined" && blockers2.length) {
|
|
267
|
+
for (const blocker of blockers2) {
|
|
268
|
+
const shouldHaveBeforeUnload = blocker.enableBeforeUnload ?? true;
|
|
269
|
+
if (shouldHaveBeforeUnload === true) {
|
|
270
|
+
shouldBlock = true;
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
if (typeof shouldHaveBeforeUnload === "function" && shouldHaveBeforeUnload() === true) {
|
|
274
|
+
shouldBlock = true;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (shouldBlock) {
|
|
280
|
+
e.preventDefault();
|
|
281
|
+
return e.returnValue = "";
|
|
282
|
+
}
|
|
283
|
+
return;
|
|
160
284
|
};
|
|
161
|
-
var originalPushState = win.history.pushState;
|
|
162
|
-
var originalReplaceState = win.history.replaceState;
|
|
163
285
|
const history = createHistory({
|
|
164
286
|
getLocation,
|
|
287
|
+
getLength: () => win.history.length,
|
|
165
288
|
pushState: (href, state) => queueHistoryAction("push", href, state),
|
|
166
289
|
replaceState: (href, state) => queueHistoryAction("replace", href, state),
|
|
167
|
-
back: () =>
|
|
168
|
-
|
|
169
|
-
|
|
290
|
+
back: (ignoreBlocker) => {
|
|
291
|
+
if (ignoreBlocker) skipBlockerNextPop = true;
|
|
292
|
+
ignoreNextBeforeUnload = true;
|
|
293
|
+
return win.history.back();
|
|
294
|
+
},
|
|
295
|
+
forward: (ignoreBlocker) => {
|
|
296
|
+
if (ignoreBlocker) skipBlockerNextPop = true;
|
|
297
|
+
ignoreNextBeforeUnload = true;
|
|
298
|
+
win.history.forward();
|
|
299
|
+
},
|
|
300
|
+
go: (n) => {
|
|
301
|
+
nextPopIsGo = true;
|
|
302
|
+
win.history.go(n);
|
|
303
|
+
},
|
|
170
304
|
createHref: (href) => createHref(href),
|
|
171
305
|
flush,
|
|
172
306
|
destroy: () => {
|
|
173
307
|
win.history.pushState = originalPushState;
|
|
174
308
|
win.history.replaceState = originalReplaceState;
|
|
175
|
-
win.removeEventListener(
|
|
176
|
-
|
|
309
|
+
win.removeEventListener(beforeUnloadEvent, onBeforeUnload, {
|
|
310
|
+
capture: true
|
|
311
|
+
});
|
|
312
|
+
win.removeEventListener(popStateEvent, onPushPopEvent);
|
|
177
313
|
},
|
|
178
|
-
onBlocked: (
|
|
314
|
+
onBlocked: () => {
|
|
179
315
|
if (rollbackLocation && currentLocation !== rollbackLocation) {
|
|
180
316
|
currentLocation = rollbackLocation;
|
|
181
|
-
onUpdate();
|
|
182
317
|
}
|
|
183
|
-
}
|
|
318
|
+
},
|
|
319
|
+
getBlockers: _getBlockers,
|
|
320
|
+
setBlockers: _setBlockers,
|
|
321
|
+
notifyOnIndexChange: false
|
|
184
322
|
});
|
|
185
|
-
win.addEventListener(
|
|
186
|
-
win.addEventListener(popStateEvent,
|
|
187
|
-
win.history.pushState = function() {
|
|
188
|
-
|
|
189
|
-
if (
|
|
190
|
-
history.notify();
|
|
323
|
+
win.addEventListener(beforeUnloadEvent, onBeforeUnload, { capture: true });
|
|
324
|
+
win.addEventListener(popStateEvent, onPushPopEvent);
|
|
325
|
+
win.history.pushState = function(...args) {
|
|
326
|
+
const res = originalPushState.apply(win.history, args);
|
|
327
|
+
if (!history._ignoreSubscribers) onPushPop("PUSH");
|
|
191
328
|
return res;
|
|
192
329
|
};
|
|
193
|
-
win.history.replaceState = function() {
|
|
194
|
-
|
|
195
|
-
if (
|
|
196
|
-
history.notify();
|
|
330
|
+
win.history.replaceState = function(...args) {
|
|
331
|
+
const res = originalReplaceState.apply(win.history, args);
|
|
332
|
+
if (!history._ignoreSubscribers) onPushPop("REPLACE");
|
|
197
333
|
return res;
|
|
198
334
|
};
|
|
199
335
|
return history;
|
|
@@ -203,7 +339,12 @@ function createHashHistory(opts) {
|
|
|
203
339
|
return createBrowserHistory({
|
|
204
340
|
window: win,
|
|
205
341
|
parseLocation: () => {
|
|
206
|
-
const
|
|
342
|
+
const hashSplit = win.location.hash.split("#").slice(1);
|
|
343
|
+
const pathPart = hashSplit[0] ?? "/";
|
|
344
|
+
const searchPart = win.location.search;
|
|
345
|
+
const hashEntries = hashSplit.slice(1);
|
|
346
|
+
const hashPart = hashEntries.length === 0 ? "" : `#${hashEntries.join("#")}`;
|
|
347
|
+
const hashHref = `${pathPart}${searchPart}${hashPart}`;
|
|
207
348
|
return parseHref(hashHref, win.history.state);
|
|
208
349
|
},
|
|
209
350
|
createHref: (href) => `${win.location.pathname}${win.location.search}#${href}`
|
|
@@ -213,24 +354,29 @@ function createMemoryHistory(opts = {
|
|
|
213
354
|
initialEntries: ["/"]
|
|
214
355
|
}) {
|
|
215
356
|
const entries = opts.initialEntries;
|
|
216
|
-
let index = opts.initialIndex
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const getLocation = () => parseHref(entries[index],
|
|
357
|
+
let index = opts.initialIndex ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1) : entries.length - 1;
|
|
358
|
+
const states = entries.map(
|
|
359
|
+
(_entry, index2) => assignKeyAndIndex(index2, void 0)
|
|
360
|
+
);
|
|
361
|
+
const getLocation = () => parseHref(entries[index], states[index]);
|
|
221
362
|
return createHistory({
|
|
222
363
|
getLocation,
|
|
364
|
+
getLength: () => entries.length,
|
|
223
365
|
pushState: (path, state) => {
|
|
224
|
-
|
|
366
|
+
if (index < entries.length - 1) {
|
|
367
|
+
entries.splice(index + 1);
|
|
368
|
+
states.splice(index + 1);
|
|
369
|
+
}
|
|
370
|
+
states.push(state);
|
|
225
371
|
entries.push(path);
|
|
226
|
-
index
|
|
372
|
+
index = Math.max(entries.length - 1, 0);
|
|
227
373
|
},
|
|
228
374
|
replaceState: (path, state) => {
|
|
229
|
-
|
|
375
|
+
states[index] = state;
|
|
230
376
|
entries[index] = path;
|
|
231
377
|
},
|
|
232
378
|
back: () => {
|
|
233
|
-
index
|
|
379
|
+
index = Math.max(index - 1, 0);
|
|
234
380
|
},
|
|
235
381
|
forward: () => {
|
|
236
382
|
index = Math.min(index + 1, entries.length - 1);
|
|
@@ -242,8 +388,8 @@ function createMemoryHistory(opts = {
|
|
|
242
388
|
});
|
|
243
389
|
}
|
|
244
390
|
function parseHref(href, state) {
|
|
245
|
-
|
|
246
|
-
|
|
391
|
+
const hashIndex = href.indexOf("#");
|
|
392
|
+
const searchIndex = href.indexOf("?");
|
|
247
393
|
return {
|
|
248
394
|
href,
|
|
249
395
|
pathname: href.substring(
|
|
@@ -252,7 +398,7 @@ function parseHref(href, state) {
|
|
|
252
398
|
),
|
|
253
399
|
hash: hashIndex > -1 ? href.substring(hashIndex) : "",
|
|
254
400
|
search: searchIndex > -1 ? href.slice(searchIndex, hashIndex === -1 ? void 0 : hashIndex) : "",
|
|
255
|
-
state: state || {}
|
|
401
|
+
state: state || { [stateIndexKey]: 0, key: createRandomKey() }
|
|
256
402
|
};
|
|
257
403
|
}
|
|
258
404
|
function createRandomKey() {
|
|
@@ -262,4 +408,5 @@ exports.createBrowserHistory = createBrowserHistory;
|
|
|
262
408
|
exports.createHashHistory = createHashHistory;
|
|
263
409
|
exports.createHistory = createHistory;
|
|
264
410
|
exports.createMemoryHistory = createMemoryHistory;
|
|
411
|
+
exports.parseHref = parseHref;
|
|
265
412
|
//# sourceMappingURL=index.cjs.map
|
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 RouterHistory {\n location: HistoryLocation\n subscribe: (cb: () => void) => () => void\n push: (path: string, state?: any) => void\n replace: (path: string, state?: any) => void\n go: (index: number) => void\n back: () => void\n forward: () => void\n createHref: (href: string) => string\n block: (blocker: BlockerFn) => () => void\n flush: () => void\n destroy: () => void\n notify: () => void\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-ignore\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 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 let subscribers = new Set<() => void>()\n let blockers: BlockerFn[] = []\n\n const onUpdate = () => {\n location = opts.getLocation()\n subscribers.forEach((subscriber) => subscriber())\n }\n\n const tryNavigation = async (task: () => void) => {\n if (typeof document !== 'undefined' && blockers.length) {\n for (let blocker of blockers) {\n const allowed = await blocker()\n if (!allowed) {\n opts.onBlocked?.(onUpdate)\n return\n }\n }\n }\n\n task()\n }\n\n return {\n get location() {\n return location\n },\n subscribe: (cb: () => void) => {\n subscribers.add(cb)\n\n return () => {\n subscribers.delete(cb)\n }\n },\n push: (path: string, state: any) => {\n state = assignKey(state)\n tryNavigation(() => {\n opts.pushState(path, state)\n onUpdate()\n })\n },\n replace: (path: string, state: any) => {\n state = assignKey(state)\n tryNavigation(() => {\n opts.replaceState(path, state)\n onUpdate()\n })\n },\n go: (index) => {\n tryNavigation(() => {\n opts.go(index)\n })\n },\n back: () => {\n tryNavigation(() => {\n opts.back()\n })\n },\n forward: () => {\n tryNavigation(() => {\n opts.forward()\n })\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: onUpdate,\n }\n}\n\nfunction assignKey(state: HistoryState) {\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 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 // Because we are proactively updating the location\n // in memory before actually updating the browser history,\n // we need to track when we are doing this so we don't\n // notify subscribers twice on the last update.\n let tracking = true\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 is a wrapper to prevent any of the callback's\n // side effects from causing a subscriber notification\n const untrack = (fn: () => void) => {\n tracking = false\n fn()\n tracking = true\n }\n\n // This function flushes the next update to the browser history\n const flush = () => {\n // Do not notify subscribers about this push/replace call\n untrack(() => {\n if (!next) return\n win.history[next.isPush ? 'pushState' : 'replaceState'](\n next.state,\n '',\n next.href,\n )\n // Reset the nextIsPush flag and clear the scheduled update\n next = undefined\n scheduled = undefined\n rollbackLocation = undefined\n })\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 var originalPushState = win.history.pushState\n var originalReplaceState = win.history.replaceState\n\n const history = createHistory({\n getLocation,\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 () {\n let res = originalPushState.apply(win.history, arguments as any)\n if (tracking) history.notify()\n return res\n }\n\n win.history.replaceState = function () {\n let res = originalReplaceState.apply(win.history, arguments as any)\n if (tracking) history.notify()\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: string[]\n initialIndex?: number\n } = {\n initialEntries: ['/'],\n },\n): RouterHistory {\n const entries = opts.initialEntries\n let index = opts.initialIndex ?? entries.length - 1\n let currentState = {\n key: createRandomKey(),\n } as HistoryState\n\n const getLocation = () => parseHref(entries[index]!, currentState)\n\n return createHistory({\n getLocation,\n\n pushState: (path, state) => {\n currentState = state\n entries.push(path)\n index++\n },\n replaceState: (path, state) => {\n currentState = state\n entries[index] = path\n },\n back: () => {\n index--\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\nfunction parseHref(href: string, state: HistoryState): HistoryLocation {\n let hashIndex = href.indexOf('#')\n let 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: 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\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 } 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?.key) {\n win.history.replaceState(\n {\n [stateIndexKey]: 0,\n key: createRandomKey(),\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 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: createRandomKey() },\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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"}
|