@equinor/fusion-framework-module-navigation 7.0.0 → 7.0.2
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/CHANGELOG.md +21 -0
- package/dist/esm/NavigationConfigurator.js +29 -6
- package/dist/esm/NavigationConfigurator.js.map +1 -1
- package/dist/esm/lib/ProxyHistory.js +114 -0
- package/dist/esm/lib/ProxyHistory.js.map +1 -0
- package/dist/esm/lib/index.js +1 -0
- package/dist/esm/lib/index.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/NavigationConfigurator.d.ts +10 -1
- package/dist/types/lib/ProxyHistory.d.ts +68 -0
- package/dist/types/lib/index.d.ts +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +7 -7
- package/src/NavigationConfigurator.ts +47 -15
- package/src/__tests__/ProxyHistory.test.ts +149 -0
- package/src/lib/ProxyHistory.ts +144 -0
- package/src/lib/index.ts +1 -0
- package/src/version.ts +1 -1
|
@@ -28,10 +28,19 @@ export declare class NavigationConfigurator extends BaseConfigBuilder<INavigatio
|
|
|
28
28
|
/**
|
|
29
29
|
* Sets a custom history instance for the navigation module.
|
|
30
30
|
*
|
|
31
|
+
* By default the resolved history is wrapped in a {@link ProxyHistory} so the
|
|
32
|
+
* module gets its own disposable handle without owning (or accidentally
|
|
33
|
+
* disposing) the original instance. Set `proxy` to `false` to use the
|
|
34
|
+
* history as-is.
|
|
35
|
+
*
|
|
31
36
|
* @param historyOrCallback - History instance or configuration callback
|
|
37
|
+
* @param options - Optional settings for history wrapping
|
|
38
|
+
* @param options.proxy - Wrap the history in a {@link ProxyHistory} (default: `true`)
|
|
32
39
|
* @returns The configurator instance for method chaining
|
|
33
40
|
*/
|
|
34
|
-
setHistory(historyOrCallback?: History | ConfigBuilderCallback<History
|
|
41
|
+
setHistory(historyOrCallback?: History | ConfigBuilderCallback<History>, options?: {
|
|
42
|
+
proxy?: boolean;
|
|
43
|
+
}): this;
|
|
35
44
|
/**
|
|
36
45
|
* Sets telemetry configuration for navigation-specific events.
|
|
37
46
|
*
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Observable } from 'rxjs';
|
|
2
|
+
import type { History, NavigateOptions, NavigationBlocker, NavigationListener, NavigationUpdate, Path, To } from './types';
|
|
3
|
+
import type { Actions } from './state/history.actions';
|
|
4
|
+
/**
|
|
5
|
+
* A lightweight proxy that delegates every {@link History} operation to an
|
|
6
|
+
* underlying target instance.
|
|
7
|
+
*
|
|
8
|
+
* Use this when you need to pass a conforming `History` object whose backing
|
|
9
|
+
* implementation can be swapped or is not yet available at construction time,
|
|
10
|
+
* or when you want a thin indirection layer without subclassing
|
|
11
|
+
* {@link BaseHistory}.
|
|
12
|
+
*
|
|
13
|
+
* The proxy does **not** own the underlying history; disposing it only tears
|
|
14
|
+
* down subscriptions and blockers registered through the proxy itself.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const browser = createHistory('browser');
|
|
19
|
+
* const proxy = new ProxyHistory(browser);
|
|
20
|
+
* proxy.push('/dashboard'); // delegates to browser.push
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class ProxyHistory implements History {
|
|
24
|
+
#private;
|
|
25
|
+
/**
|
|
26
|
+
* @param target - The history instance to delegate all operations to
|
|
27
|
+
*/
|
|
28
|
+
constructor(target: History);
|
|
29
|
+
/** @inheritdoc */
|
|
30
|
+
get state$(): Observable<NavigationUpdate>;
|
|
31
|
+
/** @inheritdoc */
|
|
32
|
+
get action$(): Observable<Actions>;
|
|
33
|
+
/** @inheritdoc */
|
|
34
|
+
get action(): History['action'];
|
|
35
|
+
/** @inheritdoc */
|
|
36
|
+
get location(): History['location'];
|
|
37
|
+
/** @inheritdoc */
|
|
38
|
+
createHref(to: To): string;
|
|
39
|
+
/** @inheritdoc */
|
|
40
|
+
createURL(to: To): URL;
|
|
41
|
+
/** @inheritdoc */
|
|
42
|
+
encodeLocation(to: To): Path;
|
|
43
|
+
/** @inheritdoc */
|
|
44
|
+
push(to: To, state?: unknown): void;
|
|
45
|
+
/** @inheritdoc */
|
|
46
|
+
replace(to: To, state?: unknown): void;
|
|
47
|
+
/** @inheritdoc */
|
|
48
|
+
navigate(to: To, options?: NavigateOptions): void;
|
|
49
|
+
/** @inheritdoc */
|
|
50
|
+
go(delta: number): void;
|
|
51
|
+
/**
|
|
52
|
+
* Triggers a POP action on the underlying history to notify framework
|
|
53
|
+
* listeners (e.g. React Router) after programmatic navigation.
|
|
54
|
+
*
|
|
55
|
+
* Delegates to the target's `pop()` when it is a {@link BaseHistory}
|
|
56
|
+
* instance; otherwise this is a no-op.
|
|
57
|
+
*/
|
|
58
|
+
pop(): void;
|
|
59
|
+
/** @inheritdoc */
|
|
60
|
+
listen(listener: NavigationListener): () => void;
|
|
61
|
+
/** @inheritdoc */
|
|
62
|
+
block(blocker: NavigationBlocker): VoidFunction;
|
|
63
|
+
/**
|
|
64
|
+
* Disposes all listeners and blockers registered through this proxy.
|
|
65
|
+
* Does **not** dispose the underlying history.
|
|
66
|
+
*/
|
|
67
|
+
[Symbol.dispose](): void;
|
|
68
|
+
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
export { BaseHistory } from './BaseHistory';
|
|
11
11
|
export { BrowserHistory } from './BrowserHistory';
|
|
12
12
|
export { MemoryHistory } from './MemoryHistory';
|
|
13
|
+
export { ProxyHistory } from './ProxyHistory';
|
|
13
14
|
export { BrowserHistoryStack } from './BrowserHistoryStack';
|
|
14
15
|
export { BrowserHistoryHashStack as HashHistoryStack } from './BrowserHistoryHashStack';
|
|
15
16
|
export { MemoryHistoryStack } from './MemoryStack';
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "7.0.
|
|
1
|
+
export declare const version = "7.0.2";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-module-navigation",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.2",
|
|
4
4
|
"description": "Navigation module for Fusion Framework providing routing and navigation capabilities using React Router 7",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "dist/esm/index.js",
|
|
@@ -32,24 +32,24 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@remix-run/router": "^1.23.0",
|
|
35
|
-
"uuid": "^
|
|
35
|
+
"uuid": "^14.0.0",
|
|
36
36
|
"zod": "^4.3.6"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"jsdom": "^
|
|
39
|
+
"jsdom": "^29.0.2",
|
|
40
40
|
"rxjs": "^7.8.1",
|
|
41
41
|
"typescript": "^5.9.3",
|
|
42
42
|
"vitest": "^4.1.0",
|
|
43
|
-
"@equinor/fusion-framework-module": "^6.0.0",
|
|
44
43
|
"@equinor/fusion-framework-module-event": "^6.0.0",
|
|
45
|
-
"@equinor/fusion-
|
|
46
|
-
"@equinor/fusion-
|
|
44
|
+
"@equinor/fusion-observable": "^9.0.1",
|
|
45
|
+
"@equinor/fusion-framework-module-telemetry": "^5.0.1",
|
|
46
|
+
"@equinor/fusion-framework-module": "^6.0.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@remix-run/router": "^1.0.0",
|
|
50
50
|
"rxjs": "^7.0.0",
|
|
51
51
|
"@equinor/fusion-framework-module": "^6.0.0",
|
|
52
|
-
"@equinor/fusion-observable": "^9.0.
|
|
52
|
+
"@equinor/fusion-observable": "^9.0.1"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsc -b",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { of, type ObservableInput } from 'rxjs';
|
|
2
|
+
import { of, from, type ObservableInput } from 'rxjs';
|
|
3
|
+
import { map } from 'rxjs/operators';
|
|
3
4
|
import {
|
|
4
5
|
BaseConfigBuilder,
|
|
5
6
|
type ModulesInstance,
|
|
@@ -12,6 +13,7 @@ import type { INavigationConfigurator } from './NavigationConfigurator.interface
|
|
|
12
13
|
|
|
13
14
|
import type { History } from './lib/types';
|
|
14
15
|
import { createHistory } from './lib/create-history';
|
|
16
|
+
import { ProxyHistory } from './lib/ProxyHistory';
|
|
15
17
|
import type { NavigationModule } from './module';
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -72,16 +74,21 @@ export class NavigationConfigurator extends BaseConfigBuilder<INavigationConfigu
|
|
|
72
74
|
return await args.requireInstance('event');
|
|
73
75
|
}
|
|
74
76
|
});
|
|
75
|
-
this.setHistory(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
this.setHistory(
|
|
78
|
+
async (args) => {
|
|
79
|
+
const history = (args.ref as ModulesInstance<[NavigationModule]>)?.navigation?.history;
|
|
80
|
+
if (history) {
|
|
81
|
+
// Wrap the provided history in a ProxyHistory to ensure the module can manage its own teardowns without affecting the original instance.
|
|
82
|
+
return new ProxyHistory(history);
|
|
83
|
+
}
|
|
84
|
+
if (typeof window !== 'undefined') {
|
|
85
|
+
return createHistory('browser');
|
|
86
|
+
}
|
|
87
|
+
return createHistory('memory');
|
|
88
|
+
},
|
|
89
|
+
// Don't wrap the default history in a ProxyHistory since it's already owned by the module and will be properly disposed.
|
|
90
|
+
{ proxy: false },
|
|
91
|
+
);
|
|
85
92
|
}
|
|
86
93
|
/**
|
|
87
94
|
* @deprecated Use `setBasename()` method instead
|
|
@@ -121,13 +128,38 @@ export class NavigationConfigurator extends BaseConfigBuilder<INavigationConfigu
|
|
|
121
128
|
/**
|
|
122
129
|
* Sets a custom history instance for the navigation module.
|
|
123
130
|
*
|
|
131
|
+
* By default the resolved history is wrapped in a {@link ProxyHistory} so the
|
|
132
|
+
* module gets its own disposable handle without owning (or accidentally
|
|
133
|
+
* disposing) the original instance. Set `proxy` to `false` to use the
|
|
134
|
+
* history as-is.
|
|
135
|
+
*
|
|
124
136
|
* @param historyOrCallback - History instance or configuration callback
|
|
137
|
+
* @param options - Optional settings for history wrapping
|
|
138
|
+
* @param options.proxy - Wrap the history in a {@link ProxyHistory} (default: `true`)
|
|
125
139
|
* @returns The configurator instance for method chaining
|
|
126
140
|
*/
|
|
127
|
-
public setHistory(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
141
|
+
public setHistory(
|
|
142
|
+
historyOrCallback?: History | ConfigBuilderCallback<History>,
|
|
143
|
+
options?: { proxy?: boolean },
|
|
144
|
+
): this {
|
|
145
|
+
const { proxy = true } = options ?? {};
|
|
146
|
+
const resolve =
|
|
147
|
+
typeof historyOrCallback === 'function'
|
|
148
|
+
? historyOrCallback
|
|
149
|
+
: // Normalize a direct instance to a callback for consistent handling.
|
|
150
|
+
async () => historyOrCallback;
|
|
151
|
+
|
|
152
|
+
if (proxy) {
|
|
153
|
+
// Wrap each emitted history in a ProxyHistory so dispose only tears down
|
|
154
|
+
// proxy-owned listeners/blockers, never the underlying history itself.
|
|
155
|
+
this._set('history', (args) =>
|
|
156
|
+
from(resolve(args) as ObservableInput<History | undefined>).pipe(
|
|
157
|
+
map((history) => (history ? new ProxyHistory(history) : undefined)),
|
|
158
|
+
),
|
|
159
|
+
);
|
|
160
|
+
} else {
|
|
161
|
+
this._set('history', resolve);
|
|
162
|
+
}
|
|
131
163
|
return this;
|
|
132
164
|
}
|
|
133
165
|
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { firstValueFrom, skip } from 'rxjs';
|
|
3
|
+
import { MemoryHistory } from '../lib/MemoryHistory';
|
|
4
|
+
import { ProxyHistory } from '../lib/ProxyHistory';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Awaits the next state emission after performing a navigation action.
|
|
8
|
+
* MemoryHistory processes state updates asynchronously through the subject.
|
|
9
|
+
*/
|
|
10
|
+
const awaitNavigation = async (
|
|
11
|
+
history: MemoryHistory | ProxyHistory,
|
|
12
|
+
action: () => void,
|
|
13
|
+
): Promise<void> => {
|
|
14
|
+
const next = firstValueFrom(history.state$.pipe(skip(1)));
|
|
15
|
+
action();
|
|
16
|
+
await next;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
describe('ProxyHistory', () => {
|
|
20
|
+
let target: MemoryHistory;
|
|
21
|
+
let proxy: ProxyHistory;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
target = new MemoryHistory();
|
|
25
|
+
proxy = new ProxyHistory(target);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
proxy[Symbol.dispose]();
|
|
30
|
+
target[Symbol.dispose]();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('delegation', () => {
|
|
34
|
+
it('should delegate location to the target', () => {
|
|
35
|
+
expect(proxy.location).toBe(target.location);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should delegate action to the target', () => {
|
|
39
|
+
expect(proxy.action).toBe(target.action);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should delegate push to the target', async () => {
|
|
43
|
+
await awaitNavigation(proxy, () => proxy.push('/test'));
|
|
44
|
+
|
|
45
|
+
expect(target.location.pathname).toBe('/test');
|
|
46
|
+
expect(proxy.location.pathname).toBe('/test');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should delegate replace to the target', async () => {
|
|
50
|
+
await awaitNavigation(proxy, () => proxy.replace('/replaced'));
|
|
51
|
+
|
|
52
|
+
expect(target.location.pathname).toBe('/replaced');
|
|
53
|
+
expect(proxy.location.pathname).toBe('/replaced');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should delegate navigate to the target', async () => {
|
|
57
|
+
await awaitNavigation(proxy, () =>
|
|
58
|
+
proxy.navigate('/nav', { replace: true, state: { foo: 1 } }),
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(target.location.pathname).toBe('/nav');
|
|
62
|
+
expect(target.location.state).toEqual({ foo: 1 });
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should delegate createHref to the target', () => {
|
|
66
|
+
expect(proxy.createHref('/path')).toBe(target.createHref('/path'));
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('should delegate createURL to the target', () => {
|
|
70
|
+
expect(proxy.createURL('/path').href).toBe(target.createURL('/path').href);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should delegate encodeLocation to the target', () => {
|
|
74
|
+
const encoded = proxy.encodeLocation('/path');
|
|
75
|
+
expect(encoded).toEqual(target.encodeLocation('/path'));
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('pop()', () => {
|
|
80
|
+
it('should delegate pop to the target when target supports it', () => {
|
|
81
|
+
const popSpy = vi.spyOn(target, 'pop');
|
|
82
|
+
proxy.pop();
|
|
83
|
+
expect(popSpy).toHaveBeenCalledOnce();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('teardown isolation', () => {
|
|
88
|
+
it('should not dispose the target when proxy is disposed', async () => {
|
|
89
|
+
// Dispose the proxy
|
|
90
|
+
proxy[Symbol.dispose]();
|
|
91
|
+
|
|
92
|
+
// Target should still be functional — push should work
|
|
93
|
+
await awaitNavigation(target, () => target.push('/after-proxy-dispose'));
|
|
94
|
+
expect(target.location.pathname).toBe('/after-proxy-dispose');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should clean up proxy-owned listeners on dispose', async () => {
|
|
98
|
+
const proxyListener = vi.fn();
|
|
99
|
+
proxy.listen(proxyListener);
|
|
100
|
+
|
|
101
|
+
// Dispose the proxy — listener teardown should be called on the target
|
|
102
|
+
proxy[Symbol.dispose]();
|
|
103
|
+
|
|
104
|
+
// Target is still alive, push something — the disposed proxy listener
|
|
105
|
+
// should not fire (listen only triggers on POP, but the underlying
|
|
106
|
+
// subscription should be removed entirely)
|
|
107
|
+
await awaitNavigation(target, () => target.push('/after-dispose'));
|
|
108
|
+
expect(target.location.pathname).toBe('/after-dispose');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should not affect target listeners when proxy is disposed', async () => {
|
|
112
|
+
// Register a listener directly on the target
|
|
113
|
+
const targetListener = vi.fn();
|
|
114
|
+
target.listen(targetListener);
|
|
115
|
+
|
|
116
|
+
// Register a listener through the proxy
|
|
117
|
+
proxy.listen(vi.fn());
|
|
118
|
+
|
|
119
|
+
// Dispose proxy — only proxy listener should be removed
|
|
120
|
+
proxy[Symbol.dispose]();
|
|
121
|
+
|
|
122
|
+
// Target should still be functional
|
|
123
|
+
await awaitNavigation(target, () => target.push('/still-works'));
|
|
124
|
+
expect(target.location.pathname).toBe('/still-works');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('listen/block unsubscribe', () => {
|
|
129
|
+
it('should allow manual unsubscribe of a listener', () => {
|
|
130
|
+
const listener = vi.fn();
|
|
131
|
+
const unlisten = proxy.listen(listener);
|
|
132
|
+
|
|
133
|
+
unlisten();
|
|
134
|
+
|
|
135
|
+
// No error on dispose — the listener was already removed
|
|
136
|
+
proxy[Symbol.dispose]();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should allow manual unsubscribe of a blocker', () => {
|
|
140
|
+
const blocker = vi.fn();
|
|
141
|
+
const unblock = proxy.block(blocker);
|
|
142
|
+
|
|
143
|
+
unblock();
|
|
144
|
+
|
|
145
|
+
// No error on dispose — the blocker was already removed
|
|
146
|
+
proxy[Symbol.dispose]();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Subscription } from 'rxjs';
|
|
2
|
+
import type { Observable } from 'rxjs';
|
|
3
|
+
|
|
4
|
+
import type { BaseHistory } from './BaseHistory';
|
|
5
|
+
import type {
|
|
6
|
+
History,
|
|
7
|
+
NavigateOptions,
|
|
8
|
+
NavigationBlocker,
|
|
9
|
+
NavigationListener,
|
|
10
|
+
NavigationUpdate,
|
|
11
|
+
Path,
|
|
12
|
+
To,
|
|
13
|
+
} from './types';
|
|
14
|
+
import type { Actions } from './state/history.actions';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A lightweight proxy that delegates every {@link History} operation to an
|
|
18
|
+
* underlying target instance.
|
|
19
|
+
*
|
|
20
|
+
* Use this when you need to pass a conforming `History` object whose backing
|
|
21
|
+
* implementation can be swapped or is not yet available at construction time,
|
|
22
|
+
* or when you want a thin indirection layer without subclassing
|
|
23
|
+
* {@link BaseHistory}.
|
|
24
|
+
*
|
|
25
|
+
* The proxy does **not** own the underlying history; disposing it only tears
|
|
26
|
+
* down subscriptions and blockers registered through the proxy itself.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const browser = createHistory('browser');
|
|
31
|
+
* const proxy = new ProxyHistory(browser);
|
|
32
|
+
* proxy.push('/dashboard'); // delegates to browser.push
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export class ProxyHistory implements History {
|
|
36
|
+
/** The underlying history instance all calls are forwarded to. */
|
|
37
|
+
readonly #target: History;
|
|
38
|
+
|
|
39
|
+
/** Teardowns owned by this proxy, cleaned up on dispose. */
|
|
40
|
+
readonly #teardowns = new Subscription();
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param target - The history instance to delegate all operations to
|
|
44
|
+
*/
|
|
45
|
+
constructor(target: History) {
|
|
46
|
+
this.#target = target;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** @inheritdoc */
|
|
50
|
+
get state$(): Observable<NavigationUpdate> {
|
|
51
|
+
return this.#target.state$;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** @inheritdoc */
|
|
55
|
+
get action$(): Observable<Actions> {
|
|
56
|
+
return this.#target.action$;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** @inheritdoc */
|
|
60
|
+
get action(): History['action'] {
|
|
61
|
+
return this.#target.action;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** @inheritdoc */
|
|
65
|
+
get location(): History['location'] {
|
|
66
|
+
return this.#target.location;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** @inheritdoc */
|
|
70
|
+
createHref(to: To): string {
|
|
71
|
+
return this.#target.createHref(to);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** @inheritdoc */
|
|
75
|
+
createURL(to: To): URL {
|
|
76
|
+
return this.#target.createURL(to);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** @inheritdoc */
|
|
80
|
+
encodeLocation(to: To): Path {
|
|
81
|
+
return this.#target.encodeLocation(to);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** @inheritdoc */
|
|
85
|
+
push(to: To, state?: unknown): void {
|
|
86
|
+
this.#target.push(to, state);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** @inheritdoc */
|
|
90
|
+
replace(to: To, state?: unknown): void {
|
|
91
|
+
this.#target.replace(to, state);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @inheritdoc */
|
|
95
|
+
navigate(to: To, options?: NavigateOptions): void {
|
|
96
|
+
this.#target.navigate(to, options);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** @inheritdoc */
|
|
100
|
+
go(delta: number): void {
|
|
101
|
+
this.#target.go(delta);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Triggers a POP action on the underlying history to notify framework
|
|
106
|
+
* listeners (e.g. React Router) after programmatic navigation.
|
|
107
|
+
*
|
|
108
|
+
* Delegates to the target's `pop()` when it is a {@link BaseHistory}
|
|
109
|
+
* instance; otherwise this is a no-op.
|
|
110
|
+
*/
|
|
111
|
+
pop(): void {
|
|
112
|
+
if ('pop' in this.#target && typeof this.#target.pop === 'function') {
|
|
113
|
+
(this.#target as BaseHistory).pop();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** @inheritdoc */
|
|
118
|
+
listen(listener: NavigationListener): () => void {
|
|
119
|
+
const unlisten = this.#target.listen(listener);
|
|
120
|
+
this.#teardowns.add(unlisten);
|
|
121
|
+
return () => {
|
|
122
|
+
unlisten();
|
|
123
|
+
this.#teardowns.remove(unlisten);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** @inheritdoc */
|
|
128
|
+
block(blocker: NavigationBlocker): VoidFunction {
|
|
129
|
+
const unblock = this.#target.block(blocker);
|
|
130
|
+
this.#teardowns.add(unblock);
|
|
131
|
+
return () => {
|
|
132
|
+
unblock();
|
|
133
|
+
this.#teardowns.remove(unblock);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Disposes all listeners and blockers registered through this proxy.
|
|
139
|
+
* Does **not** dispose the underlying history.
|
|
140
|
+
*/
|
|
141
|
+
[Symbol.dispose](): void {
|
|
142
|
+
this.#teardowns.unsubscribe();
|
|
143
|
+
}
|
|
144
|
+
}
|
package/src/lib/index.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
export { BaseHistory } from './BaseHistory';
|
|
13
13
|
export { BrowserHistory } from './BrowserHistory';
|
|
14
14
|
export { MemoryHistory } from './MemoryHistory';
|
|
15
|
+
export { ProxyHistory } from './ProxyHistory';
|
|
15
16
|
|
|
16
17
|
// History stacks
|
|
17
18
|
export { BrowserHistoryStack } from './BrowserHistoryStack';
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '7.0.
|
|
2
|
+
export const version = '7.0.2';
|