@mmstack/router-core 19.2.9 → 19.3.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.
package/README.md CHANGED
@@ -146,3 +146,113 @@ import { RouterLink } from '@angular/router';
146
146
  })
147
147
  export class NavigationComponent {}
148
148
  ```
149
+
150
+ ## Headless breadcrumb utilities
151
+
152
+ This library includes a signal-based, headless toolkit for generating and managing breadcrumbs in your Angular application. It provides the logic to derive breadcrumb data from your routes, allowing you to easily build a completely custom breadcrumb UI component & let the library worry about active routes :)
153
+
154
+ ### Consuming breadcrumbs
155
+
156
+ The primary way to access the breadcrumb data is via the `injectBreadcrumbs` function. It returns a `Signal<Breadcrumb[]>` that updates automatically as navigation changes. Each `Breadcrumb` object in the array contains reactive signals for its `label`, `link`, `ariaLabel`, and a static id for iteration purposes.
157
+
158
+ ```typescript
159
+ import { Component } from '@angular/core';
160
+ import { injectBreadcrumbs } from '@mmstack/router-core'; // Adjust path if needed
161
+
162
+ @Component({
163
+ selector: 'app-breadcrumbs',
164
+ standalone: true,
165
+ template: `
166
+ <nav aria-label="breadcrumb">
167
+ <ol>
168
+ @for (crumb of breadcrumbs(); track crumb.id) {
169
+ <li>
170
+ <a [href]="crumb.link()" [attr.aria-label]="crumb.ariaLabel()">{{ crumb.label() }}</a>
171
+ </li>
172
+ }
173
+ </ol>
174
+ </nav>
175
+ `,
176
+ })
177
+ export class CustomBreadcrumbsComponent {
178
+ protected readonly breadcrumbs = injectBreadcrumbs();
179
+ }
180
+ ```
181
+
182
+ ### Registering custom breadcrumbs
183
+
184
+ For routes where automatic breadcrumb generation isn't sufficient or when you need more control, you can manually define breadcrumbs using the `createBreadcrumb` route resolver.
185
+
186
+ This function allows you to specify the label (static or dynamic via a function) and other properties for a breadcrumb associated with a particular route.
187
+ You can use injection in the factory function, as you would with any resolver, making translations or subscribing to dynamic data a breaze! :)
188
+
189
+ ```typescript
190
+ import { Routes } from '@angular/router';
191
+ import { createBreadcrumb } from '@mmstack/router-core';
192
+ import { HomeComponent } from './home.component';
193
+ import { UserProfileComponent } from './user-profile.component';
194
+ import { UserStore } from './user.store';
195
+ import { inject } from '@angular/core';
196
+ import { AdminComponent } from './admin.component';
197
+
198
+ export const appRoutes: Routes = [
199
+ {
200
+ path: 'home',
201
+ component: HomeComponent,
202
+ resolve: {
203
+ // Simple static breadcrumb
204
+ breadcrumb: createBreadcrumb(() => ({
205
+ label: 'Home',
206
+ })),
207
+ },
208
+ },
209
+ {
210
+ path: 'admin',
211
+ component: AdminComponent,
212
+ data: {
213
+ skipBreadcrumb: true, // opt out of auto-generation for this specific route
214
+ },
215
+ },
216
+ {
217
+ path: 'users/:userId',
218
+ component: UserProfileComponent,
219
+ resolve: {
220
+ breadcrumb: createBreadcrumb(() => {
221
+ const userStore = inject(UserStore);
222
+ return {
223
+ label: () => `Profile: ${userStore.currentUser().name}` ?? 'Loading...',
224
+ ariaLabel: () => `View profile for ${userStore.currentUser().name ?? 'user'}`,
225
+ };
226
+ }),
227
+ },
228
+ },
229
+ ];
230
+ ```
231
+
232
+ ### Configuration [optional]
233
+
234
+ The breadcrumb system can be configured globally using `provideBreadcrumbConfig`. This allows you to, for example, set the system to 'manual' mode (disabling all automatic generation) or provide a custom function for generating breadcrumb labels.
235
+
236
+ ```typescript
237
+ import { provideRouter } from '@angular/router';
238
+ import { provideBreadcrumbConfig, BreadcrumbConfig, ResolvedLeafRoute } from '@mmstack/router-core'; // Adjust path
239
+ import { appRoutes } from './app.routes';
240
+ import { ApplicationConfig } from '@angular/core';
241
+
242
+ // Example: Custom label generation strategy
243
+ const customLabelStrategy = () => {
244
+ // you can inject root injectable services/stores here.
245
+ return (leaf: ResolvedLeafRoute): string => {
246
+ return leaf.route.data?.['navTitle'] || leaf.route.title || 'Default Title';
247
+ };
248
+ };
249
+ export const appConfig: ApplicationConfig = {
250
+ providers: [
251
+ // ...rest
252
+ provideBreadcrumbConfig({
253
+ // generation: 'manual' // When set to 'manual' the system only uses explicitly defined breadcrumbs
254
+ generation: customLabelStrategy, // Or provide a custom generation function
255
+ }),
256
+ ],
257
+ };
258
+ ```
@@ -7,7 +7,39 @@ import { toSignal } from '@angular/core/rxjs-interop';
7
7
  import { filter, map } from 'rxjs/operators';
8
8
  import { Subject, EMPTY, filter as filter$1, take, switchMap, finalize } from 'rxjs';
9
9
 
10
+ /**
11
+ * @internal
12
+ */
10
13
  const token = new InjectionToken('MMSTACK_BREADCRUMB_CONFIG');
14
+ /**
15
+ * Provides configuration for the breadcrumb system.
16
+ * @param config - A partial `BreadcrumbConfig` object with the desired settings. *
17
+ * @see BreadcrumbConfig
18
+ * @example
19
+ * ```typescript
20
+ * // In your app.module.ts or a standalone component's providers:
21
+ * // import { provideBreadcrumbConfig } from './breadcrumb.config'; // Adjust path
22
+ * // import { ResolvedLeafRoute } from './breadcrumb.type'; // Adjust path
23
+ *
24
+ * // const customLabelStrategy: GenerateBreadcrumbFn = () => {
25
+ * // return (leaf: ResolvedLeafRoute): string => {
26
+ * // // Example: Prioritize a 'navTitle' data property
27
+ * // if (leaf.route.data?.['navTitle']) {
28
+ * // return leaf.route.data['navTitle'];
29
+ * // }
30
+ * // // Fallback to a default mechanism
31
+ * // return leaf.route.title || leaf.segment.resolved || 'Unnamed';
32
+ * // };
33
+ * // };
34
+ *
35
+ * export const appConfig = [
36
+ * // ...rest
37
+ * provideBreadcrumbConfig({
38
+ * generation: customLabelStrategy, // or 'manual' to disable auto-generation
39
+ * }),
40
+ * ]
41
+ * ```
42
+ */
11
43
  function provideBreadcrumbConfig(config) {
12
44
  return {
13
45
  provide: token,
@@ -16,6 +48,9 @@ function provideBreadcrumbConfig(config) {
16
48
  },
17
49
  };
18
50
  }
51
+ /**
52
+ * @internal
53
+ */
19
54
  function injectBreadcrumbConfig() {
20
55
  return (inject(token, {
21
56
  optional: true,
@@ -66,10 +101,19 @@ function url() {
66
101
  });
67
102
  }
68
103
 
104
+ /**
105
+ * @internal
106
+ */
69
107
  const INTERNAL_BREADCRUMB_SYMBOL = Symbol.for('MMSTACK_INTERNAL_BREADCRUMB');
108
+ /**
109
+ * @internal
110
+ */
70
111
  function getBreadcrumbInternals(breadcrumb) {
71
112
  return breadcrumb[INTERNAL_BREADCRUMB_SYMBOL];
72
113
  }
114
+ /**
115
+ * @internal
116
+ */
73
117
  function createInternalBreadcrumb(bc, active, registered = true) {
74
118
  return {
75
119
  ...bc,
@@ -79,6 +123,9 @@ function createInternalBreadcrumb(bc, active, registered = true) {
79
123
  },
80
124
  };
81
125
  }
126
+ /**
127
+ * @internal
128
+ */
82
129
  function isInternalBreadcrumb(breadcrumb) {
83
130
  return !!breadcrumb[INTERNAL_BREADCRUMB_SYMBOL];
84
131
  }
@@ -88,10 +135,16 @@ function leafRoutes() {
88
135
  const getLeafRoutes = (snapshot) => {
89
136
  const routes = [];
90
137
  let route = snapshot.root;
138
+ const processed = new Set();
91
139
  while (route) {
92
140
  const allSegments = route.pathFromRoot.flatMap((snap) => snap.routeConfig?.path ?? []);
93
141
  const segments = allSegments.filter(Boolean);
94
142
  const path = router.serializeUrl(router.parseUrl(segments.join('/')));
143
+ if (processed.has(path)) {
144
+ route = route.firstChild;
145
+ continue;
146
+ }
147
+ processed.add(path);
95
148
  const parts = route.pathFromRoot
96
149
  .flatMap((snap) => snap.url ?? [])
97
150
  .map((u) => u.path)
@@ -227,11 +280,73 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.3", ngImpor
227
280
  providedIn: 'root',
228
281
  }]
229
282
  }] });
283
+ /**
284
+ * Injects and provides access to a reactive list of breadcrumbs.
285
+ *
286
+ * The breadcrumbs are ordered and reflect the current active navigation path.
287
+ * @see Breadcrumb
288
+ * @returns `Signal<Breadcrumb[]>`
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * @Component({
293
+ * selector: 'app-breadcrumbs',
294
+ * template: `
295
+ * <nav aria-label="breadcrumb">
296
+ * <ol>
297
+ * @for (crumb of breadcrumbs(); track crumb.id) {
298
+ * <li>
299
+ * <a [href]="crumb.link()" [attr.aria-label]="crumb.ariaLabel()">{{ crumb.label() }}</a>
300
+ * </li>
301
+ * }
302
+ * </ol>
303
+ * </nav>
304
+ * `
305
+ * })
306
+ * export class MyBreadcrumbsComponent {
307
+ * breadcrumbs = injectBreadcrumbs();
308
+ * }
309
+ * ```
310
+ */
230
311
  function injectBreadcrumbs() {
231
312
  const store = inject(BreadcrumbStore);
232
313
  return store.unwrapped;
233
314
  }
234
315
 
