@equinor/fusion-framework-module-navigation 7.0.0-next.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +32 -24
  2. package/README.md +97 -614
  3. package/dist/esm/NavigationProvider.js +57 -23
  4. package/dist/esm/NavigationProvider.js.map +1 -1
  5. package/dist/esm/events.js +20 -3
  6. package/dist/esm/events.js.map +1 -1
  7. package/dist/esm/index.js +23 -0
  8. package/dist/esm/index.js.map +1 -1
  9. package/dist/esm/lib/BaseHistory.js +23 -6
  10. package/dist/esm/lib/BaseHistory.js.map +1 -1
  11. package/dist/esm/lib/BrowserHistoryStack.js +5 -6
  12. package/dist/esm/lib/BrowserHistoryStack.js.map +1 -1
  13. package/dist/esm/lib/MemoryHistory.js +13 -6
  14. package/dist/esm/lib/MemoryHistory.js.map +1 -1
  15. package/dist/esm/lib/MemoryStack.js +1 -0
  16. package/dist/esm/lib/MemoryStack.js.map +1 -1
  17. package/dist/esm/lib/create-history.js +7 -13
  18. package/dist/esm/lib/create-history.js.map +1 -1
  19. package/dist/esm/lib/index.js +9 -0
  20. package/dist/esm/lib/index.js.map +1 -1
  21. package/dist/esm/lib/state/history.flows.js +7 -12
  22. package/dist/esm/lib/state/history.flows.js.map +1 -1
  23. package/dist/esm/lib/state/history.reducer.js +8 -4
  24. package/dist/esm/lib/state/history.reducer.js.map +1 -1
  25. package/dist/esm/lib/state/history.state.js +9 -3
  26. package/dist/esm/lib/state/history.state.js.map +1 -1
  27. package/dist/esm/lib/utils/resolve-browser-location.js +2 -2
  28. package/dist/esm/lib/utils/resolve-browser-location.js.map +1 -1
  29. package/dist/esm/module.js +4 -4
  30. package/dist/esm/version.js +1 -1
  31. package/dist/esm/version.js.map +1 -1
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/dist/types/NavigationConfigurator.interface.d.ts +25 -5
  34. package/dist/types/NavigationProvider.d.ts +57 -23
  35. package/dist/types/NavigationProvider.interface.d.ts +20 -7
  36. package/dist/types/events.d.ts +20 -3
  37. package/dist/types/index.d.ts +24 -1
  38. package/dist/types/lib/BaseHistory.d.ts +23 -6
  39. package/dist/types/lib/BrowserHistoryStack.d.ts +5 -6
  40. package/dist/types/lib/MemoryHistory.d.ts +5 -5
  41. package/dist/types/lib/create-history.d.ts +7 -13
  42. package/dist/types/lib/index.d.ts +9 -0
  43. package/dist/types/lib/state/history.flows.d.ts +6 -11
  44. package/dist/types/lib/state/history.reducer.d.ts +8 -4
  45. package/dist/types/lib/state/history.state.d.ts +9 -3
  46. package/dist/types/lib/types.d.ts +39 -8
  47. package/dist/types/version.d.ts +1 -1
  48. package/package.json +11 -12
  49. package/src/NavigationConfigurator.interface.ts +28 -5
  50. package/src/NavigationProvider.interface.ts +20 -7
  51. package/src/NavigationProvider.ts +57 -23
  52. package/src/events.ts +20 -3
  53. package/src/index.ts +25 -1
  54. package/src/lib/BaseHistory.ts +23 -6
  55. package/src/lib/BrowserHistoryStack.ts +5 -6
  56. package/src/lib/MemoryHistory.ts +13 -6
  57. package/src/lib/MemoryStack.ts +1 -0
  58. package/src/lib/create-history.ts +7 -13
  59. package/src/lib/index.ts +10 -0
  60. package/src/lib/state/history.flows.ts +7 -12
  61. package/src/lib/state/history.reducer.ts +8 -4
  62. package/src/lib/state/history.state.ts +9 -3
  63. package/src/lib/types.ts +39 -8
  64. package/src/lib/utils/resolve-browser-location.ts +2 -2
  65. package/src/module.ts +4 -4
  66. package/src/version.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-navigation",
