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