316
+ /**
317
+ * Creates and registers a breadcrumb for a specific route.
318
+ * This function is designed to be used as an Angular Route `ResolveFn`.
319
+ * It handles the registration of the breadcrumb with the `BreadcrumbStore`
320
+ * and ensures automatic deregistration when the route is destroyed.
321
+ *
322
+ * @param factory A function that returns a `CreateBreadcrumbOptions` object.
323
+ * @see CreateBreadcrumbOptions
324
+ *
325
+ * @example
326
+ * ```typescript
327
+ * export const appRoutes: Routes = [
328
+ * {
329
+ * path: 'home',
330
+ * component: HomeComponent,
331
+ * resolve: {
332
+ * breadcrumb: createBreadcrumb(() => ({
333
+ * label: 'Home',
334
+ * });
335
+ * },
336
+ * path: 'users/:userId',
337
+ * component: UserProfileComponent,
338
+ * resolve: {
339
+ * breadcrumb: createBreadcrumb(() => {
340
+ * const userStore = inject(UserStore);
341
+ * return {
342
+ * label: () => userStore.user().name ?? 'Loading...
343
+ * };
344
+ * })
345
+ * },
346
+ * }
347
+ * ];
348
+ * ```
349
+ */
235
350
  function createBreadcrumb(factory) {
236
351
  return async (route) => {
237
352
  const router = inject(Router);
@@ -257,7 +372,7 @@ function createBreadcrumb(factory) {
257
372
  const deregister = store.register(createInternalBreadcrumb(bc, computed(() => route.data?.['skipBreadcrumb'] !== true)));
258
373
  inject(DestroyRef).onDestroy(deregister);
259
374
  if (provided.awaitValue)
260
- await until(trigger, (v) => !!v);
375
+ await until(bc.label, (v) => !!v);
261
376
  return Promise.resolve();
262
377
  };
263
378
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mmstack-router-core.mjs","sources":["../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.config.ts","../../../../../packages/router/core/src/lib/url.ts","../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.type.ts","../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.store.ts","../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.resolver.ts","../../../../../packages/router/core/src/lib/preloading/preload.service.ts","../../../../../packages/router/core/src/lib/util/create-route-predicate.ts","../../../../../packages/router/core/src/lib/util/find-path.ts","../../../../../packages/router/core/src/lib/preloading/preload.strategy.ts","../../../../../packages/router/core/src/lib/link.directive.ts","../../../../../packages/router/core/src/lib/query-param.ts","../../../../../packages/router/core/src/mmstack-router-core.ts"],"sourcesContent":["import { inject, InjectionToken } from '@angular/core';\nimport { ResolvedLeafRoute } from './breadcrumb.type';\n\ntype GenerateBreadcrumbFn = () => (leaf: ResolvedLeafRoute) => string;\n\nexport type BreadcrumbConfig = {\n generation?: 'manual' | GenerateBreadcrumbFn;\n};\n\nconst token = new InjectionToken<BreadcrumbConfig>('MMSTACK_BREADCRUMB_CONFIG');\n\nexport function provideBreadcrumbConfig(config: Partial<BreadcrumbConfig>) {\n return {\n provide: token,\n useValue: {\n ...config,\n },\n };\n}\n\nexport function injectBreadcrumbConfig(): BreadcrumbConfig {\n return (\n inject(token, {\n optional: true,\n }) ?? {}\n );\n}\n","import { inject, type Signal } from '@angular/core';\r\nimport { toSignal } from '@angular/core/rxjs-interop';\r\nimport {\r\n type Event,\r\n EventType,\r\n type NavigationEnd,\r\n Router,\r\n} from '@angular/router';\r\nimport { filter, map } from 'rxjs/operators';\r\n\r\n/**\r\n * Type guard to check if a Router Event is a NavigationEnd event.\r\n * @internal\r\n */\r\nfunction isNavigationEnd(e: Event): e is NavigationEnd {\r\n return 'type' in e && e.type === EventType.NavigationEnd;\r\n}\r\n\r\n/**\r\n * Creates a Signal that tracks the current router URL.\r\n *\r\n * The signal emits the URL string reflecting the router state *after* redirects\r\n * have completed for each successful navigation. It initializes with the router's\r\n * current URL state.\r\n *\r\n * @returns {Signal<string>} A Signal emitting the `urlAfterRedirects` upon successful navigation.\r\n *\r\n * @example\r\n * ```ts\r\n * import { Component, effect } from '@angular/core';\r\n * import { url } from '@mmstack/router-core'; // Adjust import path\r\n *\r\n * @Component({\r\n * selector: 'app-root',\r\n * template: `Current URL: {{ currentUrl() }}`\r\n * })\r\n * export class AppComponent {\r\n * currentUrl = url();\r\n *\r\n * constructor() {\r\n * effect(() => {\r\n * console.log('Navigation ended. New URL:', this.currentUrl());\r\n * // e.g., track page view with analytics\r\n * });\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function url(): Signal<string> {\r\n const router = inject(Router);\r\n\r\n return toSignal(\r\n router.events.pipe(\r\n filter(isNavigationEnd),\r\n map((e) => e.urlAfterRedirects),\r\n ),\r\n {\r\n initialValue: router.url,\r\n },\r\n );\r\n}\r\n","import { type Signal } from '@angular/core';\nimport { ActivatedRouteSnapshot } from '@angular/router';\n\nexport type Breadcrumb = {\n id: string;\n label: Signal<string>;\n ariaLabel: Signal<string>;\n link: Signal<string>;\n};\n\nconst INTERNAL_BREADCRUMB_SYMBOL = Symbol.for('MMSTACK_INTERNAL_BREADCRUMB');\n\n/**\n * @internal\n */\nexport type InternalBreadcrumb = Breadcrumb & {\n [INTERNAL_BREADCRUMB_SYMBOL]: {\n active: Signal<boolean>;\n registered: boolean;\n };\n};\n\nexport function getBreadcrumbInternals(breadcrumb: InternalBreadcrumb) {\n return (breadcrumb as InternalBreadcrumb)[INTERNAL_BREADCRUMB_SYMBOL];\n}\n\nexport function createInternalBreadcrumb(\n bc: Breadcrumb,\n active: Signal<boolean>,\n registered = true,\n): InternalBreadcrumb {\n return {\n ...bc,\n [INTERNAL_BREADCRUMB_SYMBOL]: {\n active,\n registered,\n },\n };\n}\n\n/**\n * @internal\n */\nexport type ResolvedLeafRoute = {\n route: ActivatedRouteSnapshot;\n segment: {\n path: string;\n resolved: string;\n };\n path: string;\n link: string;\n};\n\nexport function isInternalBreadcrumb(\n breadcrumb: Breadcrumb | InternalBreadcrumb,\n): breadcrumb is InternalBreadcrumb {\n return !!(breadcrumb as InternalBreadcrumb)[INTERNAL_BREADCRUMB_SYMBOL];\n}\n","import { computed, inject, Injectable, Signal, untracked } from '@angular/core';\nimport {\n ActivatedRouteSnapshot,\n Router,\n RouterStateSnapshot,\n} from '@angular/router';\nimport { mapArray, mutable } from '@mmstack/primitives';\nimport { url } from '../url';\nimport { injectBreadcrumbConfig } from './breadcrumb.config';\nimport {\n Breadcrumb,\n createInternalBreadcrumb,\n getBreadcrumbInternals,\n InternalBreadcrumb,\n isInternalBreadcrumb,\n ResolvedLeafRoute,\n} from './breadcrumb.type';\n\nfunction leafRoutes(): Signal<ResolvedLeafRoute[]> {\n const router = inject(Router);\n\n const getLeafRoutes = (\n snapshot: RouterStateSnapshot,\n ): ResolvedLeafRoute[] => {\n const routes: ResolvedLeafRoute[] = [];\n let route: ActivatedRouteSnapshot | null = snapshot.root;\n\n while (route) {\n const allSegments = route.pathFromRoot.flatMap(\n (snap) => snap.routeConfig?.path ?? [],\n );\n\n const segments = allSegments.filter(Boolean);\n\n const path = router.serializeUrl(router.parseUrl(segments.join('/')));\n\n const parts = route.pathFromRoot\n .flatMap((snap) => snap.url ?? [])\n .map((u) => u.path)\n .filter(Boolean);\n\n const link = router.serializeUrl(router.parseUrl(parts.join('/')));\n\n routes.push({\n route,\n segment: {\n path: segments.at(-1) ?? '',\n resolved: parts.at(-1) ?? '',\n },\n path,\n link,\n });\n route = route.firstChild;\n }\n\n return routes;\n };\n\n const currentUrl = url();\n\n const leafRoutes = computed(() => {\n currentUrl();\n return getLeafRoutes(router.routerState.snapshot);\n });\n\n return leafRoutes;\n}\n\nfunction uppercaseFirst(str: string): string {\n const lcs = str.toLowerCase();\n return lcs.charAt(0).toUpperCase() + lcs.slice(1);\n}\n\nfunction removeMatrixAndQueryParams(path: string): string {\n const [cleanPath] = path.split(';');\n return cleanPath.split('?')[0];\n}\n\nfunction parsePathSegment(pathSegment: string): string {\n return pathSegment\n .split('/')\n .flatMap((part) => part.split('.'))\n .flatMap((part) => part.split('-'))\n .map((part) => uppercaseFirst(removeMatrixAndQueryParams(part)))\n .join(' ');\n}\n\nfunction generateLabel(leaf: ResolvedLeafRoute): string {\n const title = leaf.route.title ?? leaf.route.data?.['title'];\n\n if (title && typeof title === 'string') return title;\n if (leaf.segment.path.includes(':')) return leaf.segment.resolved;\n\n return parsePathSegment(leaf.segment.path);\n}\n\nfunction autoGenerateBreadcrumb(\n id: string,\n leaf: Signal<ResolvedLeafRoute>,\n autoGenerateFn: Signal<(leaf: ResolvedLeafRoute) => string>,\n): Breadcrumb {\n const label = computed(() => autoGenerateFn()(leaf()));\n\n return createInternalBreadcrumb(\n {\n id,\n label,\n ariaLabel: label,\n link: computed(() => leaf().link),\n },\n computed(\n () =>\n leaf().route.data?.['skipBreadcrumb'] !== true &&\n id !== '' &&\n id !== '/' &&\n leaf().segment.path !== '' &&\n leaf().segment.path !== '/' &&\n !leaf().segment.path.endsWith('/') &&\n !!label(),\n ),\n );\n}\n\nfunction injectGenerateLabelFn() {\n const { generation } = injectBreadcrumbConfig();\n\n if (typeof generation !== 'function') return computed(() => generateLabel);\n\n const provided = generation();\n return computed(() => provided);\n}\n\nfunction injectIsManual() {\n return injectBreadcrumbConfig().generation === 'manual';\n}\n\nfunction exposeActiveSignal(\n crumbSignal: Signal<Breadcrumb>,\n manual: boolean,\n): Signal<Breadcrumb> & {\n active: Signal<boolean>;\n} {\n const active = manual\n ? computed(() => {\n const crumb = crumbSignal();\n\n return (\n isInternalBreadcrumb(crumb) &&\n getBreadcrumbInternals(crumb).registered &&\n getBreadcrumbInternals(crumb).active()\n );\n })\n : computed(() => {\n const crumb = crumbSignal();\n if (!isInternalBreadcrumb(crumb)) return true;\n return getBreadcrumbInternals(crumb).active();\n });\n\n const sig = crumbSignal as Signal<Breadcrumb> & {\n active: Signal<boolean>;\n };\n\n sig.active = active;\n\n return sig;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class BreadcrumbStore {\n private readonly map = mutable<Map<string, InternalBreadcrumb>>(new Map());\n private readonly isManual = injectIsManual();\n private readonly autoGenerateLabelFn = injectGenerateLabelFn();\n\n private readonly all = mapArray(\n leafRoutes(),\n (leaf) => {\n const stableId = computed(() => leaf().path);\n\n return exposeActiveSignal(\n computed(\n () => {\n const id = stableId();\n\n const found = this.map().get(id);\n\n if (!found)\n return autoGenerateBreadcrumb(id, leaf, this.autoGenerateLabelFn);\n\n if (!id.includes(':')) return found;\n\n return {\n ...found,\n link: computed(() => leaf().link),\n };\n },\n {\n equal: (a, b) => a.id === b.id,\n },\n ),\n this.isManual,\n );\n },\n {\n equal: (a, b) => a.link === b.link,\n },\n );\n\n private readonly crumbs = computed((): Signal<Breadcrumb>[] =>\n this.all().filter((c) => c.active()),\n );\n\n readonly unwrapped = computed(() => this.crumbs().map((c) => c()));\n\n register(breadcrumb: InternalBreadcrumb) {\n this.map.inline((m) => m.set(breadcrumb.id, breadcrumb));\n\n return () => {\n this.map.inline((m) => m.delete(breadcrumb.id));\n };\n }\n\n has(id: string): boolean {\n return untracked(this.map).has(id);\n }\n}\n\nexport function injectBreadcrumbs() {\n const store = inject(BreadcrumbStore);\n return store.unwrapped;\n}\n","import { computed, DestroyRef, inject } from '@angular/core';\nimport {\n createUrlTreeFromSnapshot,\n Router,\n type ResolveFn,\n} from '@angular/router';\nimport { BreadcrumbStore } from './breadcrumb.store';\n\ntype CreateBreadcrumbOptions = {\n label: string | (() => string);\n ariaLabel?: string | (() => string);\n awaitValue?: boolean;\n};\n\nimport { until } from '@mmstack/primitives';\nimport { url } from '../url';\nimport { Breadcrumb, createInternalBreadcrumb } from './breadcrumb.type';\n\nexport function createBreadcrumb(\n factory: () => CreateBreadcrumbOptions,\n): ResolveFn<void> {\n return async (route) => {\n const router = inject(Router);\n const store = inject(BreadcrumbStore);\n\n const segments = route.pathFromRoot.flatMap(\n (snap) => snap.routeConfig?.path ?? [],\n );\n\n const joinedSegments = segments.filter(Boolean).join('/');\n\n const fp = router.serializeUrl(router.parseUrl(joinedSegments));\n if (store.has(fp)) return Promise.resolve();\n\n const tree = createUrlTreeFromSnapshot(\n route,\n [],\n route.queryParams,\n route.fragment,\n );\n\n const provided = factory();\n\n const trigger = url();\n\n const link = computed(() => router.serializeUrl(tree));\n\n const { label, ariaLabel = label } = provided;\n\n const bc: Breadcrumb = {\n id: fp,\n ariaLabel:\n typeof ariaLabel === 'string'\n ? computed(() => ariaLabel)\n : computed(ariaLabel),\n label:\n typeof label === 'string' ? computed(() => label) : computed(label),\n link,\n };\n\n const deregister = store.register(\n createInternalBreadcrumb(\n bc,\n computed(() => route.data?.['skipBreadcrumb'] !== true),\n ),\n );\n\n inject(DestroyRef).onDestroy(deregister);\n\n if (provided.awaitValue) await until(trigger, (v) => !!v);\n\n return Promise.resolve();\n };\n}\n","import { Injectable } from '@angular/core';\nimport { Subject } from 'rxjs';\n\n@Injectable({ providedIn: 'root' })\nexport class PreloadService {\n private readonly preloadOnDemand$ = new Subject<string>();\n readonly preloadRequested$ = this.preloadOnDemand$.asObservable();\n\n startPreload(routePath: string) {\n this.preloadOnDemand$.next(routePath);\n }\n}\n","function parsePathSegment(segmentString: string): {\n pathPart: string;\n matrixParams: Record<string, string>;\n} {\n const parts = segmentString.split(';');\n const pathPart = parts[0];\n const matrixParams: Record<string, string> = {};\n for (let i = 1; i < parts.length; i++) {\n const [key, value = 'true'] = parts[i].split('=');\n if (key) {\n matrixParams[key] = value;\n }\n }\n return { pathPart, matrixParams };\n}\n\nfunction createBasePredicate(path: string): (path: string) => boolean {\n const partPredicates = path\n .split('/')\n .filter((part) => !!part.trim())\n .map((configSegmentString) => {\n const { pathPart: configPathPart, matrixParams: configMatrixParams } =\n parsePathSegment(configSegmentString);\n\n let singlePathPartPredicate: (linkSegmentPathPart: string) => boolean;\n if (configPathPart.startsWith(':')) {\n singlePathPartPredicate = () => true;\n } else {\n singlePathPartPredicate = (linkSegmentPathPart: string) =>\n linkSegmentPathPart === configPathPart;\n }\n\n const configSegmentHasMatrixParams =\n Object.keys(configMatrixParams).length > 0;\n\n return (linkSegmentString: string) => {\n const { pathPart: linkPathPart, matrixParams: linkMatrixParams } =\n parsePathSegment(linkSegmentString);\n\n if (!singlePathPartPredicate(linkPathPart)) {\n return false;\n }\n\n if (!configSegmentHasMatrixParams) {\n return true;\n }\n\n return Object.entries(configMatrixParams).every(\n ([key, value]) =>\n linkMatrixParams.hasOwnProperty(key) &&\n linkMatrixParams[key] === value,\n );\n };\n });\n\n return (path: string) => {\n const linkPathOnly = path.split(/[?#]/).at(0) ?? '';\n if (!linkPathOnly && partPredicates.length > 0) return false;\n if (!linkPathOnly && partPredicates.length === 0) return true;\n\n const parts = linkPathOnly.split('/').filter((part) => !!part.trim());\n if (parts.length < partPredicates.length) return false;\n\n return parts.every((seg, idx) => {\n const pred = partPredicates.at(idx);\n if (!pred) return true;\n return pred(seg);\n });\n };\n}\n\ntype ParsedSegment = {\n pathPart: string;\n matrixParams: Record<string, string>;\n};\n\nfunction singleSegmentMatches(\n configSegment: ParsedSegment,\n linkSegment: ParsedSegment,\n): boolean {\n if (configSegment.pathPart.startsWith(':')) {\n } else if (configSegment.pathPart !== linkSegment.pathPart) {\n return false;\n }\n\n const configMatrix = configSegment.matrixParams;\n const linkMatrix = linkSegment.matrixParams;\n for (const key in configMatrix) {\n if (\n !linkMatrix.hasOwnProperty(key) ||\n linkMatrix[key] !== configMatrix[key]\n ) {\n return false;\n }\n }\n return true;\n}\n\nfunction matchSegmentsRecursive(\n configSegments: ParsedSegment[],\n linkSegments: ParsedSegment[],\n configIdx: number,\n linkIdx: number,\n): boolean {\n if (configIdx === configSegments.length) {\n return linkIdx === linkSegments.length;\n }\n\n if (linkIdx === linkSegments.length) {\n for (let i = configIdx; i < configSegments.length; i++) {\n if (configSegments[i].pathPart !== '**') {\n return false;\n }\n }\n return true;\n }\n\n const currentConfigSegment = configSegments[configIdx];\n\n if (currentConfigSegment.pathPart === '**') {\n if (\n matchSegmentsRecursive(\n configSegments,\n linkSegments,\n configIdx + 1,\n linkIdx,\n )\n ) {\n return true;\n }\n\n if (linkIdx < linkSegments.length) {\n if (\n matchSegmentsRecursive(\n configSegments,\n linkSegments,\n configIdx,\n linkIdx + 1,\n )\n ) {\n return true;\n }\n }\n\n return false;\n } else {\n if (\n linkIdx < linkSegments.length &&\n singleSegmentMatches(currentConfigSegment, linkSegments[linkIdx])\n ) {\n return matchSegmentsRecursive(\n configSegments,\n linkSegments,\n configIdx + 1,\n linkIdx + 1,\n );\n }\n\n return false;\n }\n}\n\nfunction createWildcardPredicate(path: string): (linkPath: string) => boolean {\n const configSegments = path\n .split('/')\n .filter((p) => !!p.trim())\n .map((segment) => parsePathSegment(segment));\n\n return (linkPath: string): boolean => {\n const linkPathOnly = linkPath.split(/[?#]/).at(0) ?? '';\n const linkSegments = linkPathOnly\n .split('/')\n .filter((p) => !!p.trim())\n .map((segment) => parsePathSegment(segment));\n\n return matchSegmentsRecursive(configSegments, linkSegments, 0, 0);\n };\n}\n\nexport function createRoutePredicate(\n path: string,\n): (linkPath: string) => boolean {\n return path.includes('**')\n ? createWildcardPredicate(path)\n : createBasePredicate(path);\n}\n","// The following functions are adapted from ngx-quicklink,\n// (https://github.com/mgechev/ngx-quicklink)\n// Copyright (c) Minko Gechev and contributors, licensed under the MIT License.\n\nimport { PRIMARY_OUTLET, Route } from '@angular/router';\n\nfunction isPrimaryRoute(route: Route): boolean {\n return route.outlet === PRIMARY_OUTLET || !route.outlet;\n}\n\nexport const findPath = (config: Route[], route: Route): string => {\n const configQueue = config.slice();\n const parent = new Map<Route, Route>();\n const visited = new Set<Route>();\n\n while (configQueue.length) {\n const el = configQueue.shift();\n if (!el) {\n continue;\n }\n\n visited.add(el);\n\n if (el === route) {\n break;\n }\n\n (el.children || []).forEach((childRoute: Route) => {\n if (!visited.has(childRoute)) {\n parent.set(childRoute, el);\n configQueue.push(childRoute);\n }\n });\n\n const lazyRoutes = (el as any)._loadedRoutes || [];\n if (Array.isArray(lazyRoutes)) {\n lazyRoutes.forEach((lazyRoute: Route) => {\n if (lazyRoute && !visited.has(lazyRoute)) {\n parent.set(lazyRoute, el);\n configQueue.push(lazyRoute);\n }\n });\n }\n }\n\n let path = '';\n let currentRoute: Route | undefined = route;\n\n while (currentRoute) {\n const currentPath = currentRoute.path || '';\n if (isPrimaryRoute(currentRoute)) {\n path = `/${currentPath}${path}`;\n } else {\n path = `/(${currentRoute.outlet}:${currentPath})${path}`;\n }\n currentRoute = parent.get(currentRoute);\n }\n\n let normalizedPath = path.replaceAll(/\\/+/g, '/');\n\n if (normalizedPath !== '/' && normalizedPath.endsWith('/')) {\n normalizedPath = normalizedPath.slice(0, -1);\n }\n\n return normalizedPath;\n};\n","import { inject, Injectable } from '@angular/core';\nimport { PreloadingStrategy, type Route, Router } from '@angular/router';\nimport { EMPTY, filter, finalize, Observable, switchMap, take } from 'rxjs';\nimport { createRoutePredicate, findPath } from '../util';\nimport { PreloadService } from './preload.service';\n\nfunction hasSlowConnection() {\n if (\n globalThis.window &&\n 'navigator' in globalThis.window &&\n 'connection' in globalThis.window.navigator &&\n typeof globalThis.window.navigator.connection === 'object' &&\n !!globalThis.window.navigator.connection\n ) {\n const is2g =\n 'effectiveType' in globalThis.window.navigator.connection &&\n typeof globalThis.window.navigator.connection.effectiveType ===\n 'string' &&\n globalThis.window.navigator.connection.effectiveType.endsWith('2g');\n if (is2g) return true;\n if (\n 'saveData' in globalThis.window.navigator.connection &&\n typeof globalThis.window.navigator.connection.saveData === 'boolean' &&\n globalThis.window.navigator.connection.saveData\n )\n return true;\n }\n\n return false;\n}\n\nfunction noPreload(route: Route) {\n return route.data && route.data['preload'] === false;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class PreloadStrategy implements PreloadingStrategy {\n private readonly loading = new Set<string>();\n private readonly router = inject(Router);\n private readonly svc = inject(PreloadService);\n\n preload(route: Route, load: () => Observable<any>): Observable<any> {\n if (noPreload(route) || hasSlowConnection()) return EMPTY;\n\n const fp = findPath(this.router.config, route);\n\n if (this.loading.has(fp)) return EMPTY;\n\n const predicate = createRoutePredicate(fp);\n return this.svc.preloadRequested$.pipe(\n filter((path) => path === fp || predicate(path)),\n take(1),\n switchMap(() => load()),\n finalize(() => this.loading.delete(fp)),\n );\n }\n}\n","import {\n booleanAttribute,\n computed,\n Directive,\n effect,\n inject,\n input,\n output,\n untracked,\n} from '@angular/core';\nimport {\n type ActivatedRoute,\n type Params,\n Router,\n RouterLink,\n RouterLinkWithHref,\n UrlTree,\n} from '@angular/router';\nimport { elementVisibility } from '@mmstack/primitives';\nimport { PreloadService } from './preloading';\n\nfunction inputToUrlTree(\n router: Router,\n link: string | any[] | UrlTree | null,\n relativeTo?: ActivatedRoute,\n queryParams?: Params,\n fragment?: string,\n queryParamsHandling?: 'merge' | 'preserve' | '',\n routerLinkUrlTree?: UrlTree | null,\n): UrlTree | null {\n if (!link) return null;\n if (routerLinkUrlTree) return routerLinkUrlTree;\n\n if (link instanceof UrlTree) return link;\n\n const arr = Array.isArray(link) ? link : [link];\n\n return router.createUrlTree(arr, {\n relativeTo,\n queryParams,\n fragment,\n queryParamsHandling,\n });\n}\n\nfunction treeToSerializedUrl(\n router: Router,\n urlTree: UrlTree | null,\n): string | null {\n if (!urlTree) return null;\n return router.serializeUrl(urlTree);\n}\n\nexport function injectTriggerPreload() {\n const svc = inject(PreloadService);\n const router = inject(Router);\n\n return (\n link: string | any[] | UrlTree | null,\n relativeTo?: ActivatedRoute,\n queryParams?: Params,\n fragment?: string,\n queryParamsHandling?: 'merge' | 'preserve' | '',\n ) => {\n const urlTree = inputToUrlTree(\n router,\n link,\n relativeTo,\n queryParams,\n fragment,\n queryParamsHandling,\n );\n const fullPath = treeToSerializedUrl(router, urlTree);\n if (!fullPath) return;\n\n svc.startPreload(fullPath);\n };\n}\n\n@Directive({\n selector: '[mmLink]',\n exportAs: 'mmLink',\n host: {\n '(mouseenter)': 'onHover()',\n },\n hostDirectives: [\n {\n directive: RouterLink,\n inputs: [\n 'routerLink: mmLink',\n 'target',\n 'queryParams',\n 'fragment',\n 'queryParamsHandling',\n 'state',\n 'relativeTo',\n 'skipLocationChange',\n 'replaceUrl',\n ],\n },\n ],\n})\nexport class LinkDirective {\n private readonly routerLink =\n inject(RouterLink, {\n self: true,\n optional: true,\n }) ?? inject(RouterLinkWithHref, { self: true, optional: true });\n\n private readonly svc = inject(PreloadService);\n private readonly router = inject(Router);\n\n readonly target = input<string>();\n readonly queryParams = input<Params>();\n readonly fragment = input<string>();\n readonly queryParamsHandling = input<'merge' | 'preserve' | ''>();\n readonly state = input<Record<string, any>>();\n readonly info = input<unknown>();\n readonly relativeTo = input<ActivatedRoute>();\n readonly skipLocationChange = input(false, { transform: booleanAttribute });\n readonly replaceUrl = input(false, { transform: booleanAttribute });\n readonly mmLink = input.required<string | any[] | UrlTree | null>();\n readonly preloadOn = input<'hover' | 'visible' | null>('hover');\n\n readonly preloading = output<void>();\n\n private readonly urlTree = computed(() => {\n return inputToUrlTree(\n this.router,\n this.mmLink(),\n this.relativeTo(),\n this.queryParams(),\n this.fragment(),\n this.queryParamsHandling(),\n this.routerLink?.urlTree,\n );\n });\n\n private readonly fullPath = computed(() => {\n return treeToSerializedUrl(this.router, this.urlTree());\n });\n\n onHover() {\n if (untracked(this.preloadOn) !== 'hover') return;\n this.requestPreload();\n }\n\n constructor() {\n const intersection = elementVisibility();\n\n effect(() => {\n if (this.preloadOn() !== 'visible') return;\n if (intersection.visible()) this.requestPreload();\n });\n }\n\n private requestPreload() {\n const fp = untracked(this.fullPath);\n if (!this.routerLink || !fp) return;\n this.svc.startPreload(fp);\n this.preloading.emit();\n }\n\n onClick(\n button: number,\n ctrlKey: boolean,\n shiftKey: boolean,\n altKey: boolean,\n metaKey: boolean,\n ) {\n return this.routerLink?.onClick(button, ctrlKey, shiftKey, altKey, metaKey);\n }\n}\n","import {\r\n computed,\r\n inject,\r\n isSignal,\r\n untracked,\r\n type WritableSignal,\r\n} from '@angular/core';\r\nimport { toSignal } from '@angular/core/rxjs-interop';\r\nimport { ActivatedRoute, Router } from '@angular/router';\r\nimport { toWritable } from '@mmstack/primitives';\r\n\r\n/**\r\n * Creates a WritableSignal that synchronizes with a specific URL query parameter,\r\n * enabling two-way binding between the signal's state and the URL.\r\n *\r\n * Reading the signal provides the current value of the query parameter (or null if absent).\r\n * Setting the signal updates the URL query parameter using `Router.navigate`, triggering\r\n * navigation and causing the signal to update reactively if the navigation is successful.\r\n *\r\n * @param key The key of the query parameter to synchronize with.\r\n * Can be a static string (e.g., `'search'`) or a function/signal returning a string\r\n * for dynamic keys (e.g., `() => this.userId() + '_filter'` or `computed(() => this.category() + '_sort')`).\r\n * The signal will reactively update if the key returned by the function/signal changes.\r\n * @returns {WritableSignal<string | null>} A signal representing the query parameter's value.\r\n * - Reading returns the current value string, or `null` if the parameter is absent in the URL.\r\n * - Setting the signal to a string updates the query parameter in the URL (e.g., `signal.set('value')` results in `?key=value`).\r\n * - Setting the signal to `null` removes the query parameter from the URL (e.g., `signal.set(null)` results in `?otherParam=...`).\r\n * - Automatically reflects changes if the query parameters update due to external navigation.\r\n * @remarks\r\n * - Requires Angular's `ActivatedRoute` and `Router` to be available in the injection context.\r\n * - Uses `Router.navigate` with `queryParamsHandling: 'merge'` to preserve other existing query parameters during updates.\r\n * - Handles dynamic keys reactively. If the result of the `key` function/signal changes, the signal will start reflecting the value of the *new* query parameter key.\r\n * - During Server-Side Rendering (SSR), it reads the initial value from the route snapshot. Write operations (`set`) might have limited or no effect on the server depending on the platform configuration.\r\n *\r\n * @example\r\n * ```ts\r\n * import { Component, computed, effect, signal } from '@angular/core';\r\n * import { queryParam } from '@mmstack/router-core'; // Adjust import path as needed\r\n * // import { FormsModule } from '@angular/forms'; // If using ngModel\r\n *\r\n * @Component({\r\n * selector: 'app-product-list',\r\n * standalone: true,\r\n * // imports: [FormsModule], // If using ngModel\r\n * template: `\r\n * <div>\r\n * Sort By:\r\n * <select [value]=\"sortSignal() ?? ''\" (change)=\"sortSignal.set($any($event.target).value || null)\">\r\n * <option value=\"\">Default</option>\r\n * <option value=\"price_asc\">Price Asc</option>\r\n * <option value=\"price_desc\">Price Desc</option>\r\n * <option value=\"name\">Name</option>\r\n * </select>\r\n * <button (click)=\"sortSignal.set(null)\" [disabled]=\"!sortSignal()\">Clear Sort</button>\r\n * </div>\r\n * <div>\r\n * Page:\r\n * <input type=\"number\" min=\"1\" [value]=\"pageSignal() ?? '1'\" #p (input)=\"setPage(p.value)\"/>\r\n * </div>\r\n * * `\r\n * })\r\n * export class ProductListComponent {\r\n * // Two-way bind the 'sort' query parameter (?sort=...)\r\n * // Defaults to null if param is missing\r\n * sortSignal = queryParam('sort');\r\n *\r\n * // Example with a different type (needs serialization or separate logic)\r\n * // For simplicity, we treat page as string | null here\r\n * pageSignal = queryParam('page');\r\n *\r\n * constructor() {\r\n * effect(() => {\r\n * const currentSort = this.sortSignal();\r\n * const currentPage = this.pageSignal(); // Read as string | null\r\n * console.log('Sort/Page changed, reloading products for:', { sort: currentSort, page: currentPage });\r\n * // --- Fetch data based on currentSort and currentPage ---\r\n * });\r\n * }\r\n *\r\n * setPage(value: string): void {\r\n * const pageNum = parseInt(value, 10);\r\n * // Set to null if page is 1 (to remove param), otherwise set string value\r\n * this.pageSignal.set(isNaN(pageNum) || pageNum <= 1 ? null : pageNum.toString());\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function queryParam(\r\n key: string | (() => string),\r\n): WritableSignal<string | null> {\r\n const route = inject(ActivatedRoute);\r\n const router = inject(Router);\r\n\r\n const keySignal =\r\n typeof key === 'string'\r\n ? computed(() => key)\r\n : isSignal(key)\r\n ? key\r\n : computed(key);\r\n\r\n const queryParamMap = toSignal(route.queryParamMap, {\r\n initialValue: route.snapshot.queryParamMap,\r\n });\r\n\r\n const queryParams = toSignal(route.queryParams, {\r\n initialValue: route.snapshot.queryParams,\r\n });\r\n\r\n const queryParam = computed(() => queryParamMap().get(keySignal()));\r\n\r\n const set = (newValue: string | null) => {\r\n const next = {\r\n ...untracked(queryParams),\r\n };\r\n const key = untracked(keySignal);\r\n\r\n if (newValue === null) {\r\n delete next[key];\r\n } else {\r\n next[key] = newValue;\r\n }\r\n\r\n router.navigate([], {\r\n relativeTo: route,\r\n queryParams: next,\r\n queryParamsHandling: 'merge',\r\n });\r\n };\r\n\r\n return toWritable(queryParam, set);\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["parsePathSegment","filter"],"mappings":"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"}
1
+ {"version":3,"file":"mmstack-router-core.mjs","sources":["../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.config.ts","../../../../../packages/router/core/src/lib/url.ts","../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.type.ts","../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.store.ts","../../../../../packages/router/core/src/lib/breadcrumb/breadcrumb.resolver.ts","../../../../../packages/router/core/src/lib/preloading/preload.service.ts","../../../../../packages/router/core/src/lib/util/create-route-predicate.ts","../../../../../packages/router/core/src/lib/util/find-path.ts","../../../../../packages/router/core/src/lib/preloading/preload.strategy.ts","../../../../../packages/router/core/src/lib/link.directive.ts","../../../../../packages/router/core/src/lib/query-param.ts","../../../../../packages/router/core/src/mmstack-router-core.ts"],"sourcesContent":["import { inject, InjectionToken } from '@angular/core';\nimport { ResolvedLeafRoute } from './breadcrumb.type';\n\n/**\n * A function that returns a custom label generation function.\n * The outer function is called in a root injection context\n * The returned function takes a `ResolvedLeafRoute` and produces a string label for the breadcrumb.\n * As the inner function is wrapped in a computed, changes to signals called within it will update the breadcrumb label reactively.\n */\ntype GenerateBreadcrumbFn = () => (leaf: ResolvedLeafRoute) => string;\n\n/**\n * Configuration options for the breadcrumb system.\n * Use `provideBreadcrumbConfig` to supply these options to your application.\n */\n\nexport type BreadcrumbConfig = {\n /**\n * Defines how breadcrumb labels are generated.\n * - If set to `'manual'`, breadcrumbs will only be displayed if manually registered\n * via `createBreadcrumb`. Automatic generation based on routes is disabled.\n * - Alternatively provide a custom label generation function\n * If left undefined, the system will automatically generate labels based on the route's title, data, or path.\n * @see GenerateBreadcrumbFn\n * @example\n * ```typescript\n * // For custom label generation:\n * // const myCustomLabelGenerator = () => (leaf: ResolvedLeafRoute) => {\n * // return leaf.route.data?.['customTitle'] || leaf.route.routeConfig?.path || 'Default';\n * // };\n * //\n * // config: { generation: myCustomLabelGenerator }\n * ```\n */\n generation?: 'manual' | GenerateBreadcrumbFn;\n};\n\n/**\n * @internal\n */\nconst token = new InjectionToken<BreadcrumbConfig>('MMSTACK_BREADCRUMB_CONFIG');\n\n/**\n * Provides configuration for the breadcrumb system.\n * @param config - A partial `BreadcrumbConfig` object with the desired settings. *\n * @see BreadcrumbConfig\n * @example\n * ```typescript\n * // In your app.module.ts or a standalone component's providers:\n * // import { provideBreadcrumbConfig } from './breadcrumb.config'; // Adjust path\n * // import { ResolvedLeafRoute } from './breadcrumb.type'; // Adjust path\n *\n * // const customLabelStrategy: GenerateBreadcrumbFn = () => {\n * // return (leaf: ResolvedLeafRoute): string => {\n * // // Example: Prioritize a 'navTitle' data property\n * // if (leaf.route.data?.['navTitle']) {\n * // return leaf.route.data['navTitle'];\n * // }\n * // // Fallback to a default mechanism\n * // return leaf.route.title || leaf.segment.resolved || 'Unnamed';\n * // };\n * // };\n *\n * export const appConfig = [\n * // ...rest\n * provideBreadcrumbConfig({\n * generation: customLabelStrategy, // or 'manual' to disable auto-generation\n * }),\n * ]\n * ```\n */\nexport function provideBreadcrumbConfig(config: Partial<BreadcrumbConfig>) {\n return {\n provide: token,\n useValue: {\n ...config,\n },\n };\n}\n\n/**\n * @internal\n */\nexport function injectBreadcrumbConfig(): BreadcrumbConfig {\n return (\n inject(token, {\n optional: true,\n }) ?? {}\n );\n}\n","import { inject, type Signal } from '@angular/core';\r\nimport { toSignal } from '@angular/core/rxjs-interop';\r\nimport {\r\n type Event,\r\n EventType,\r\n type NavigationEnd,\r\n Router,\r\n} from '@angular/router';\r\nimport { filter, map } from 'rxjs/operators';\r\n\r\n/**\r\n * Type guard to check if a Router Event is a NavigationEnd event.\r\n * @internal\r\n */\r\nfunction isNavigationEnd(e: Event): e is NavigationEnd {\r\n return 'type' in e && e.type === EventType.NavigationEnd;\r\n}\r\n\r\n/**\r\n * Creates a Signal that tracks the current router URL.\r\n *\r\n * The signal emits the URL string reflecting the router state *after* redirects\r\n * have completed for each successful navigation. It initializes with the router's\r\n * current URL state.\r\n *\r\n * @returns {Signal<string>} A Signal emitting the `urlAfterRedirects` upon successful navigation.\r\n *\r\n * @example\r\n * ```ts\r\n * import { Component, effect } from '@angular/core';\r\n * import { url } from '@mmstack/router-core'; // Adjust import path\r\n *\r\n * @Component({\r\n * selector: 'app-root',\r\n * template: `Current URL: {{ currentUrl() }}`\r\n * })\r\n * export class AppComponent {\r\n * currentUrl = url();\r\n *\r\n * constructor() {\r\n * effect(() => {\r\n * console.log('Navigation ended. New URL:', this.currentUrl());\r\n * // e.g., track page view with analytics\r\n * });\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function url(): Signal<string> {\r\n const router = inject(Router);\r\n\r\n return toSignal(\r\n router.events.pipe(\r\n filter(isNavigationEnd),\r\n map((e) => e.urlAfterRedirects),\r\n ),\r\n {\r\n initialValue: router.url,\r\n },\r\n );\r\n}\r\n","import { type Signal } from '@angular/core';\nimport { ActivatedRouteSnapshot } from '@angular/router';\n\n/**\n * Represents a single breadcrumb item within the navigation path.\n * All dynamic properties are represented as Angular Signals to enable reactivity.\n */\nexport type Breadcrumb = {\n /**\n * A unique identifier for the breadcrumb item. Generally the unresolved path for example `/posts/:id`.\n * Useful for `@for` tracking in templates.\n */\n id: string;\n /**\n * The visible text for the breadcrumb item.\n * Updated reactively as the url/link based on\n * either a provided definition, or the current route.\n */\n label: Signal<string>;\n /**\n * An accessible label for the breadcrumb item.\n * Defaults to the same value as `label` if not provided.\n */\n ariaLabel: Signal<string>;\n /**\n * The URL link for the breadcrumb item.\n * Updates as the route changes.\n */\n link: Signal<string>;\n};\n\n/**\n * @internal\n */\nconst INTERNAL_BREADCRUMB_SYMBOL = Symbol.for('MMSTACK_INTERNAL_BREADCRUMB');\n\n/**\n * @internal\n */\nexport type InternalBreadcrumb = Breadcrumb & {\n [INTERNAL_BREADCRUMB_SYMBOL]: {\n active: Signal<boolean>;\n registered: boolean;\n };\n};\n\n/**\n * @internal\n */\nexport function getBreadcrumbInternals(breadcrumb: InternalBreadcrumb) {\n return (breadcrumb as InternalBreadcrumb)[INTERNAL_BREADCRUMB_SYMBOL];\n}\n\n/**\n * @internal\n */\nexport function createInternalBreadcrumb(\n bc: Breadcrumb,\n active: Signal<boolean>,\n registered = true,\n): InternalBreadcrumb {\n return {\n ...bc,\n [INTERNAL_BREADCRUMB_SYMBOL]: {\n active,\n registered,\n },\n };\n}\n\n/**\n * @internal\n */\nexport type ResolvedLeafRoute = {\n route: ActivatedRouteSnapshot;\n segment: {\n path: string;\n resolved: string;\n };\n path: string;\n link: string;\n};\n\n/**\n * @internal\n */\nexport function isInternalBreadcrumb(\n breadcrumb: Breadcrumb | InternalBreadcrumb,\n): breadcrumb is InternalBreadcrumb {\n return !!(breadcrumb as InternalBreadcrumb)[INTERNAL_BREADCRUMB_SYMBOL];\n}\n","import { computed, inject, Injectable, Signal, untracked } from '@angular/core';\nimport {\n ActivatedRouteSnapshot,\n Router,\n RouterStateSnapshot,\n} from '@angular/router';\nimport { mapArray, mutable } from '@mmstack/primitives';\nimport { url } from '../url';\nimport { injectBreadcrumbConfig } from './breadcrumb.config';\nimport {\n Breadcrumb,\n createInternalBreadcrumb,\n getBreadcrumbInternals,\n InternalBreadcrumb,\n isInternalBreadcrumb,\n ResolvedLeafRoute,\n} from './breadcrumb.type';\n\nfunction leafRoutes(): Signal<ResolvedLeafRoute[]> {\n const router = inject(Router);\n\n const getLeafRoutes = (\n snapshot: RouterStateSnapshot,\n ): ResolvedLeafRoute[] => {\n const routes: ResolvedLeafRoute[] = [];\n let route: ActivatedRouteSnapshot | null = snapshot.root;\n const processed = new Set<string>();\n\n while (route) {\n const allSegments = route.pathFromRoot.flatMap(\n (snap) => snap.routeConfig?.path ?? [],\n );\n\n const segments = allSegments.filter(Boolean);\n\n const path = router.serializeUrl(router.parseUrl(segments.join('/')));\n\n if (processed.has(path)) {\n route = route.firstChild;\n continue;\n }\n processed.add(path);\n\n const parts = route.pathFromRoot\n .flatMap((snap) => snap.url ?? [])\n .map((u) => u.path)\n .filter(Boolean);\n\n const link = router.serializeUrl(router.parseUrl(parts.join('/')));\n\n routes.push({\n route,\n segment: {\n path: segments.at(-1) ?? '',\n resolved: parts.at(-1) ?? '',\n },\n path,\n link,\n });\n route = route.firstChild;\n }\n\n return routes;\n };\n\n const currentUrl = url();\n\n const leafRoutes = computed(() => {\n currentUrl();\n return getLeafRoutes(router.routerState.snapshot);\n });\n\n return leafRoutes;\n}\n\nfunction uppercaseFirst(str: string): string {\n const lcs = str.toLowerCase();\n return lcs.charAt(0).toUpperCase() + lcs.slice(1);\n}\n\nfunction removeMatrixAndQueryParams(path: string): string {\n const [cleanPath] = path.split(';');\n return cleanPath.split('?')[0];\n}\n\nfunction parsePathSegment(pathSegment: string): string {\n return pathSegment\n .split('/')\n .flatMap((part) => part.split('.'))\n .flatMap((part) => part.split('-'))\n .map((part) => uppercaseFirst(removeMatrixAndQueryParams(part)))\n .join(' ');\n}\n\nfunction generateLabel(leaf: ResolvedLeafRoute): string {\n const title = leaf.route.title ?? leaf.route.data?.['title'];\n\n if (title && typeof title === 'string') return title;\n if (leaf.segment.path.includes(':')) return leaf.segment.resolved;\n\n return parsePathSegment(leaf.segment.path);\n}\n\nfunction autoGenerateBreadcrumb(\n id: string,\n leaf: Signal<ResolvedLeafRoute>,\n autoGenerateFn: Signal<(leaf: ResolvedLeafRoute) => string>,\n): Breadcrumb {\n const label = computed(() => autoGenerateFn()(leaf()));\n\n return createInternalBreadcrumb(\n {\n id,\n label,\n ariaLabel: label,\n link: computed(() => leaf().link),\n },\n computed(\n () =>\n leaf().route.data?.['skipBreadcrumb'] !== true &&\n id !== '' &&\n id !== '/' &&\n leaf().segment.path !== '' &&\n leaf().segment.path !== '/' &&\n !leaf().segment.path.endsWith('/') &&\n !!label(),\n ),\n );\n}\n\nfunction injectGenerateLabelFn() {\n const { generation } = injectBreadcrumbConfig();\n\n if (typeof generation !== 'function') return computed(() => generateLabel);\n\n const provided = generation();\n return computed(() => provided);\n}\n\nfunction injectIsManual() {\n return injectBreadcrumbConfig().generation === 'manual';\n}\n\nfunction exposeActiveSignal(\n crumbSignal: Signal<Breadcrumb>,\n manual: boolean,\n): Signal<Breadcrumb> & {\n active: Signal<boolean>;\n} {\n const active = manual\n ? computed(() => {\n const crumb = crumbSignal();\n\n return (\n isInternalBreadcrumb(crumb) &&\n getBreadcrumbInternals(crumb).registered &&\n getBreadcrumbInternals(crumb).active()\n );\n })\n : computed(() => {\n const crumb = crumbSignal();\n if (!isInternalBreadcrumb(crumb)) return true;\n return getBreadcrumbInternals(crumb).active();\n });\n\n const sig = crumbSignal as Signal<Breadcrumb> & {\n active: Signal<boolean>;\n };\n\n sig.active = active;\n\n return sig;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class BreadcrumbStore {\n private readonly map = mutable<Map<string, InternalBreadcrumb>>(new Map());\n private readonly isManual = injectIsManual();\n private readonly autoGenerateLabelFn = injectGenerateLabelFn();\n\n private readonly all = mapArray(\n leafRoutes(),\n (leaf) => {\n const stableId = computed(() => leaf().path);\n\n return exposeActiveSignal(\n computed(\n () => {\n const id = stableId();\n\n const found = this.map().get(id);\n\n if (!found)\n return autoGenerateBreadcrumb(id, leaf, this.autoGenerateLabelFn);\n\n if (!id.includes(':')) return found;\n\n return {\n ...found,\n link: computed(() => leaf().link),\n };\n },\n {\n equal: (a, b) => a.id === b.id,\n },\n ),\n this.isManual,\n );\n },\n {\n equal: (a, b) => a.link === b.link,\n },\n );\n\n private readonly crumbs = computed((): Signal<Breadcrumb>[] =>\n this.all().filter((c) => c.active()),\n );\n\n readonly unwrapped = computed(() => this.crumbs().map((c) => c()));\n\n register(breadcrumb: InternalBreadcrumb) {\n this.map.inline((m) => m.set(breadcrumb.id, breadcrumb));\n\n return () => {\n this.map.inline((m) => m.delete(breadcrumb.id));\n };\n }\n\n has(id: string): boolean {\n return untracked(this.map).has(id);\n }\n}\n\n/**\n * Injects and provides access to a reactive list of breadcrumbs.\n *\n * The breadcrumbs are ordered and reflect the current active navigation path.\n * @see Breadcrumb\n * @returns `Signal<Breadcrumb[]>`\n *\n * @example\n * ```typescript\n * @Component({\n * selector: 'app-breadcrumbs',\n * template: `\n * <nav aria-label=\"breadcrumb\">\n * <ol>\n * @for (crumb of breadcrumbs(); track crumb.id) {\n * <li>\n * <a [href]=\"crumb.link()\" [attr.aria-label]=\"crumb.ariaLabel()\">{{ crumb.label() }}</a>\n * </li>\n * }\n * </ol>\n * </nav>\n * `\n * })\n * export class MyBreadcrumbsComponent {\n * breadcrumbs = injectBreadcrumbs();\n * }\n * ```\n */\nexport function injectBreadcrumbs() {\n const store = inject(BreadcrumbStore);\n return store.unwrapped;\n}\n","import { computed, DestroyRef, inject } from '@angular/core';\nimport {\n createUrlTreeFromSnapshot,\n Router,\n type ResolveFn,\n} from '@angular/router';\nimport { BreadcrumbStore } from './breadcrumb.store';\n\n/**\n * Options for defining a breadcrumb.\n *\n */\ntype CreateBreadcrumbOptions = {\n /**\n * The visible text for the breadcrumb.\n * Can be a static string or a function for dynamic labels.\n */\n label: string | (() => string);\n /**\n * An accessible label for the breadcrumb item.\n * Defaults to the value of `label` if not provided.\n * Can be a static string or a function returning a string for dynamic ARIA labels.\n */\n ariaLabel?: string | (() => string);\n /**\n * If `true`, the route resolver will wait until the `label` signal has a value before `resolving`\n */\n awaitValue?: boolean;\n};\n\nimport { until } from '@mmstack/primitives';\nimport { url } from '../url';\nimport { Breadcrumb, createInternalBreadcrumb } from './breadcrumb.type';\n\n/**\n * Creates and registers a breadcrumb for a specific route.\n * This function is designed to be used as an Angular Route `ResolveFn`.\n * It handles the registration of the breadcrumb with the `BreadcrumbStore`\n * and ensures automatic deregistration when the route is destroyed.\n *\n * @param factory A function that returns a `CreateBreadcrumbOptions` object.\n * @see CreateBreadcrumbOptions\n *\n * @example\n * ```typescript\n * export const appRoutes: Routes = [\n * {\n * path: 'home',\n * component: HomeComponent,\n * resolve: {\n * breadcrumb: createBreadcrumb(() => ({\n * label: 'Home',\n * });\n * },\n * path: 'users/:userId',\n * component: UserProfileComponent,\n * resolve: {\n * breadcrumb: createBreadcrumb(() => {\n * const userStore = inject(UserStore);\n * return {\n * label: () => userStore.user().name ?? 'Loading...\n * };\n * })\n * },\n * }\n * ];\n * ```\n */\nexport function createBreadcrumb(\n factory: () => CreateBreadcrumbOptions,\n): ResolveFn<void> {\n return async (route) => {\n const router = inject(Router);\n const store = inject(BreadcrumbStore);\n\n const segments = route.pathFromRoot.flatMap(\n (snap) => snap.routeConfig?.path ?? [],\n );\n\n const joinedSegments = segments.filter(Boolean).join('/');\n\n const fp = router.serializeUrl(router.parseUrl(joinedSegments));\n if (store.has(fp)) return Promise.resolve();\n\n const tree = createUrlTreeFromSnapshot(\n route,\n [],\n route.queryParams,\n route.fragment,\n );\n\n const provided = factory();\n\n const trigger = url();\n\n const link = computed(() => router.serializeUrl(tree));\n\n const { label, ariaLabel = label } = provided;\n\n const bc: Breadcrumb = {\n id: fp,\n ariaLabel:\n typeof ariaLabel === 'string'\n ? computed(() => ariaLabel)\n : computed(ariaLabel),\n label:\n typeof label === 'string' ? computed(() => label) : computed(label),\n link,\n };\n\n const deregister = store.register(\n createInternalBreadcrumb(\n bc,\n computed(() => route.data?.['skipBreadcrumb'] !== true),\n ),\n );\n\n inject(DestroyRef).onDestroy(deregister);\n\n if (provided.awaitValue) await until(bc.label, (v) => !!v);\n\n return Promise.resolve();\n };\n}\n","import { Injectable } from '@angular/core';\nimport { Subject } from 'rxjs';\n\n@Injectable({ providedIn: 'root' })\nexport class PreloadService {\n private readonly preloadOnDemand$ = new Subject<string>();\n readonly preloadRequested$ = this.preloadOnDemand$.asObservable();\n\n startPreload(routePath: string) {\n this.preloadOnDemand$.next(routePath);\n }\n}\n","function parsePathSegment(segmentString: string): {\n pathPart: string;\n matrixParams: Record<string, string>;\n} {\n const parts = segmentString.split(';');\n const pathPart = parts[0];\n const matrixParams: Record<string, string> = {};\n for (let i = 1; i < parts.length; i++) {\n const [key, value = 'true'] = parts[i].split('=');\n if (key) {\n matrixParams[key] = value;\n }\n }\n return { pathPart, matrixParams };\n}\n\nfunction createBasePredicate(path: string): (path: string) => boolean {\n const partPredicates = path\n .split('/')\n .filter((part) => !!part.trim())\n .map((configSegmentString) => {\n const { pathPart: configPathPart, matrixParams: configMatrixParams } =\n parsePathSegment(configSegmentString);\n\n let singlePathPartPredicate: (linkSegmentPathPart: string) => boolean;\n if (configPathPart.startsWith(':')) {\n singlePathPartPredicate = () => true;\n } else {\n singlePathPartPredicate = (linkSegmentPathPart: string) =>\n linkSegmentPathPart === configPathPart;\n }\n\n const configSegmentHasMatrixParams =\n Object.keys(configMatrixParams).length > 0;\n\n return (linkSegmentString: string) => {\n const { pathPart: linkPathPart, matrixParams: linkMatrixParams } =\n parsePathSegment(linkSegmentString);\n\n if (!singlePathPartPredicate(linkPathPart)) {\n return false;\n }\n\n if (!configSegmentHasMatrixParams) {\n return true;\n }\n\n return Object.entries(configMatrixParams).every(\n ([key, value]) =>\n linkMatrixParams.hasOwnProperty(key) &&\n linkMatrixParams[key] === value,\n );\n };\n });\n\n return (path: string) => {\n const linkPathOnly = path.split(/[?#]/).at(0) ?? '';\n if (!linkPathOnly && partPredicates.length > 0) return false;\n if (!linkPathOnly && partPredicates.length === 0) return true;\n\n const parts = linkPathOnly.split('/').filter((part) => !!part.trim());\n if (parts.length < partPredicates.length) return false;\n\n return parts.every((seg, idx) => {\n const pred = partPredicates.at(idx);\n if (!pred) return true;\n return pred(seg);\n });\n };\n}\n\ntype ParsedSegment = {\n pathPart: string;\n matrixParams: Record<string, string>;\n};\n\nfunction singleSegmentMatches(\n configSegment: ParsedSegment,\n linkSegment: ParsedSegment,\n): boolean {\n if (configSegment.pathPart.startsWith(':')) {\n } else if (configSegment.pathPart !== linkSegment.pathPart) {\n return false;\n }\n\n const configMatrix = configSegment.matrixParams;\n const linkMatrix = linkSegment.matrixParams;\n for (const key in configMatrix) {\n if (\n !linkMatrix.hasOwnProperty(key) ||\n linkMatrix[key] !== configMatrix[key]\n ) {\n return false;\n }\n }\n return true;\n}\n\nfunction matchSegmentsRecursive(\n configSegments: ParsedSegment[],\n linkSegments: ParsedSegment[],\n configIdx: number,\n linkIdx: number,\n): boolean {\n if (configIdx === configSegments.length) {\n return linkIdx === linkSegments.length;\n }\n\n if (linkIdx === linkSegments.length) {\n for (let i = configIdx; i < configSegments.length; i++) {\n if (configSegments[i].pathPart !== '**') {\n return false;\n }\n }\n return true;\n }\n\n const currentConfigSegment = configSegments[configIdx];\n\n if (currentConfigSegment.pathPart === '**') {\n if (\n matchSegmentsRecursive(\n configSegments,\n linkSegments,\n configIdx + 1,\n linkIdx,\n )\n ) {\n return true;\n }\n\n if (linkIdx < linkSegments.length) {\n if (\n matchSegmentsRecursive(\n configSegments,\n linkSegments,\n configIdx,\n linkIdx + 1,\n )\n ) {\n return true;\n }\n }\n\n return false;\n } else {\n if (\n linkIdx < linkSegments.length &&\n singleSegmentMatches(currentConfigSegment, linkSegments[linkIdx])\n ) {\n return matchSegmentsRecursive(\n configSegments,\n linkSegments,\n configIdx + 1,\n linkIdx + 1,\n );\n }\n\n return false;\n }\n}\n\nfunction createWildcardPredicate(path: string): (linkPath: string) => boolean {\n const configSegments = path\n .split('/')\n .filter((p) => !!p.trim())\n .map((segment) => parsePathSegment(segment));\n\n return (linkPath: string): boolean => {\n const linkPathOnly = linkPath.split(/[?#]/).at(0) ?? '';\n const linkSegments = linkPathOnly\n .split('/')\n .filter((p) => !!p.trim())\n .map((segment) => parsePathSegment(segment));\n\n return matchSegmentsRecursive(configSegments, linkSegments, 0, 0);\n };\n}\n\nexport function createRoutePredicate(\n path: string,\n): (linkPath: string) => boolean {\n return path.includes('**')\n ? createWildcardPredicate(path)\n : createBasePredicate(path);\n}\n","// The following functions are adapted from ngx-quicklink,\n// (https://github.com/mgechev/ngx-quicklink)\n// Copyright (c) Minko Gechev and contributors, licensed under the MIT License.\n\nimport { PRIMARY_OUTLET, Route } from '@angular/router';\n\nfunction isPrimaryRoute(route: Route): boolean {\n return route.outlet === PRIMARY_OUTLET || !route.outlet;\n}\n\nexport const findPath = (config: Route[], route: Route): string => {\n const configQueue = config.slice();\n const parent = new Map<Route, Route>();\n const visited = new Set<Route>();\n\n while (configQueue.length) {\n const el = configQueue.shift();\n if (!el) {\n continue;\n }\n\n visited.add(el);\n\n if (el === route) {\n break;\n }\n\n (el.children || []).forEach((childRoute: Route) => {\n if (!visited.has(childRoute)) {\n parent.set(childRoute, el);\n configQueue.push(childRoute);\n }\n });\n\n const lazyRoutes = (el as any)._loadedRoutes || [];\n if (Array.isArray(lazyRoutes)) {\n lazyRoutes.forEach((lazyRoute: Route) => {\n if (lazyRoute && !visited.has(lazyRoute)) {\n parent.set(lazyRoute, el);\n configQueue.push(lazyRoute);\n }\n });\n }\n }\n\n let path = '';\n let currentRoute: Route | undefined = route;\n\n while (currentRoute) {\n const currentPath = currentRoute.path || '';\n if (isPrimaryRoute(currentRoute)) {\n path = `/${currentPath}${path}`;\n } else {\n path = `/(${currentRoute.outlet}:${currentPath})${path}`;\n }\n currentRoute = parent.get(currentRoute);\n }\n\n let normalizedPath = path.replaceAll(/\\/+/g, '/');\n\n if (normalizedPath !== '/' && normalizedPath.endsWith('/')) {\n normalizedPath = normalizedPath.slice(0, -1);\n }\n\n return normalizedPath;\n};\n","import { inject, Injectable } from '@angular/core';\nimport { PreloadingStrategy, type Route, Router } from '@angular/router';\nimport { EMPTY, filter, finalize, Observable, switchMap, take } from 'rxjs';\nimport { createRoutePredicate, findPath } from '../util';\nimport { PreloadService } from './preload.service';\n\nfunction hasSlowConnection() {\n if (\n globalThis.window &&\n 'navigator' in globalThis.window &&\n 'connection' in globalThis.window.navigator &&\n typeof globalThis.window.navigator.connection === 'object' &&\n !!globalThis.window.navigator.connection\n ) {\n const is2g =\n 'effectiveType' in globalThis.window.navigator.connection &&\n typeof globalThis.window.navigator.connection.effectiveType ===\n 'string' &&\n globalThis.window.navigator.connection.effectiveType.endsWith('2g');\n if (is2g) return true;\n if (\n 'saveData' in globalThis.window.navigator.connection &&\n typeof globalThis.window.navigator.connection.saveData === 'boolean' &&\n globalThis.window.navigator.connection.saveData\n )\n return true;\n }\n\n return false;\n}\n\nfunction noPreload(route: Route) {\n return route.data && route.data['preload'] === false;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class PreloadStrategy implements PreloadingStrategy {\n private readonly loading = new Set<string>();\n private readonly router = inject(Router);\n private readonly svc = inject(PreloadService);\n\n preload(route: Route, load: () => Observable<any>): Observable<any> {\n if (noPreload(route) || hasSlowConnection()) return EMPTY;\n\n const fp = findPath(this.router.config, route);\n\n if (this.loading.has(fp)) return EMPTY;\n\n const predicate = createRoutePredicate(fp);\n return this.svc.preloadRequested$.pipe(\n filter((path) => path === fp || predicate(path)),\n take(1),\n switchMap(() => load()),\n finalize(() => this.loading.delete(fp)),\n );\n }\n}\n","import {\n booleanAttribute,\n computed,\n Directive,\n effect,\n inject,\n input,\n output,\n untracked,\n} from '@angular/core';\nimport {\n type ActivatedRoute,\n type Params,\n Router,\n RouterLink,\n RouterLinkWithHref,\n UrlTree,\n} from '@angular/router';\nimport { elementVisibility } from '@mmstack/primitives';\nimport { PreloadService } from './preloading';\n\nfunction inputToUrlTree(\n router: Router,\n link: string | any[] | UrlTree | null,\n relativeTo?: ActivatedRoute,\n queryParams?: Params,\n fragment?: string,\n queryParamsHandling?: 'merge' | 'preserve' | '',\n routerLinkUrlTree?: UrlTree | null,\n): UrlTree | null {\n if (!link) return null;\n if (routerLinkUrlTree) return routerLinkUrlTree;\n\n if (link instanceof UrlTree) return link;\n\n const arr = Array.isArray(link) ? link : [link];\n\n return router.createUrlTree(arr, {\n relativeTo,\n queryParams,\n fragment,\n queryParamsHandling,\n });\n}\n\nfunction treeToSerializedUrl(\n router: Router,\n urlTree: UrlTree | null,\n): string | null {\n if (!urlTree) return null;\n return router.serializeUrl(urlTree);\n}\n\nexport function injectTriggerPreload() {\n const svc = inject(PreloadService);\n const router = inject(Router);\n\n return (\n link: string | any[] | UrlTree | null,\n relativeTo?: ActivatedRoute,\n queryParams?: Params,\n fragment?: string,\n queryParamsHandling?: 'merge' | 'preserve' | '',\n ) => {\n const urlTree = inputToUrlTree(\n router,\n link,\n relativeTo,\n queryParams,\n fragment,\n queryParamsHandling,\n );\n const fullPath = treeToSerializedUrl(router, urlTree);\n if (!fullPath) return;\n\n svc.startPreload(fullPath);\n };\n}\n\n@Directive({\n selector: '[mmLink]',\n exportAs: 'mmLink',\n host: {\n '(mouseenter)': 'onHover()',\n },\n hostDirectives: [\n {\n directive: RouterLink,\n inputs: [\n 'routerLink: mmLink',\n 'target',\n 'queryParams',\n 'fragment',\n 'queryParamsHandling',\n 'state',\n 'relativeTo',\n 'skipLocationChange',\n 'replaceUrl',\n ],\n },\n ],\n})\nexport class LinkDirective {\n private readonly routerLink =\n inject(RouterLink, {\n self: true,\n optional: true,\n }) ?? inject(RouterLinkWithHref, { self: true, optional: true });\n\n private readonly svc = inject(PreloadService);\n private readonly router = inject(Router);\n\n readonly target = input<string>();\n readonly queryParams = input<Params>();\n readonly fragment = input<string>();\n readonly queryParamsHandling = input<'merge' | 'preserve' | ''>();\n readonly state = input<Record<string, any>>();\n readonly info = input<unknown>();\n readonly relativeTo = input<ActivatedRoute>();\n readonly skipLocationChange = input(false, { transform: booleanAttribute });\n readonly replaceUrl = input(false, { transform: booleanAttribute });\n readonly mmLink = input.required<string | any[] | UrlTree | null>();\n readonly preloadOn = input<'hover' | 'visible' | null>('hover');\n\n readonly preloading = output<void>();\n\n private readonly urlTree = computed(() => {\n return inputToUrlTree(\n this.router,\n this.mmLink(),\n this.relativeTo(),\n this.queryParams(),\n this.fragment(),\n this.queryParamsHandling(),\n this.routerLink?.urlTree,\n );\n });\n\n private readonly fullPath = computed(() => {\n return treeToSerializedUrl(this.router, this.urlTree());\n });\n\n onHover() {\n if (untracked(this.preloadOn) !== 'hover') return;\n this.requestPreload();\n }\n\n constructor() {\n const intersection = elementVisibility();\n\n effect(() => {\n if (this.preloadOn() !== 'visible') return;\n if (intersection.visible()) this.requestPreload();\n });\n }\n\n private requestPreload() {\n const fp = untracked(this.fullPath);\n if (!this.routerLink || !fp) return;\n this.svc.startPreload(fp);\n this.preloading.emit();\n }\n\n onClick(\n button: number,\n ctrlKey: boolean,\n shiftKey: boolean,\n altKey: boolean,\n metaKey: boolean,\n ) {\n return this.routerLink?.onClick(button, ctrlKey, shiftKey, altKey, metaKey);\n }\n}\n","import {\r\n computed,\r\n inject,\r\n isSignal,\r\n untracked,\r\n type WritableSignal,\r\n} from '@angular/core';\r\nimport { toSignal } from '@angular/core/rxjs-interop';\r\nimport { ActivatedRoute, Router } from '@angular/router';\r\nimport { toWritable } from '@mmstack/primitives';\r\n\r\n/**\r\n * Creates a WritableSignal that synchronizes with a specific URL query parameter,\r\n * enabling two-way binding between the signal's state and the URL.\r\n *\r\n * Reading the signal provides the current value of the query parameter (or null if absent).\r\n * Setting the signal updates the URL query parameter using `Router.navigate`, triggering\r\n * navigation and causing the signal to update reactively if the navigation is successful.\r\n *\r\n * @param key The key of the query parameter to synchronize with.\r\n * Can be a static string (e.g., `'search'`) or a function/signal returning a string\r\n * for dynamic keys (e.g., `() => this.userId() + '_filter'` or `computed(() => this.category() + '_sort')`).\r\n * The signal will reactively update if the key returned by the function/signal changes.\r\n * @returns {WritableSignal<string | null>} A signal representing the query parameter's value.\r\n * - Reading returns the current value string, or `null` if the parameter is absent in the URL.\r\n * - Setting the signal to a string updates the query parameter in the URL (e.g., `signal.set('value')` results in `?key=value`).\r\n * - Setting the signal to `null` removes the query parameter from the URL (e.g., `signal.set(null)` results in `?otherParam=...`).\r\n * - Automatically reflects changes if the query parameters update due to external navigation.\r\n * @remarks\r\n * - Requires Angular's `ActivatedRoute` and `Router` to be available in the injection context.\r\n * - Uses `Router.navigate` with `queryParamsHandling: 'merge'` to preserve other existing query parameters during updates.\r\n * - Handles dynamic keys reactively. If the result of the `key` function/signal changes, the signal will start reflecting the value of the *new* query parameter key.\r\n * - During Server-Side Rendering (SSR), it reads the initial value from the route snapshot. Write operations (`set`) might have limited or no effect on the server depending on the platform configuration.\r\n *\r\n * @example\r\n * ```ts\r\n * import { Component, computed, effect, signal } from '@angular/core';\r\n * import { queryParam } from '@mmstack/router-core'; // Adjust import path as needed\r\n * // import { FormsModule } from '@angular/forms'; // If using ngModel\r\n *\r\n * @Component({\r\n * selector: 'app-product-list',\r\n * standalone: true,\r\n * // imports: [FormsModule], // If using ngModel\r\n * template: `\r\n * <div>\r\n * Sort By:\r\n * <select [value]=\"sortSignal() ?? ''\" (change)=\"sortSignal.set($any($event.target).value || null)\">\r\n * <option value=\"\">Default</option>\r\n * <option value=\"price_asc\">Price Asc</option>\r\n * <option value=\"price_desc\">Price Desc</option>\r\n * <option value=\"name\">Name</option>\r\n * </select>\r\n * <button (click)=\"sortSignal.set(null)\" [disabled]=\"!sortSignal()\">Clear Sort</button>\r\n * </div>\r\n * <div>\r\n * Page:\r\n * <input type=\"number\" min=\"1\" [value]=\"pageSignal() ?? '1'\" #p (input)=\"setPage(p.value)\"/>\r\n * </div>\r\n * * `\r\n * })\r\n * export class ProductListComponent {\r\n * // Two-way bind the 'sort' query parameter (?sort=...)\r\n * // Defaults to null if param is missing\r\n * sortSignal = queryParam('sort');\r\n *\r\n * // Example with a different type (needs serialization or separate logic)\r\n * // For simplicity, we treat page as string | null here\r\n * pageSignal = queryParam('page');\r\n *\r\n * constructor() {\r\n * effect(() => {\r\n * const currentSort = this.sortSignal();\r\n * const currentPage = this.pageSignal(); // Read as string | null\r\n * console.log('Sort/Page changed, reloading products for:', { sort: currentSort, page: currentPage });\r\n * // --- Fetch data based on currentSort and currentPage ---\r\n * });\r\n * }\r\n *\r\n * setPage(value: string): void {\r\n * const pageNum = parseInt(value, 10);\r\n * // Set to null if page is 1 (to remove param), otherwise set string value\r\n * this.pageSignal.set(isNaN(pageNum) || pageNum <= 1 ? null : pageNum.toString());\r\n * }\r\n * }\r\n * ```\r\n */\r\nexport function queryParam(\r\n key: string | (() => string),\r\n): WritableSignal<string | null> {\r\n const route = inject(ActivatedRoute);\r\n const router = inject(Router);\r\n\r\n const keySignal =\r\n typeof key === 'string'\r\n ? computed(() => key)\r\n : isSignal(key)\r\n ? key\r\n : computed(key);\r\n\r\n const queryParamMap = toSignal(route.queryParamMap, {\r\n initialValue: route.snapshot.queryParamMap,\r\n });\r\n\r\n const queryParams = toSignal(route.queryParams, {\r\n initialValue: route.snapshot.queryParams,\r\n });\r\n\r\n const queryParam = computed(() => queryParamMap().get(keySignal()));\r\n\r\n const set = (newValue: string | null) => {\r\n const next = {\r\n ...untracked(queryParams),\r\n };\r\n const key = untracked(keySignal);\r\n\r\n if (newValue === null) {\r\n delete next[key];\r\n } else {\r\n next[key] = newValue;\r\n }\r\n\r\n router.navigate([], {\r\n relativeTo: route,\r\n queryParams: next,\r\n queryParamsHandling: 'merge',\r\n });\r\n };\r\n\r\n return toWritable(queryParam, set);\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["parsePathSegment","filter"],"mappings":"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"}
@@ -1,14 +1,73 @@
1
1
  import { InjectionToken } from '@angular/core';
2
2
  import { ResolvedLeafRoute } from './breadcrumb.type';
3
+ /**
4
+ * A function that returns a custom label generation function.
5
+ * The outer function is called in a root injection context
6
+ * The returned function takes a `ResolvedLeafRoute` and produces a string label for the breadcrumb.
7
+ * As the inner function is wrapped in a computed, changes to signals called within it will update the breadcrumb label reactively.
8
+ */
3
9
  type GenerateBreadcrumbFn = () => (leaf: ResolvedLeafRoute) => string;
10
+ /**
11
+ * Configuration options for the breadcrumb system.
12
+ * Use `provideBreadcrumbConfig` to supply these options to your application.
13
+ */
4
14
  export type BreadcrumbConfig = {
15
+ /**
16
+ * Defines how breadcrumb labels are generated.
17
+ * - If set to `'manual'`, breadcrumbs will only be displayed if manually registered
18
+ * via `createBreadcrumb`. Automatic generation based on routes is disabled.
19
+ * - Alternatively provide a custom label generation function
20
+ * If left undefined, the system will automatically generate labels based on the route's title, data, or path.
21
+ * @see GenerateBreadcrumbFn
22
+ * @example
23
+ * ```typescript
24
+ * // For custom label generation:
25
+ * // const myCustomLabelGenerator = () => (leaf: ResolvedLeafRoute) => {
26
+ * // return leaf.route.data?.['customTitle'] || leaf.route.routeConfig?.path || 'Default';
27
+ * // };
28
+ * //
29
+ * // config: { generation: myCustomLabelGenerator }
30
+ * ```
31
+ */
5
32
  generation?: 'manual' | GenerateBreadcrumbFn;
6
33
  };
34
+ /**
35
+ * Provides configuration for the breadcrumb system.
36
+ * @param config - A partial `BreadcrumbConfig` object with the desired settings. *
37
+ * @see BreadcrumbConfig
38
+ * @example
39
+ * ```typescript
40
+ * // In your app.module.ts or a standalone component's providers:
41
+ * // import { provideBreadcrumbConfig } from './breadcrumb.config'; // Adjust path
42
+ * // import { ResolvedLeafRoute } from './breadcrumb.type'; // Adjust path
43
+ *
44
+ * // const customLabelStrategy: GenerateBreadcrumbFn = () => {
45
+ * // return (leaf: ResolvedLeafRoute): string => {
46
+ * // // Example: Prioritize a 'navTitle' data property
47
+ * // if (leaf.route.data?.['navTitle']) {
48
+ * // return leaf.route.data['navTitle'];
49
+ * // }
50
+ * // // Fallback to a default mechanism
51
+ * // return leaf.route.title || leaf.segment.resolved || 'Unnamed';
52
+ * // };
53
+ * // };
54
+ *
55
+ * export const appConfig = [
56
+ * // ...rest
57
+ * provideBreadcrumbConfig({
58
+ * generation: customLabelStrategy, // or 'manual' to disable auto-generation
59
+ * }),
60
+ * ]
61
+ * ```
62
+ */
7
63
  export declare function provideBreadcrumbConfig(config: Partial<BreadcrumbConfig>): {
8
64
  provide: InjectionToken<BreadcrumbConfig>;
9
65
  useValue: {
10
66
  generation?: ("manual" | GenerateBreadcrumbFn) | undefined;
11
67
  };
12
68
  };
69
+ /**
70
+ * @internal
71
+ */
13
72
  export declare function injectBreadcrumbConfig(): BreadcrumbConfig;
14
73
  export {};
@@ -1,8 +1,58 @@
1
1
  import { type ResolveFn } from '@angular/router';
2
+ /**
3
+ * Options for defining a breadcrumb.
4
+ *
5
+ */
2
6
  type CreateBreadcrumbOptions = {
7
+ /**
8
+ * The visible text for the breadcrumb.
9
+ * Can be a static string or a function for dynamic labels.
10
+ */
3
11
  label: string | (() => string);
12
+ /**
13
+ * An accessible label for the breadcrumb item.
14
+ * Defaults to the value of `label` if not provided.
15
+ * Can be a static string or a function returning a string for dynamic ARIA labels.
16
+ */
4
17
  ariaLabel?: string | (() => string);
18
+ /**
19
+ * If `true`, the route resolver will wait until the `label` signal has a value before `resolving`
20
+ */
5
21
  awaitValue?: boolean;
6
22
  };
23
+ /**
24
+ * Creates and registers a breadcrumb for a specific route.
25
+ * This function is designed to be used as an Angular Route `ResolveFn`.
26
+ * It handles the registration of the breadcrumb with the `BreadcrumbStore`
27
+ * and ensures automatic deregistration when the route is destroyed.
28
+ *
29
+ * @param factory A function that returns a `CreateBreadcrumbOptions` object.
30
+ * @see CreateBreadcrumbOptions
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * export const appRoutes: Routes = [
35
+ * {
36
+ * path: 'home',
37
+ * component: HomeComponent,
38
+ * resolve: {
39
+ * breadcrumb: createBreadcrumb(() => ({
40
+ * label: 'Home',
41
+ * });
42
+ * },
43
+ * path: 'users/:userId',
44
+ * component: UserProfileComponent,
45
+ * resolve: {
46
+ * breadcrumb: createBreadcrumb(() => {
47
+ * const userStore = inject(UserStore);
48
+ * return {
49
+ * label: () => userStore.user().name ?? 'Loading...
50
+ * };
51
+ * })
52
+ * },
53
+ * }
54
+ * ];
55
+ * ```
56
+ */
7
57
  export declare function createBreadcrumb(factory: () => CreateBreadcrumbOptions): ResolveFn<void>;
8
58
  export {};
@@ -13,4 +13,32 @@ export declare class BreadcrumbStore {
13
13
  static ɵfac: i0.ɵɵFactoryDeclaration<BreadcrumbStore, never>;
14
14
  static ɵprov: i0.ɵɵInjectableDeclaration<BreadcrumbStore>;
15
15
  }
16
+ /**
17
+ * Injects and provides access to a reactive list of breadcrumbs.
18
+ *
19
+ * The breadcrumbs are ordered and reflect the current active navigation path.
20
+ * @see Breadcrumb
21
+ * @returns `Signal<Breadcrumb[]>`
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * @Component({
26
+ * selector: 'app-breadcrumbs',
27
+ * template: `
28
+ * <nav aria-label="breadcrumb">
29
+ * <ol>
30
+ * @for (crumb of breadcrumbs(); track crumb.id) {
31
+ * <li>
32
+ * <a [href]="crumb.link()" [attr.aria-label]="crumb.ariaLabel()">{{ crumb.label() }}</a>
33
+ * </li>
34
+ * }
35
+ * </ol>
36
+ * </nav>
37
+ * `
38
+ * })
39
+ * export class MyBreadcrumbsComponent {
40
+ * breadcrumbs = injectBreadcrumbs();
41
+ * }
42
+ * ```
43
+ */
16
44
  export declare function injectBreadcrumbs(): Signal<Breadcrumb[]>;
@@ -1,11 +1,35 @@
1
1
  import { type Signal } from '@angular/core';
2
2
  import { ActivatedRouteSnapshot } from '@angular/router';
3
+ /**
4
+ * Represents a single breadcrumb item within the navigation path.
5
+ * All dynamic properties are represented as Angular Signals to enable reactivity.
6
+ */
3
7
  export type Breadcrumb = {
8
+ /**
9
+ * A unique identifier for the breadcrumb item. Generally the unresolved path for example `/posts/:id`.
10
+ * Useful for `@for` tracking in templates.
11
+ */
4
12
  id: string;
13
+ /**
14
+ * The visible text for the breadcrumb item.
15
+ * Updated reactively as the url/link based on
16
+ * either a provided definition, or the current route.
17
+ */
5
18
  label: Signal<string>;
19
+ /**
20
+ * An accessible label for the breadcrumb item.
21
+ * Defaults to the same value as `label` if not provided.
22
+ */
6
23
  ariaLabel: Signal<string>;
24
+ /**
25
+ * The URL link for the breadcrumb item.
26
+ * Updates as the route changes.
27
+ */
7
28
  link: Signal<string>;
8
29
  };
30
+ /**
31
+ * @internal
32
+ */
9
33
  declare const INTERNAL_BREADCRUMB_SYMBOL: unique symbol;
10
34
  /**
11
35
  * @internal
@@ -16,10 +40,16 @@ export type InternalBreadcrumb = Breadcrumb & {
16
40
  registered: boolean;
17
41
  };
18
42
  };
43
+ /**
44
+ * @internal
45
+ */
19
46
  export declare function getBreadcrumbInternals(breadcrumb: InternalBreadcrumb): {
20
47
  active: Signal<boolean>;
21
48
  registered: boolean;
22
49
  };
50
+ /**
51
+ * @internal
52
+ */
23
53
  export declare function createInternalBreadcrumb(bc: Breadcrumb, active: Signal<boolean>, registered?: boolean): InternalBreadcrumb;
24
54
  /**
25
55
  * @internal
@@ -33,5 +63,8 @@ export type ResolvedLeafRoute = {
33
63
  path: string;
34
64
  link: string;
35
65
  };
66
+ /**
67
+ * @internal
68
+ */
36
69
  export declare function isInternalBreadcrumb(breadcrumb: Breadcrumb | InternalBreadcrumb): breadcrumb is InternalBreadcrumb;
37
70
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmstack/router-core",
3
- "version": "19.2.9",
3
+ "version": "19.3.0",
4
4
  "keywords": [
5
5
  "angular",
6
6
  "signals",
@@ -10,7 +10,8 @@
10
10
  "params",
11
11
  "preloading",
12
12
  "preload",
13
- "navigation"
13
+ "navigation",
14
+ "breadcrumbs"
14
15
  ],
15
16
  "license": "MIT",
16
17
  "repository": {