3
- "version": "7.0.0-next.2",
3
+ "version": "7.0.0",
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",
@@ -33,24 +33,23 @@
33
33
  "dependencies": {
34
34
  "@remix-run/router": "^1.23.0",
35
35
  "uuid": "^13.0.0",
36
- "zod": "^4.1.11"
36
+ "zod": "^4.3.6"
37
37
  },
38
38
  "devDependencies": {
39
- "@types/uuid": "^11.0.0",
40
39
  "jsdom": "^27.1.0",
41
40
  "rxjs": "^7.8.1",
42
- "typescript": "^5.8.2",
43
- "vitest": "^3.2.4",
44
- "@equinor/fusion-framework-module": "^5.0.7-next.0",
45
- "@equinor/fusion-framework-module-event": "^5.0.2-next.0",
46
- "@equinor/fusion-framework-module-telemetry": "^4.6.5-next.0",
47
- "@equinor/fusion-observable": "^8.5.9-next.0"
41
+ "typescript": "^5.9.3",
42
+ "vitest": "^4.1.0",
43
+ "@equinor/fusion-framework-module": "^6.0.0",
44
+ "@equinor/fusion-framework-module-event": "^6.0.0",
45
+ "@equinor/fusion-framework-module-telemetry": "^5.0.0",
46
+ "@equinor/fusion-observable": "^9.0.0"
48
47
  },
49
48
  "peerDependencies": {
50
- "@remix-run/router": "^1.23.0",
49
+ "@remix-run/router": "^1.0.0",
51
50
  "rxjs": "^7.0.0",
52
- "@equinor/fusion-framework-module": "^5.0.7-next.0",
53
- "@equinor/fusion-observable": "^8.5.9-next.0"
51
+ "@equinor/fusion-framework-module": "^6.0.0",
52
+ "@equinor/fusion-observable": "^9.0.0"
54
53
  },
55
54
  "scripts": {
56
55
  "build": "tsc -b",
@@ -4,15 +4,38 @@ import type { IEventModuleProvider } from '@equinor/fusion-framework-module-even
4
4
 
5
5
  /**
6
6
  * Configuration object for the navigation module.
7
- * Provides options for customizing history, basename, telemetry, and event settings.
7
+ *
8
+ * Provides options for customizing the history implementation, basename prefix,
9
+ * telemetry tracking, and event dispatching used by the {@link NavigationProvider}.
8
10
  */
9
11
  export interface INavigationConfigurator {
10
- /** Optional base pathname for the application (e.g., "/app") */
12
+ /**
13
+ * Base pathname prefix for the application (e.g. `"/apps/my-app"`).
14
+ *
15
+ * When set, the navigation provider automatically prepends this prefix to
16
+ * outgoing paths and strips it from incoming paths, so consumer code
17
+ * operates on clean, basename-free paths.
18
+ */
11
19
  basename?: string;
12
- /** Optional custom history instance (browser, hash, or memory). If not provided, defaults to browser history. */
20
+
21
+ /**
22
+ * Custom {@link History} instance for navigation.
23
+ *
24
+ * If not provided, defaults to browser history in browser environments
25
+ * or memory history in Node.js environments. Create instances with
26
+ * {@link createHistory}.
27
+ */
13
28
  history?: History;
14
- /** Optional telemetry provider for tracking navigation events */
29
+
30
+ /**
31
+ * Telemetry provider for tracking navigation events, location changes,
32
+ * and errors for monitoring and debugging.
33
+ */
15
34
  telemetry?: ITelemetryProvider;
16
- /** Optional event provider for dispatching navigation events */
35
+
36
+ /**
37
+ * Event provider for dispatching {@link NavigateEvent} and {@link NavigatedEvent}.
38
+ * Allows other modules to listen for and react to navigation changes.
39
+ */
17
40
  eventProvider?: IEventModuleProvider;
18
41
  }
@@ -9,7 +9,17 @@ import type { IModuleProvider } from '@equinor/fusion-framework-module';
9
9
 
10
10
  /**
11
11
  * Navigation provider interface.
12
- * Provides routing and navigation capabilities with basename localization.
12
+ *
13
+ * Provides routing and navigation capabilities with automatic basename
14
+ * localization. Consumers work with clean paths (e.g. `/users`) while the
15
+ * underlying history operates on full paths (e.g. `/apps/my-app/users`).
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * const nav: INavigationProvider = framework.modules.navigation;
20
+ * nav.push('/users');
21
+ * console.log(nav.path.pathname); // '/users'
22
+ * ```
13
23
  */
14
24
  export interface INavigationProvider extends IModuleProvider {
15
25
  /**
@@ -41,22 +51,25 @@ export interface INavigationProvider extends IModuleProvider {
41
51
  /**
42
52
  * Creates a router instance from route configuration.
43
53
  *
44
- * @param routes - Route configuration objects compatible with industry-standard routers (Remix/React Router)
45
- * @returns A configured and initialized router instance
54
+ * @deprecated Use `@equinor/fusion-framework-react-router` instead.
55
+ * @param routes - Route configuration objects compatible with Remix/React Router
56
+ * @returns A configured and initialized {@link Router} instance with basename applied
46
57
  */
47
58
  createRouter(routes: AgnosticRouteObject[]): Router;
48
59
 
49
60
  /**
50
- * Creates a localized href string for navigation.
61
+ * Creates a localized href string including the basename prefix.
51
62
  *
52
- * @param to - Optional path or location (defaults to current path)
63
+ * @param to - Path or location to resolve (defaults to current path)
64
+ * @returns Fully-qualified href string with basename included
53
65
  */
54
66
  createHref(to?: To): string;
55
67
 
56
68
  /**
57
- * Creates a full URL object for navigation.
69
+ * Creates a full {@link URL} object including the basename prefix.
58
70
  *
59
- * @param to - Optional path or location (defaults to current path)
71
+ * @param to - Path or location to resolve (defaults to current path)
72
+ * @returns A {@link URL} instance representing the resolved navigation target
60
73
  */
61
74
  createURL(to?: To): URL;
62
75
 
@@ -37,17 +37,23 @@ const normalizePathname = (path: string) => path.replace(/\/+/g, '/').replace(/\
37
37
 
38
38
  /**
39
39
  * Navigation provider implementation.
40
- * Manages routing and navigation state with basename localization.
40
+ *
41
+ * Manages routing and navigation state with automatic basename localization.
42
+ * Wraps a {@link History} instance to expose observable state, path localization,
43
+ * and router creation.
41
44
  *
42
45
  * @remarks
43
- * This provider:
44
- * - Wraps the Navigator to provide observable navigation state
45
- * - Localizes paths by removing basename prefix
46
- * - Creates routers compatible with industry-standard routers (Remix/React Router)
47
- * - Handles navigation actions (push, replace, createHref, etc.)
46
+ * - Emits localized paths (basename removed) to consumers via {@link NavigationProvider.state$ | state$}
47
+ * - Internally prefixes paths with the basename before forwarding to the history stack
48
+ * - Creates routers compatible with Remix / React Router via {@link NavigationProvider.createRouter | createRouter}
49
+ * - Dispatches {@link NavigatedEvent} and telemetry on navigation changes
48
50
  *
49
- * Path localization ensures that consumers receive paths relative to the basename,
50
- * while internally we work with full paths including basename.
51
+ * @example
52
+ * ```ts
53
+ * const provider = new NavigationProvider({ version, config });
54
+ * provider.push('/users');
55
+ * console.log(provider.path.pathname); // '/users'
56
+ * ```
51
57
  */
52
58
  export class NavigationProvider
53
59
  extends BaseModuleProvider<INavigationConfigurator>
@@ -62,14 +68,19 @@ export class NavigationProvider
62
68
 
63
69
  /**
64
70
  * Observable stream of navigation state updates.
65
- * Emits localized paths (with basename removed) for consumers.
71
+ *
72
+ * Emits localized paths (with basename removed) and filters to only
73
+ * paths within the basename scope. Late subscribers receive the last
74
+ * emitted value immediately.
66
75
  */
67
76
  public get state$(): Observable<NavigationUpdate> {
68
77
  return this.#state$;
69
78
  }
70
79
 
71
80
  /**
72
- * Gets the basename.
81
+ * Gets the basename prefix configured for this provider.
82
+ *
83
+ * @returns The basename string, or an empty string if none is configured
73
84
  */
74
85
  public get basename(): string {
75
86
  return this.#basename ?? '';
@@ -89,22 +100,28 @@ export class NavigationProvider
89
100
  }
90
101
 
91
102
  /**
92
- * Gets the history instance.
103
+ * Gets the underlying history instance.
104
+ *
105
+ * @returns The {@link History} instance used for navigation
93
106
  */
94
107
  public get history(): History {
95
108
  return this.#history;
96
109
  }
97
110
 
98
111
  /**
99
- * Gets the current localized path (basename removed).
112
+ * Gets the current localized path with the basename prefix removed.
113
+ *
114
+ * @returns A {@link Path} object representing the current location without basename
100
115
  */
101
116
  public get path(): Path {
102
117
  return this._localizePath(this.#history.location);
103
118
  }
104
119
 
105
120
  /**
121
+ * Creates a new {@link NavigationProvider}.
122
+ *
106
123
  * @param args - Configuration arguments containing module config
107
- * @throws {Error} If no history is provided in the configuration
124
+ * @throws {Error} If no history instance is provided in the configuration
108
125
  */
109
126
  constructor(args: BaseModuleProviderCtorArgs<INavigationConfigurator>) {
110
127
  super(args);
@@ -201,10 +218,10 @@ export class NavigationProvider
201
218
  /**
202
219
  * Creates a router instance from route configuration.
203
220
  *
204
- * @deprecated Use `@equinor/fusion-framework-react-router` instead
221
+ * @deprecated Use `@equinor/fusion-framework-react-router` instead.
205
222
  *
206
- * @param routes - Route configuration objects compatible with industry-standard routers (Remix/React Router)
207
- * @returns A configured and initialized router instance
223
+ * @param routes - Route configuration objects compatible with Remix/React Router
224
+ * @returns A configured and initialized {@link Router} instance with basename applied
208
225
  */
209
226
  public createRouter(routes: AgnosticRouteObject[]) {
210
227
  this.#telemetry?.trackEvent({
@@ -225,18 +242,26 @@ export class NavigationProvider
225
242
  }
226
243
 
227
244
  /**
228
- * Creates a localized href string for navigation.
245
+ * Creates a localized href string including the basename prefix.
229
246
  *
230
- * @param to - Optional path or location (defaults to current path)
247
+ * @param to - Path or location to resolve (defaults to current path)
248
+ * @returns Fully-qualified href string with basename included
249
+ *
250
+ * @example
251
+ * ```ts
252
+ * // basename = '/apps/my-app'
253
+ * provider.createHref('/users'); // '/apps/my-app/users'
254
+ * ```
231
255
  */
232
256
  public createHref(to?: To): string {
233
257
  return this.#history.createHref(this._createToPath(to ?? this.path));
234
258
  }
235
259
 
236
260
  /**
237
- * Creates a full URL object for navigation.
261
+ * Creates a full {@link URL} object including the basename prefix.
238
262
  *
239
- * @param to - Optional path or location (defaults to current path)
263
+ * @param to - Path or location to resolve (defaults to current path)
264
+ * @returns A {@link URL} instance representing the resolved navigation target
240
265
  */
241
266
  public createURL(to?: To): URL {
242
267
  return this.#history.createURL(this._createToPath(to ?? this.path));
@@ -277,14 +302,20 @@ export class NavigationProvider
277
302
  (this.#history as BaseHistory).pop();
278
303
  }
279
304
  /**
280
- * Checks if a pathname is within the basename scope.
305
+ * Checks whether a pathname falls within the configured basename scope.
306
+ *
307
+ * @param pathname - The pathname to check
308
+ * @returns `true` if the pathname starts with the basename (or no basename is set)
281
309
  */
282
310
  protected _isWithinBasenameScope(pathname: string): boolean {
283
311
  return this.#basename ? pathname.startsWith(this.#basename) : true;
284
312
  }
285
313
 
286
314
  /**
287
- * Localizes a path by removing the basename prefix.
315
+ * Localizes a path by stripping the basename prefix from the pathname.
316
+ *
317
+ * @param location - The full path to localize
318
+ * @returns A new {@link Path} with the basename removed from the pathname
288
319
  */
289
320
  protected _localizePath(location: Path): Path {
290
321
  const { pathname, search, hash } = location;
@@ -296,7 +327,10 @@ export class NavigationProvider
296
327
  }
297
328
 
298
329
  /**
299
- * Creates a full path object from a target location, adding basename prefix.
330
+ * Creates a full path object from a target location, prepending the basename prefix.
331
+ *
332
+ * @param to - The target location (string path or partial {@link Path} object)
333
+ * @returns A partial {@link Path} with basename prepended to the pathname
300
334
  */
301
335
  protected _createToPath(to: To): Partial<Path> {
302
336
  // Parse the 'to' parameter into path components
package/src/events.ts CHANGED
@@ -15,7 +15,16 @@ export interface NavigateEventDetail {
15
15
 
16
16
  /**
17
17
  * Event emitted before navigation occurs.
18
- * Can be canceled by calling `preventDefault()`.
18
+ * Can be canceled by calling `preventDefault()` to block the navigation.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * eventProvider.addEventListener('onNavigate', (event) => {
23
+ * if (hasUnsavedChanges) {
24
+ * event.preventDefault();
25
+ * }
26
+ * });
27
+ * ```
19
28
  */
20
29
  export class NavigateEvent extends FrameworkEvent<
21
30
  FrameworkEventInit<NavigateEventDetail, INavigationProvider>
@@ -41,8 +50,16 @@ export interface NavigatedEventDetail {
41
50
  }
42
51
 
43
52
  /**
44
- * Event emitted after navigation occurs.
45
- * Contains the navigation action and location details.
53
+ * Event emitted after navigation completes.
54
+ * Contains the navigation action type and both current and previous locations.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * eventProvider.addEventListener('onNavigated', (event) => {
59
+ * const { action, current, previous } = event.detail;
60
+ * console.log(`${action}: ${previous.location.pathname} → ${current.location.pathname}`);
61
+ * });
62
+ * ```
46
63
  */
47
64
  export class NavigatedEvent extends FrameworkEvent<
48
65
  FrameworkEventInit<NavigatedEventDetail, INavigationProvider>
package/src/index.ts CHANGED
@@ -1,3 +1,27 @@
1
+ /**
2
+ * @module @equinor/fusion-framework-module-navigation
3
+ *
4
+ * Navigation module for Fusion Framework providing routing and navigation capabilities.
5
+ *
6
+ * Manages observable navigation state with automatic basename localization,
7
+ * so consumers work with clean paths while the underlying history receives
8
+ * full paths including the basename prefix.
9
+ *
10
+ * @remarks
11
+ * Supports browser, hash, and memory history types. Integrates with
12
+ * `@remix-run/router` for router creation and is compatible with
13
+ * industry-standard routers (Remix / React Router).
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { enableNavigation, createHistory } from '@equinor/fusion-framework-module-navigation';
18
+ *
19
+ * enableNavigation(configurator, '/apps/my-app');
20
+ * ```
21
+ *
22
+ * @packageDocumentation
23
+ */
24
+
1
25
  export type { INavigationConfigurator } from './NavigationConfigurator.interface';
2
26
  export { NavigationConfigurator } from './NavigationConfigurator';
3
27
 
@@ -26,6 +50,6 @@ export type {
26
50
  } from './lib/types';
27
51
 
28
52
  /**
29
- * @deprecated use History instead
53
+ * @deprecated Use {@link History} instead.
30
54
  */
31
55
  export type { History as INavigator } from './lib';
@@ -16,8 +16,10 @@ import type {
16
16
 
17
17
  /**
18
18
  * Abstract base class for history implementations.
19
- * Provides common state management and navigation logic that can be shared
20
- * across different history implementations (browser, memory, etc.).
19
+ *
20
+ * Provides common state management, navigation logic, and subscription
21
+ * lifecycle that is shared across different history backends (browser,
22
+ * hash, memory).
21
23
  */
22
24
  export abstract class BaseHistory implements History {
23
25
  // Subscriptions for cleanup
@@ -27,14 +29,18 @@ export abstract class BaseHistory implements History {
27
29
  #state: HistoryState;
28
30
 
29
31
  /**
30
- * Gets the current location.
32
+ * Gets the current location in the history stack.
33
+ *
34
+ * @returns The current {@link Location} including pathname, search, hash, state, and key
31
35
  */
32
36
  public get location(): History['location'] {
33
37
  return this.#state.subject.value.current.location;
34
38
  }
35
39
 
36
40
  /**
37
- * Gets the current action.
41
+ * Gets the current navigation action type.
42
+ *
43
+ * @returns The most recent {@link Action} (`Pop`, `Push`, or `Replace`)
38
44
  */
39
45
  public get action(): History['action'] {
40
46
  return this.#state.subject.value.current.action;
@@ -56,7 +62,9 @@ export abstract class BaseHistory implements History {
56
62
  }
57
63
 
58
64
  /**
59
- * Checks if there are any active navigation blockers.
65
+ * Checks whether there are any active navigation blockers.
66
+ *
67
+ * @returns `true` if one or more blockers are registered
60
68
  */
61
69
  public get hasBlockers(): boolean {
62
70
  return this.#state.subject.value.blockers.length > 0;
@@ -68,13 +76,19 @@ export abstract class BaseHistory implements History {
68
76
 
69
77
  /**
70
78
  * Creates a valid href string for a given path.
79
+ *
80
+ * @param to - Target path or partial path object
81
+ * @returns Fully-qualified href string
71
82
  */
72
83
  public createHref(to: To): string {
73
84
  return this.createURL(to).href;
74
85
  }
75
86
 
76
87
  /**
77
- * Creates a URL object for a given path.
88
+ * Creates a {@link URL} object for a given path.
89
+ *
90
+ * @param to - Target path or partial path object
91
+ * @returns Resolved {@link URL} instance
78
92
  */
79
93
  public createURL(to: To): URL {
80
94
  return this.#state.stack.createURL(to);
@@ -82,6 +96,9 @@ export abstract class BaseHistory implements History {
82
96
 
83
97
  /**
84
98
  * Encodes a location by properly URL-encoding the pathname.
99
+ *
100
+ * @param to - Target path or partial path object
101
+ * @returns A {@link Path} with URL-encoded components
85
102
  */
86
103
  public encodeLocation(to: To): Path {
87
104
  return this.#state.stack.createURL(to);
@@ -2,17 +2,16 @@ import { pathToString, resolvePath, resolveWindowLocation } from './utils';
2
2
  import type { HistoryStack, Location, To } from './types';
3
3
 
4
4
  /**
5
- * Browser history stack implementation using native browser APIs.
5
+ * Browser history stack implementation using the native History API.
6
6
  *
7
- * Manages navigation state using the browser's History API (pushState/replaceState).
8
- * Stores location state in history.state and uses relative paths for navigation.
9
- * This is the base implementation for regular (non-hash) routing.
7
+ * Manages navigation state via `pushState` / `replaceState` and stores
8
+ * location state in `history.state`. This is the default stack for
9
+ * pathname-based (non-hash) routing.
10
10
  *
11
11
  * @example
12
12
  * ```ts
13
13
  * const stack = new BrowserHistoryStack(window);
14
- * stack.push({ pathname: '/users', key: 'abc123', state: { userId: 1 } });
15
- * // Updates URL to /users and adds entry to history
14
+ * stack.push({ pathname: '/users', search: '', hash: '', key: 'abc', state: null });
16
15
  * ```
17
16
  */
18
17
  export class BrowserHistoryStack implements HistoryStack {
@@ -10,7 +10,14 @@ import { createHistoryReducer, createStore } from './state';
10
10
  const defaultInitialLocation: NavigationUpdate = {
11
11
  delta: 0,
12
12
  action: Action.Pop,
13
- location: { pathname: '/', search: '', hash: '', key: 'unknown', state: null },
13
+ location: {
14
+ pathname: '/',
15
+ search: '',
16
+ hash: '',
17
+ key: 'unknown',
18
+ state: null,
19
+ unstable_mask: undefined,
20
+ },
14
21
  };
15
22
 
16
23
  /**
@@ -26,11 +33,11 @@ export type MemoryHistoryOptions = {
26
33
  /**
27
34
  * Memory history implementation using in-memory storage.
28
35
  *
29
- * Useful for:
30
- * - Testing: Control navigation state in tests without browser APIs
31
- * - SSR: Server-side rendering where window is not available
32
- * - Widgets: Serving applications as widgets without affecting the main browser history
33
- * - Node.js environments: Environments without browser APIs
36
+ * Does not touch browser APIs, making it suitable for:
37
+ * - **Testing** deterministic navigation state without a DOM
38
+ * - **SSR** — server-side rendering where `window` is unavailable
39
+ * - **Widgets** embedded apps that must not alter the host page URL
40
+ * - **Node.js** any environment without browser history APIs
34
41
  */
35
42
  export class MemoryHistory extends BaseHistory {
36
43
  public constructor(options?: MemoryHistoryOptions) {
@@ -39,6 +39,7 @@ export class MemoryHistoryStack implements HistoryStack {
39
39
  hash: '',
40
40
  state: null,
41
41
  key: '',
42
+ unstable_mask: undefined,
42
43
  };
43
44
  }
44
45
 
@@ -13,25 +13,19 @@ type HistoryCtorMap = {
13
13
  * Creates a history instance based on the specified type.
14
14
  *
15
15
  * Factory function for creating different history implementations:
16
- * - `'browser'`: Creates a {@link BrowserHistory} instance using regular routing (pathname-based)
17
- * - `'hash'`: Creates a {@link BrowserHistory} instance using hash routing (hash-based)
18
- * - `'memory'`: Creates a {@link MemoryHistory} instance for testing or SSR (in-memory)
16
+ * - `'browser'`: Creates a {@link BrowserHistory} using pathname-based routing
17
+ * - `'hash'`: Creates a {@link BrowserHistory} using hash-based routing (`#/path`)
18
+ * - `'memory'`: Creates a {@link MemoryHistory} for testing, SSR, or widget apps
19
19
  *
20
- * All returned instances are compatible with industry-standard routers (Remix/React Router).
21
- *
22
- * @param type - The type of history to create ('browser', 'hash', or 'memory')
23
- * @param args - Optional arguments for the history type
24
- * @returns A History instance compatible with industry-standard routers (Remix/React Router)
20
+ * @param type - The type of history to create (`'browser'`, `'hash'`, or `'memory'`)
21
+ * @param args - Optional arguments forwarded to the history constructor
22
+ * @returns A {@link History} instance of the requested type
23
+ * @throws {Error} If `type` is not one of `'browser'`, `'hash'`, or `'memory'`
25
24
  *
26
25
  * @example
27
26
  * ```ts
28
- * // Regular browser routing
29
27
  * const history = createHistory('browser');
30
- *
31
- * // Hash-based routing
32
28
  * const hashHistory = createHistory('hash');
33
- *
34
- * // In-memory history for testing
35
29
  * const memoryHistory = createHistory('memory', { initialLocation: { ... } });
36
30
  * ```
37
31
  */
package/src/lib/index.ts CHANGED
@@ -1,3 +1,13 @@
1
+ /**
2
+ * Internal history implementations, stacks, and types.
3
+ *
4
+ * @remarks
5
+ * This sub-module is re-exported as `@equinor/fusion-framework-module-navigation/lib`
6
+ * and provides the low-level building blocks for navigation state management.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+
1
11
  // History implementations
2
12
  export { BaseHistory } from './BaseHistory';
3
13
  export { BrowserHistory } from './BrowserHistory';
@@ -47,7 +47,7 @@ export const navigate: HistoryFlowCreator =
47
47
  const path = resolvePath(payload.to);
48
48
  const key = meta.key;
49
49
  const { replace, state } = payload.options;
50
- const nextLocation = { ...path, key, state } satisfies Location;
50
+ const nextLocation = { ...path, key, state, unstable_mask: undefined } satisfies Location;
51
51
  // prevent death loop navigation
52
52
  if (compareLocation(nextLocation, stack.current)) {
53
53
  return actions.abortNavigate('Location is the same as the current location');
@@ -233,19 +233,14 @@ export const validateCurrentLocation: HistoryFlowCreator =
233
233
  /**
234
234
  * Creates a combined history flow from multiple flow creators.
235
235
  *
236
- * Execution flow:
237
- * 1. Creates a preprocessing step that applies blocker checking (unless skipped)
238
- * 2. Initializes each flow creator with the stack to create individual flows
239
- * 3. Merges all flows so they process actions in parallel
240
- * 4. Returns a combined flow that:
241
- * - First applies preprocessing (blocker checking)
242
- * - Then processes actions through all merged flows
243
- * - Emits results from any flow that matches the action
236
+ * Merges all provided flows so they process actions in parallel.
237
+ * Optionally prepends a blocker-checking step that gates navigation
238
+ * actions through registered {@link NavigationBlocker | blockers}.
244
239
  *
245
240
  * @param flowCreators - Array of flow creators to combine
246
- * @param options - Optional configuration options
247
- * @param options.skipBlockCheck - If true, skip blocker checking
248
- * @returns A combined history flow creator
241
+ * @param options - Optional configuration
242
+ * @param options.skipBlockCheck - If `true`, skip blocker checking
243
+ * @returns A combined {@link HistoryFlowCreator} that merges all provided flows
249
244
  */
250
245
  export const createFlow = (
251
246
  flowCreators: HistoryFlowCreator[],
@@ -14,10 +14,14 @@ const findIndex = (state: LocationState) => {
14
14
  /**
15
15
  * Creates a reducer for history state management.
16
16
  *
17
- * @param initial - Initial navigation update or function that returns initial state
18
- * @param options - Optional configuration options
19
- * @param options.maxHistory - Maximum number of history entries to keep (default: 100)
20
- * @returns A reducer for history state
17
+ * Handles navigate, go, and pop success actions by updating the
18
+ * history array and current location. Enforces a maximum history
19
+ * length to prevent unbounded memory growth.
20
+ *
21
+ * @param initial - Initial navigation update or factory returning initial state
22
+ * @param options - Optional configuration
23
+ * @param options.maxHistory - Maximum number of history entries to keep (default: `100`)
24
+ * @returns A reducer with initial state for use with {@link createStore}
21
25
  */
22
26
  export const createHistoryReducer = (
23
27
  initial: NavigationUpdate | (() => LocationState),
@@ -22,10 +22,16 @@ export const defaultFlows = [flowCreators.navigate, flowCreators.go, flowCreator
22
22
  /**
23
23
  * Creates a history store with the specified stack and reducer.
24
24
  *
25
- * @param stack - The history stack implementation
26
- * @param reducer - The reducer for history state
25
+ * Combines the reactive state container with a {@link HistoryStack} and wires
26
+ * up navigation flows for action processing.
27
+ *
28
+ * @param stack - The history stack implementation (browser, hash, or memory)
29
+ * @param reducer - The reducer that handles state transitions
27
30
  * @param options - Optional configuration options
28
- * @returns A HistoryState instance
31
+ * @param options.flows - Custom flow creators (defaults to {@link defaultFlows})
32
+ * @param options.skipBlockCheck - Skip blocker checking in flows
33
+ * @param options.validateCurrentLocation - Add location validation flow
34
+ * @returns A fully-initialized {@link HistoryState} with flows attached
29
35
  */
30
36
  export const createStore = (
31
37
  stack: HistoryStack,