ng-hub-ui-breadcrumbs 22.5.2 → 22.7.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
|
@@ -122,7 +122,7 @@ const routes: Routes = [
|
|
|
122
122
|
|
|
123
123
|
### 1. Import the Component
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
Import `HubBreadcrumbComponent` directly in your component. (`HubBreadcrumbsModule` still works in a module-based setup, but it is deprecated — see [HubBreadcrumbsModule](#hubbreadcrumbsmodule).)
|
|
126
126
|
|
|
127
127
|
```typescript
|
|
128
128
|
import { HubBreadcrumbComponent } from 'ng-hub-ui-breadcrumbs';
|
|
@@ -271,7 +271,7 @@ Fully customize the structure, including separators/dividers.
|
|
|
271
271
|
|
|
272
272
|
### HubBreadcrumbComponent
|
|
273
273
|
|
|
274
|
-
The main container component. It reads the breadcrumb trail directly from the Angular `Router` and exposes
|
|
274
|
+
The main container component. It reads the breadcrumb trail directly from the Angular `Router` — or takes it from `items` when you hand it one — and exposes seven inputs, one output and an optional item template.
|
|
275
275
|
|
|
276
276
|
| Selector | Host class |
|
|
277
277
|
| ---------------- | ----------------- |
|
|
@@ -279,20 +279,20 @@ The main container component. It reads the breadcrumb trail directly from the An
|
|
|
279
279
|
|
|
280
280
|
#### Inputs
|
|
281
281
|
|
|
282
|
-
| Input
|
|
283
|
-
|
|
|
284
|
-
| `variant`
|
|
285
|
-
| `truncateItems`
|
|
286
|
-
| `items`
|
|
287
|
-
| `maxItems`
|
|
288
|
-
| `itemsBeforeCollapse` | `number`
|
|
289
|
-
| `itemsAfterCollapse`
|
|
290
|
-
| `collapsedAriaLabel`
|
|
282
|
+
| Input | Type | Default | Description |
|
|
283
|
+
| --------------------- | -------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
284
|
+
| `variant` | `string` | `undefined` | Selects a **semantic accent** for the breadcrumb links and their hover. The built-in values (`primary`, `secondary`, `success`, `danger`, `warning`, `info`, `neutral`, `light`, `dark`) map to the exact design-system tints; **any other string is also accepted** and resolves through `--hub-sys-color-<variant>`. The current (last) item always stays muted. When omitted, links use the standard link colour (no visual change). |
|
|
285
|
+
| `truncateItems` | `boolean` | `false` | When `true`, clips each label to `--hub-breadcrumb-max-item-width` (default `12rem`) with an ellipsis and shows the full text as a tooltip when a label overflows. Off by default, so the standard layout and wrapping are unchanged. It covers a `hubBreadcrumbItem` template too: the component draws the clipping box (`span.hub-breadcrumb__custom`) around the projected content, since scoped styles cannot reach elements the consuming component owns. |
|
|
286
|
+
| `items` | `BreadcrumbItem[] \| null` | `null` | Trail supplied by you, replacing the one derived from the router. The way in for crumbs the route tree cannot express — an ancestor served by another application, or a trail assembled by hand. Left `null`, the component keeps reading `HubBreadcrumbsService`. |
|
|
287
|
+
| `maxItems` | `number \| undefined` | `undefined` | Length above which the trail collapses behind an indicator. Undefined never collapses, however long the trail grows. |
|
|
288
|
+
| `itemsBeforeCollapse` | `number` | `1` | Crumbs kept at the head of a collapsed trail. |
|
|
289
|
+
| `itemsAfterCollapse` | `number` | `1` | Crumbs kept at the tail of a collapsed trail, the current page included. |
|
|
290
|
+
| `collapsedAriaLabel` | `string` | `'Show the hidden breadcrumb items'` | Accessible name of the collapsed indicator. It is an input because it is the one string this component announces, and the library carries no translations of its own. |
|
|
291
291
|
|
|
292
292
|
#### Outputs
|
|
293
293
|
|
|
294
|
-
| Output
|
|
295
|
-
|
|
|
294
|
+
| Output | Type | Description |
|
|
295
|
+
| ---------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
296
296
|
| `collapsedClick` | `void` | Fires when the collapsed indicator is activated. The trail expands on its own; the event is there for consumers that want to react as well — open a menu of the hidden crumbs, log the interaction. |
|
|
297
297
|
|
|
298
298
|
```html
|
|
@@ -316,8 +316,9 @@ The main container component. It reads the breadcrumb trail directly from the An
|
|
|
316
316
|
|
|
317
317
|
Above `maxItems` crumbs the middle folds behind a `…` button. The button takes
|
|
318
318
|
keyboard focus, announces itself with `collapsedAriaLabel`, opens the trail in
|
|
319
|
-
place and emits `collapsedClick`.
|
|
320
|
-
|
|
319
|
+
place and emits `collapsedClick`. Expanding removes the button, so focus moves on
|
|
320
|
+
to the first crumb it revealed instead of falling back to the page body. An
|
|
321
|
+
expansion answers one trail: the next navigation collapses it again.
|
|
321
322
|
|
|
322
323
|
#### Crumbs that leave the application
|
|
323
324
|
|
|
@@ -367,7 +368,7 @@ import { provideHubBreadcrumbTooltip } from 'ng-hub-ui-breadcrumbs';
|
|
|
367
368
|
import { hubTooltipAdapter } from 'ng-hub-ui-utils';
|
|
368
369
|
|
|
369
370
|
export const appConfig: ApplicationConfig = {
|
|
370
|
-
|
|
371
|
+
providers: [provideHubBreadcrumbTooltip(hubTooltipAdapter)]
|
|
371
372
|
};
|
|
372
373
|
```
|
|
373
374
|
|
|
@@ -383,49 +384,93 @@ A structural directive used to define a custom template for breadcrumb items.
|
|
|
383
384
|
| --------------------- | --------------------------- |
|
|
384
385
|
| `[hubBreadcrumbItem]` | `BreadcrumbTemplateContext` |
|
|
385
386
|
|
|
387
|
+
### HubBreadcrumbLabelDirective
|
|
388
|
+
|
|
389
|
+
Adds the overflow tooltip to a breadcrumb label. Since 22.7.0 the component wraps a
|
|
390
|
+
`hubBreadcrumbItem` template in its own clipping box, so a custom crumb gets the tooltip
|
|
391
|
+
without asking. Apply the directive by hand only to give it different text.
|
|
392
|
+
|
|
393
|
+
| Selector | Input | Default |
|
|
394
|
+
| ---------------------- | ------------------------------------------------------------ | ------- |
|
|
395
|
+
| `[hubBreadcrumbLabel]` | `hubBreadcrumbLabel: string` (alias) — explicit tooltip text | `''` |
|
|
396
|
+
|
|
397
|
+
Left empty, the tooltip text is the host element's own text content, and it is shown only
|
|
398
|
+
while that text is actually clipped. The directive never clips anything itself: the ellipsis
|
|
399
|
+
comes from the `truncateItems` styles.
|
|
400
|
+
|
|
401
|
+
Applying it by hand is optional. The component already puts it on the labels it renders and on
|
|
402
|
+
the box it wraps a `hubBreadcrumbItem` template in, so a custom crumb is clipped and gets its
|
|
403
|
+
tooltip with nothing added. Reach for the directive when the tooltip should say something other
|
|
404
|
+
than the label — a full path, a date spelled out — and import `HubBreadcrumbLabelDirective` into
|
|
405
|
+
the component that declares the template.
|
|
406
|
+
|
|
407
|
+
```html
|
|
408
|
+
<hub-breadcrumb [truncateItems]="true">
|
|
409
|
+
<ng-template hubBreadcrumbItem let-item>
|
|
410
|
+
<a class="my-crumb" [hubBreadcrumbLabel]="item.url" [routerLink]="item.url">{{ item.label }}</a>
|
|
411
|
+
</ng-template>
|
|
412
|
+
</hub-breadcrumb>
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Tooltip adapter
|
|
416
|
+
|
|
417
|
+
The contract truncated labels use to reach a richer tooltip. It is structurally typed and
|
|
418
|
+
declared here rather than imported, so the package keeps zero hard dependencies.
|
|
419
|
+
|
|
420
|
+
| Export | Kind | Description |
|
|
421
|
+
| -------------------------------- | ---------------------- | ---------------------------------------------------------------------- |
|
|
422
|
+
| `provideHubBreadcrumbTooltip()` | `EnvironmentProviders` | Registers an adapter once for the whole application. |
|
|
423
|
+
| `HUB_BREADCRUMB_TOOLTIP_ADAPTER` | `InjectionToken` | The token the provider fills. Inject it with `{ optional: true }`. |
|
|
424
|
+
| `HubBreadcrumbTooltipAdapter` | interface | `attach(host: HTMLElement, text: string): HubBreadcrumbTooltipHandle`. |
|
|
425
|
+
| `HubBreadcrumbTooltipHandle` | interface | `update(text: string): void` and `destroy(): void`. |
|
|
426
|
+
|
|
386
427
|
### HubBreadcrumbsService
|
|
387
428
|
|
|
388
|
-
An injectable (`providedIn: 'root'`) service that
|
|
429
|
+
An injectable (`providedIn: 'root'`) service that publishes the breadcrumb trail. The component reads the signal; you can also inject it directly when you need the breadcrumb data elsewhere.
|
|
389
430
|
|
|
390
|
-
| Member
|
|
391
|
-
|
|
|
392
|
-
| `breadcrumbs
|
|
431
|
+
| Member | Type | Description |
|
|
432
|
+
| -------------- | ------------------------------ | ------------------------------------------------------------------------------- |
|
|
433
|
+
| `breadcrumbs` | `Signal<BreadcrumbItem[]>` | The current trail. Read it in a template or a `computed`, with nothing to wrap. |
|
|
434
|
+
| `breadcrumbs$` | `Observable<BreadcrumbItem[]>` | The same trail as a stream, for code already composing with rxjs. |
|
|
435
|
+
|
|
436
|
+
Replacing the service (a test double, a facade over another source) means publishing
|
|
437
|
+
`breadcrumbs`: that is the member the component reads.
|
|
393
438
|
|
|
394
439
|
### HubBreadcrumbsModule
|
|
395
440
|
|
|
396
|
-
An
|
|
441
|
+
**Deprecated — removed in 23.0.0.** An `NgModule` that imports and exports `HubBreadcrumbComponent` and `HubBreadcrumbItemDirective` for module-based applications, and provides nothing of its own. Import the two declarables directly instead; `HubBreadcrumbsService` is `providedIn: 'root'` and never travelled through the module. See `BREAKING_CHANGES.md`.
|
|
397
442
|
|
|
398
443
|
### Interfaces
|
|
399
444
|
|
|
400
445
|
#### BreadcrumbItem
|
|
401
446
|
|
|
402
|
-
| Property
|
|
403
|
-
|
|
|
404
|
-
| `label`
|
|
405
|
-
| `url`
|
|
406
|
-
| `data`
|
|
407
|
-
| `href`
|
|
408
|
-
| `target`
|
|
409
|
-
| `rel`
|
|
410
|
-
| `download` | `string` | Optional. Anchor `download`: the crumb points at a file to save instead of a page to open.
|
|
447
|
+
| Property | Type | Description |
|
|
448
|
+
| ---------- | -------- | -------------------------------------------------------------------------------------------------------- |
|
|
449
|
+
| `label` | `string` | The resolved text to display for the breadcrumb. |
|
|
450
|
+
| `url` | `string` | The in-app destination, handed to `routerLink`. |
|
|
451
|
+
| `data` | `any` | Optional. The original route data object (useful for icons, etc.). |
|
|
452
|
+
| `href` | `string` | Optional. External destination. When present the crumb renders a plain anchor instead of a `routerLink`. |
|
|
453
|
+
| `target` | `string` | Optional. Anchor `target` (e.g. `_blank`). Only meaningful alongside `href`. |
|
|
454
|
+
| `rel` | `string` | Optional. Anchor `rel`. Left unset, a `_blank` crumb still gets `noopener noreferrer`. |
|
|
455
|
+
| `download` | `string` | Optional. Anchor `download`: the crumb points at a file to save instead of a page to open. |
|
|
411
456
|
|
|
412
457
|
#### BreadcrumbRouteConfig
|
|
413
458
|
|
|
414
459
|
The object form accepted by a route's `data.breadcrumb`, for crumbs whose destination lies outside the router. The string and function forms stay valid and remain the right choice for an ordinary in-app crumb.
|
|
415
460
|
|
|
416
|
-
| Property | Type
|
|
417
|
-
| ---------- |
|
|
418
|
-
| `label` | `string \| ((data: any) => string)`
|
|
419
|
-
| `href` | `string`
|
|
420
|
-
| `target` | `string`
|
|
421
|
-
| `rel` | `string`
|
|
422
|
-
| `download` | `string`
|
|
461
|
+
| Property | Type | Description |
|
|
462
|
+
| ---------- | ----------------------------------- | ------------------------------------------------------------------ |
|
|
463
|
+
| `label` | `string \| ((data: any) => string)` | Static label, or a function receiving the route's resolved `data`. |
|
|
464
|
+
| `href` | `string` | Optional. Same as on `BreadcrumbItem`. |
|
|
465
|
+
| `target` | `string` | Optional. Same as on `BreadcrumbItem`. |
|
|
466
|
+
| `rel` | `string` | Optional. Same as on `BreadcrumbItem`. |
|
|
467
|
+
| `download` | `string` | Optional. Same as on `BreadcrumbItem`. |
|
|
423
468
|
|
|
424
469
|
#### BreadcrumbTemplateContext
|
|
425
470
|
|
|
426
|
-
| Property | Type | Description
|
|
427
|
-
| ----------- | ---------------- |
|
|
428
|
-
| `$implicit` | `BreadcrumbItem` | The current breadcrumb item object (bound via `let-item`).
|
|
471
|
+
| Property | Type | Description |
|
|
472
|
+
| ----------- | ---------------- | --------------------------------------------------------------- |
|
|
473
|
+
| `$implicit` | `BreadcrumbItem` | The current breadcrumb item object (bound via `let-item`). |
|
|
429
474
|
| `isLast` | `boolean` | `true` if this item is the last one in the list (current page). |
|
|
430
475
|
|
|
431
476
|
## Styling
|
|
@@ -450,11 +495,12 @@ For a complete and up-to-date token catalog, see [CSS Variables Reference](./doc
|
|
|
450
495
|
The link colour follows the `--hub-breadcrumb-accent` token (which itself defaults to the standard link colour). Setting a `variant` re-bases this token; you can also override it directly:
|
|
451
496
|
|
|
452
497
|
```scss
|
|
453
|
-
/* The accent is
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
498
|
+
/* The accent slot is deliberately not declared on the component's host, so any rule of
|
|
499
|
+
yours wins with no scoping trick: the crumb element by tag or by class, or an ancestor
|
|
500
|
+
it inherits from. A `variant` still wins over both — that is what a variant is for.
|
|
501
|
+
The remaining tokens keep their defaults on `:host`, so those go on the crumb element
|
|
502
|
+
itself or on `.hub-breadcrumb__list`. */
|
|
503
|
+
hub-breadcrumb {
|
|
458
504
|
--hub-breadcrumb-accent: var(--hub-sys-color-info);
|
|
459
505
|
}
|
|
460
506
|
```
|
|
@@ -464,8 +510,9 @@ The link colour follows the `--hub-breadcrumb-accent` token (which itself defaul
|
|
|
464
510
|
Keyboard focus is drawn with the design-system ring, so a breadcrumb focus looks like focus everywhere else in the application. Re-tint it without touching the outline:
|
|
465
511
|
|
|
466
512
|
```scss
|
|
467
|
-
/*
|
|
468
|
-
|
|
513
|
+
/* These defaults are declared on :host, so an override has to land on the crumb element
|
|
514
|
+
itself or inside it — a value set on an ancestor never reaches them. (The accent is the
|
|
515
|
+
exception: it is deliberately left undeclared, so it does inherit.) */
|
|
469
516
|
.hub-breadcrumb__list {
|
|
470
517
|
--hub-breadcrumb-focus-ring-color: rgba(25, 135, 84, 0.35);
|
|
471
518
|
--hub-breadcrumb-focus-ring-width: 0.25rem;
|
|
@@ -496,24 +543,37 @@ Keyboard focus is drawn with the design-system ring, so a breadcrumb focus looks
|
|
|
496
543
|
|
|
497
544
|
For a one-call theme that sets surface, spacing, divider, current-item colour, links and accent, use the `hub-breadcrumb-theme()` mixin. Every parameter is optional and defaults to `null`, so only the ones you pass are emitted as `--hub-breadcrumb-*` overrides. It is token-based with no Bootstrap dependency.
|
|
498
545
|
|
|
546
|
+
Include it on the `<hub-breadcrumb>` element with a selector that outranks the component's
|
|
547
|
+
own `:host` defaults — tag plus class does it. A bare `.docs-breadcrumb` ties on specificity
|
|
548
|
+
and loses on source order, and the same class on a wrapper never reaches the component at
|
|
549
|
+
all, because a declaration on the element always beats an inherited value.
|
|
550
|
+
|
|
551
|
+
```html
|
|
552
|
+
<hub-breadcrumb class="docs-breadcrumb"></hub-breadcrumb>
|
|
553
|
+
```
|
|
554
|
+
|
|
499
555
|
```scss
|
|
500
556
|
@use 'ng-hub-ui-breadcrumbs/styles/mixins/breadcrumb-theme' as *;
|
|
501
557
|
|
|
502
|
-
.docs-breadcrumb {
|
|
558
|
+
hub-breadcrumb.docs-breadcrumb {
|
|
503
559
|
@include hub-breadcrumb-theme(
|
|
504
560
|
$bg: #f8fafc,
|
|
505
561
|
$padding-x: 0.75rem,
|
|
506
|
-
$divider: "'/'",
|
|
562
|
+
$divider: "'/'",
|
|
563
|
+
// keep the inner quotes — it feeds CSS `content`
|
|
507
564
|
$accent: var(--hub-sys-color-info)
|
|
508
565
|
);
|
|
509
566
|
}
|
|
510
567
|
```
|
|
511
568
|
|
|
569
|
+
An include that passes `$accent` and nothing else is the one exception: the accent slot is
|
|
570
|
+
not declared on the host, so it may sit on an ancestor and still recolour the links.
|
|
571
|
+
|
|
512
572
|
## Changelog
|
|
513
573
|
|
|
514
574
|
All notable changes are documented in the [CHANGELOG.md](./CHANGELOG.md). For breaking changes, see [BREAKING_CHANGES.md](./BREAKING_CHANGES.md).
|
|
515
575
|
|
|
516
|
-
The latest release is **
|
|
576
|
+
The latest release is **v22.5.2**, a fix for a breadcrumb drawn before the first navigation completes. The collapsing inputs, crumbs pointing outside the router and the keyboard focus ring arrived in **v22.5.0**; the packaging path `ng-hub-ui-breadcrumbs/styles` in **v22.4.0**.
|
|
517
577
|
|
|
518
578
|
## Contributing
|
|
519
579
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, TemplateRef, Directive, InjectionToken, input, ElementRef, signal, afterNextRender, effect, Injectable, contentChild, output, computed, linkedSignal, Component, NgModule, makeEnvironmentProviders } from '@angular/core';
|
|
2
|
+
import { inject, TemplateRef, Directive, InjectionToken, input, ElementRef, signal, afterNextRender, effect, Injectable, Injector, contentChild, output, computed, linkedSignal, ChangeDetectionStrategy, Component, NgModule, makeEnvironmentProviders } from '@angular/core';
|
|
3
3
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
|
-
import { toSignal } from '@angular/core/rxjs-interop';
|
|
5
4
|
import { Router, ActivatedRoute, NavigationEnd, RouterLink } from '@angular/router';
|
|
5
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
6
6
|
import { filter, startWith, map } from 'rxjs';
|
|
7
7
|
|
|
8
8
|
class HubBreadcrumbItemDirective {
|
|
@@ -29,12 +29,16 @@ const HUB_BREADCRUMB_TOOLTIP_ADAPTER = new InjectionToken('HUB_BREADCRUMB_TOOLTI
|
|
|
29
29
|
/**
|
|
30
30
|
* Adds an overflow-aware tooltip to a breadcrumb label element.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* `
|
|
35
|
-
* a tooltip: the native `title` attribute by default, or the richer hub-ui
|
|
32
|
+
* When the label is truncated (its rendered text is wider than its box — typically
|
|
33
|
+
* because `hub-breadcrumb` truncation is enabled), the directive exposes the full
|
|
34
|
+
* text as a tooltip: the native `title` attribute by default, or the richer hub-ui
|
|
36
35
|
* tooltip when a {@link HUB_BREADCRUMB_TOOLTIP_ADAPTER} is provided. When the
|
|
37
36
|
* label fits, no tooltip is shown.
|
|
37
|
+
*
|
|
38
|
+
* `hub-breadcrumb` already applies it to the labels it renders and to the box it
|
|
39
|
+
* wraps a `hubBreadcrumbItem` template in, so applying `[hubBreadcrumbLabel]` by
|
|
40
|
+
* hand is for saying something other than the label — a full path, a spelled-out
|
|
41
|
+
* date — through the directive's own input.
|
|
38
42
|
*/
|
|
39
43
|
class HubBreadcrumbLabelDirective {
|
|
40
44
|
/**
|
|
@@ -135,7 +139,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
135
139
|
class HubBreadcrumbsService {
|
|
136
140
|
#router = inject(Router);
|
|
137
141
|
#activatedRoute = inject(ActivatedRoute);
|
|
142
|
+
/** The trail as a stream, for consumers already composing with rxjs. */
|
|
138
143
|
breadcrumbs$ = this.#router.events.pipe(filter((event) => event instanceof NavigationEnd), startWith(undefined), map(() => this.createBreadcrumbs(this.#activatedRoute.root)));
|
|
144
|
+
/**
|
|
145
|
+
* The trail as a signal, and the surface the component reads. Published here
|
|
146
|
+
* rather than left to each consumer, because a stream that only ever carries
|
|
147
|
+
* the current trail is one every caller was wrapping in the same `toSignal`
|
|
148
|
+
* — the component included. Wrapped once, subscribed once.
|
|
149
|
+
*/
|
|
150
|
+
breadcrumbs = toSignal(this.breadcrumbs$, { initialValue: [] });
|
|
139
151
|
createBreadcrumbs(route, url = '', breadcrumbs = []) {
|
|
140
152
|
const children = route.children;
|
|
141
153
|
if (children.length === 0) {
|
|
@@ -207,17 +219,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
207
219
|
}]
|
|
208
220
|
}] });
|
|
209
221
|
|
|
210
|
-
/**
|
|
211
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Variants with exact design-system token coverage via the SCSS `@each` loop.
|
|
224
|
+
* Kept in step with that loop by hand, because Sass cannot read this file: a name
|
|
225
|
+
* dropped from here is not broken, only paid for twice — once inline and once by
|
|
226
|
+
* the stylesheet.
|
|
227
|
+
*/
|
|
228
|
+
const BUILT_IN_VARIANTS = new Set([
|
|
229
|
+
'primary',
|
|
230
|
+
'secondary',
|
|
231
|
+
'success',
|
|
232
|
+
'danger',
|
|
233
|
+
'warning',
|
|
234
|
+
'info',
|
|
235
|
+
'neutral',
|
|
236
|
+
'light',
|
|
237
|
+
'dark'
|
|
238
|
+
]);
|
|
212
239
|
class HubBreadcrumbComponent {
|
|
213
240
|
#breadcrumbsSvc = inject(HubBreadcrumbsService);
|
|
241
|
+
#host = inject(ElementRef);
|
|
242
|
+
#injector = inject(Injector);
|
|
214
243
|
itemTemplate = contentChild(HubBreadcrumbItemDirective, { ...(ngDevMode ? { debugName: "itemTemplate" } : /* istanbul ignore next */ {}), read: TemplateRef });
|
|
215
|
-
breadcrumbs$ = this.#breadcrumbsSvc.breadcrumbs$;
|
|
216
244
|
/**
|
|
217
|
-
* Semantic accent for the breadcrumb links: `'primary'` · `'
|
|
218
|
-
* `'danger'` · `'warning'` · `'info'
|
|
219
|
-
* `--hub-sys-color-<variant>`).
|
|
220
|
-
* current (last) item stays muted.
|
|
245
|
+
* Semantic accent for the breadcrumb links: `'primary'` · `'secondary'` ·
|
|
246
|
+
* `'success'` · `'danger'` · `'warning'` · `'info'` · `'neutral'` · `'light'` ·
|
|
247
|
+
* `'dark'`, or any custom string (read as `--hub-sys-color-<variant>`).
|
|
248
|
+
* Re-bases `--hub-breadcrumb-accent`; the current (last) item stays muted.
|
|
249
|
+
* Defaults to the standard link colour.
|
|
221
250
|
*/
|
|
222
251
|
variant = input(/* @ts-ignore */
|
|
223
252
|
...(ngDevMode ? [undefined, { debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
@@ -227,6 +256,10 @@ class HubBreadcrumbComponent {
|
|
|
227
256
|
* exposes its full text as a tooltip (native `title`, or the hub-ui tooltip
|
|
228
257
|
* when {@link provideHubBreadcrumbTooltip} is wired). Off by default, so the
|
|
229
258
|
* standard breadcrumb layout is unchanged.
|
|
259
|
+
*
|
|
260
|
+
* It reaches a `hubBreadcrumbItem` template as well: the projected elements
|
|
261
|
+
* belong to the consuming component, so the template wraps them in a
|
|
262
|
+
* `span.hub-breadcrumb__custom` of its own and clips that instead.
|
|
230
263
|
*/
|
|
231
264
|
truncateItems = input(false, /* @ts-ignore */
|
|
232
265
|
...(ngDevMode ? [{ debugName: "truncateItems" }] : /* istanbul ignore next */ []));
|
|
@@ -263,10 +296,8 @@ class HubBreadcrumbComponent {
|
|
|
263
296
|
* open a menu of the hidden crumbs, log the interaction.
|
|
264
297
|
*/
|
|
265
298
|
collapsedClick = output();
|
|
266
|
-
/** Trail as published by the service, tracked as a signal. */
|
|
267
|
-
#routerTrail = toSignal(this.breadcrumbs$, { initialValue: [] });
|
|
268
299
|
/** Effective trail: the manual one when supplied, the router's otherwise. */
|
|
269
|
-
trail = computed(() => this.items() ?? this.#
|
|
300
|
+
trail = computed(() => this.items() ?? this.#breadcrumbsSvc.breadcrumbs(), /* @ts-ignore */
|
|
270
301
|
...(ngDevMode ? [{ debugName: "trail" }] : /* istanbul ignore next */ []));
|
|
271
302
|
/**
|
|
272
303
|
* Whether the reader has opened a collapsed trail. Derived from the trail so a
|
|
@@ -299,8 +330,8 @@ class HubBreadcrumbComponent {
|
|
|
299
330
|
}, /* @ts-ignore */
|
|
300
331
|
...(ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []));
|
|
301
332
|
/**
|
|
302
|
-
* Inline accent for custom (non-built-in) variants — the built-in
|
|
303
|
-
* resolved by the SCSS `@each` loop, so this returns `null` for them.
|
|
333
|
+
* Inline accent for custom (non-built-in) variants — the nine built-in accents
|
|
334
|
+
* are resolved by the SCSS `@each` loop, so this returns `null` for them.
|
|
304
335
|
*/
|
|
305
336
|
customAccent = computed(() => {
|
|
306
337
|
const v = this.variant();
|
|
@@ -311,6 +342,29 @@ class HubBreadcrumbComponent {
|
|
|
311
342
|
expand() {
|
|
312
343
|
this.expanded.set(true);
|
|
313
344
|
this.collapsedClick.emit();
|
|
345
|
+
afterNextRender(() => this.#focusFirstRevealedCrumb(), { injector: this.#injector });
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Expanding removes the indicator — the element that was holding focus — from the
|
|
349
|
+
* DOM, and a browser answers that by focusing `<body>`: whoever opened the trail
|
|
350
|
+
* from the keyboard would have to tab from the top of the page to reach the crumbs
|
|
351
|
+
* they just asked for. Focus lands on the first revealed crumb instead, which is
|
|
352
|
+
* where reading continues.
|
|
353
|
+
*/
|
|
354
|
+
#focusFirstRevealedCrumb() {
|
|
355
|
+
const crumbs = this.#host.nativeElement.querySelectorAll('.hub-breadcrumb__item');
|
|
356
|
+
const revealed = crumbs[Math.max(0, this.itemsBeforeCollapse())];
|
|
357
|
+
if (!revealed) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
// A crumb may render as plain text — the current page, or a custom template with
|
|
361
|
+
// no control of its own — and text takes no focus. Make that one crumb
|
|
362
|
+
// programmatically focusable rather than let focus fall back to the body.
|
|
363
|
+
const target = revealed.querySelector('a, button, [tabindex]') ?? revealed;
|
|
364
|
+
if (target === revealed) {
|
|
365
|
+
revealed.tabIndex = -1;
|
|
366
|
+
}
|
|
367
|
+
target.focus();
|
|
314
368
|
}
|
|
315
369
|
/**
|
|
316
370
|
* A crumb opening in a new tab hands the opener to the destination unless it
|
|
@@ -321,18 +375,25 @@ class HubBreadcrumbComponent {
|
|
|
321
375
|
return item.rel ?? (item.target === '_blank' ? 'noopener noreferrer' : null);
|
|
322
376
|
}
|
|
323
377
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
324
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: HubBreadcrumbComponent, isStandalone: true, selector: "hub-breadcrumb", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, truncateItems: { classPropertyName: "truncateItems", publicName: "truncateItems", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, itemsBeforeCollapse: { classPropertyName: "itemsBeforeCollapse", publicName: "itemsBeforeCollapse", isSignal: true, isRequired: false, transformFunction: null }, itemsAfterCollapse: { classPropertyName: "itemsAfterCollapse", publicName: "itemsAfterCollapse", isSignal: true, isRequired: false, transformFunction: null }, collapsedAriaLabel: { classPropertyName: "collapsedAriaLabel", publicName: "collapsedAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsedClick: "collapsedClick" }, host: { properties: { "class.hub-breadcrumb--truncate": "truncateItems()", "attr.data-variant": "variant() ?? null", "style.--hub-breadcrumb-accent": "customAccent()" }, classAttribute: "hub-breadcrumb" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: HubBreadcrumbItemDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (row of rows(); track $index) {\n\t\t\t@if (row.item; as item) {\n\t\t\t\t<li class=\"hub-breadcrumb__item\" [class.hub-breadcrumb__item--active]=\"row.isLast\">\n\t\t\t\t\t@if (itemTemplate(); as template) {\n\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t[ngTemplateOutlet]=\"template\"\n\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t$implicit: item,\n\t\t\t\t\t\t\t\tisLast: row.isLast\n\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t} @else if (row.isLast) {\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__text\" hubBreadcrumbLabel aria-current=\"page\">{{ item.label }}</span>\n\t\t\t\t\t} @else if (item.href) {\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclass=\"hub-breadcrumb__link\"\n\t\t\t\t\t\t\thubBreadcrumbLabel\n\t\t\t\t\t\t\t[href]=\"item.href\"\n\t\t\t\t\t\t\t[attr.target]=\"item.target ?? null\"\n\t\t\t\t\t\t\t[attr.rel]=\"row.rel\"\n\t\t\t\t\t\t\t[attr.download]=\"item.download ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<a [routerLink]=\"item.url\" class=\"hub-breadcrumb__link\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t}\n\t\t\t\t</li>\n\t\t\t} @else {\n\t\t\t\t<li class=\"hub-breadcrumb__item hub-breadcrumb__item--collapsed\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"hub-breadcrumb__collapsed\"\n\t\t\t\t\t\t[attr.aria-label]=\"collapsedAriaLabel()\"\n\t\t\t\t\t\t[attr.aria-expanded]=\"expanded()\"\n\t\t\t\t\t\t(click)=\"expand()\"\n\t\t\t\t\t>\n\t\t\t\t\t\t…\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t}\n\t\t}\n\t</ol>\n</nav>\n", styles: [":root,:host{--hub-breadcrumb-padding-x: var(--hub-ref-space-3, 1rem);--hub-breadcrumb-padding-y: .25rem;--hub-breadcrumb-margin-bottom: var(--hub-ref-space-0, 0);--hub-breadcrumb-bg: var(--hub-sys-surface-page, transparent);--hub-breadcrumb-color: var(--hub-sys-text-primary, #212529);--hub-breadcrumb-border-radius: var(--hub-ref-radius-md, .375rem);--hub-breadcrumb-divider-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-item-padding-x: var(--hub-ref-space-1, .25rem);--hub-breadcrumb-item-active-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-accent: var(--hub-sys-color-primary, #0d6efd);--hub-breadcrumb-accent-emphasis: color-mix(in oklch, var(--hub-breadcrumb-accent) 80%, var(--hub-sys-color-ink, #212529));--hub-breadcrumb-accent-subtle: color-mix(in oklch, var(--hub-breadcrumb-accent) 12%, var(--hub-sys-surface-page, #fff));--hub-breadcrumb-accent-on: oklch(from var(--hub-breadcrumb-accent) clamp(0, (.62 - l) * 1000, 1) 0 h);--hub-breadcrumb-link-color: var(--hub-breadcrumb-accent);--hub-breadcrumb-link-hover-color: var(--hub-breadcrumb-accent-emphasis, var(--hub-sys-link-hover-color, #0a58ca));--hub-breadcrumb-link-decoration: none;--hub-breadcrumb-link-hover-decoration: underline;--hub-breadcrumb-link-focus-color: var(--hub-breadcrumb-accent-emphasis);--hub-breadcrumb-focus-bg: transparent;--hub-breadcrumb-focus-ring-width: var(--hub-sys-focus-ring-width, .25rem);--hub-breadcrumb-focus-ring-color: var(--hub-sys-focus-ring-color, rgba(13, 110, 253, .25));--hub-breadcrumb-focus-ring-radius: var(--hub-ref-radius-sm, .25rem);--hub-breadcrumb-collapsed-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-collapsed-hover-color: var(--hub-breadcrumb-accent);--hub-breadcrumb-collapsed-bg: transparent;--hub-breadcrumb-collapsed-hover-bg: var(--hub-breadcrumb-accent-subtle);--hub-breadcrumb-divider: \">\";--hub-breadcrumb-divider-flipped: \"<\";--hub-breadcrumb-font-size: inherit;--hub-breadcrumb-max-item-width: 12rem}.hub-breadcrumb__nav .hub-breadcrumb__list{display:flex;flex-wrap:wrap;font-size:var(--hub-breadcrumb-font-size, inherit);padding:var(--hub-breadcrumb-padding-y, .25rem) var(--hub-breadcrumb-padding-x, var(--hub-ref-space-3, 1rem));margin-bottom:var(--hub-breadcrumb-margin-bottom, var(--hub-ref-space-0, 0));list-style:none;color:var(--hub-breadcrumb-color, var(--hub-sys-text-primary, #212529));background-color:var(--hub-breadcrumb-bg, var(--hub-sys-surface-page, transparent));border-radius:var(--hub-breadcrumb-border-radius, var(--hub-ref-radius-md, .375rem))}.hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item{padding-inline-start:var(--hub-breadcrumb-item-padding-x, var(--hub-ref-space-1, .25rem))}.hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item:before{padding-inline-end:var(--hub-breadcrumb-item-padding-x, var(--hub-ref-space-1, .25rem));color:var(--hub-breadcrumb-divider-color, var(--hub-sys-text-muted, #6c757d));content:var(--hub-breadcrumb-divider, \">\")}.hub-breadcrumb__nav .hub-breadcrumb__item--active{color:var(--hub-breadcrumb-item-active-color, var(--hub-sys-text-muted, #6c757d))}.hub-breadcrumb__nav .hub-breadcrumb__link{color:var(--hub-breadcrumb-link-color, var(--hub-sys-link-color, #0d6efd));text-decoration:var(--hub-breadcrumb-link-decoration, none)}.hub-breadcrumb__nav .hub-breadcrumb__link:hover{color:var(--hub-breadcrumb-link-hover-color, var(--hub-sys-link-hover-color, #0a58ca));text-decoration:var(--hub-breadcrumb-link-hover-decoration, underline)}.hub-breadcrumb__nav .hub-breadcrumb__collapsed{display:inline-flex;align-items:center;padding:0 .125rem;border:0;border-radius:var(--hub-breadcrumb-focus-ring-radius, var(--hub-ref-radius-sm, .25rem));background-color:var(--hub-breadcrumb-collapsed-bg, transparent);color:var(--hub-breadcrumb-collapsed-color, var(--hub-sys-text-muted, #6c757d));font:inherit;line-height:inherit;cursor:pointer}.hub-breadcrumb__nav .hub-breadcrumb__collapsed:hover{background-color:var(--hub-breadcrumb-collapsed-hover-bg);color:var(--hub-breadcrumb-collapsed-hover-color)}.hub-breadcrumb__nav .hub-breadcrumb__link:focus-visible,.hub-breadcrumb__nav .hub-breadcrumb__collapsed:focus-visible{outline:0;border-radius:var(--hub-breadcrumb-focus-ring-radius, var(--hub-ref-radius-sm, .25rem));background-color:var(--hub-breadcrumb-focus-bg, transparent);color:var(--hub-breadcrumb-link-focus-color);box-shadow:0 0 0 var(--hub-breadcrumb-focus-ring-width, var(--hub-sys-focus-ring-width, .25rem)) var(--hub-breadcrumb-focus-ring-color, var(--hub-sys-focus-ring-color, rgba(13, 110, 253, .25)))}[dir=rtl] .hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item:before{content:var(--hub-breadcrumb-divider-flipped, var(--hub-breadcrumb-divider, \">\"))}:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__link,:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__text,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__link,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__text{display:inline-block;max-inline-size:var(--hub-breadcrumb-max-item-width, 12rem);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}:host([data-variant=primary]),.hub-breadcrumb[data-variant=primary]{--hub-breadcrumb-accent: var(--hub-sys-color-primary)}:host([data-variant=secondary]),.hub-breadcrumb[data-variant=secondary]{--hub-breadcrumb-accent: var(--hub-sys-color-secondary)}:host([data-variant=success]),.hub-breadcrumb[data-variant=success]{--hub-breadcrumb-accent: var(--hub-sys-color-success)}:host([data-variant=danger]),.hub-breadcrumb[data-variant=danger]{--hub-breadcrumb-accent: var(--hub-sys-color-danger)}:host([data-variant=warning]),.hub-breadcrumb[data-variant=warning]{--hub-breadcrumb-accent: var(--hub-sys-color-warning)}:host([data-variant=info]),.hub-breadcrumb[data-variant=info]{--hub-breadcrumb-accent: var(--hub-sys-color-info)}:host([data-variant=neutral]),.hub-breadcrumb[data-variant=neutral]{--hub-breadcrumb-accent: var(--hub-sys-color-neutral)}:host([data-variant=light]),.hub-breadcrumb[data-variant=light]{--hub-breadcrumb-accent: var(--hub-sys-color-light)}:host([data-variant=dark]),.hub-breadcrumb[data-variant=dark]{--hub-breadcrumb-accent: var(--hub-sys-color-dark)}:host([data-variant]),.hub-breadcrumb[data-variant]{--hub-breadcrumb-accent-emphasis: color-mix(in oklch, var(--hub-breadcrumb-accent) 80%, var(--hub-sys-color-ink, #212529));--hub-breadcrumb-accent-subtle: color-mix(in oklch, var(--hub-breadcrumb-accent) 12%, var(--hub-sys-surface-page, #fff));--hub-breadcrumb-accent-on: oklch(from var(--hub-breadcrumb-accent) clamp(0, (.62 - l) * 1000, 1) 0 h);--hub-breadcrumb-link-hover-color: var(--hub-breadcrumb-accent-emphasis)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HubBreadcrumbLabelDirective, selector: "[hubBreadcrumbLabel]", inputs: ["hubBreadcrumbLabel"] }] });
|
|
378
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: HubBreadcrumbComponent, isStandalone: true, selector: "hub-breadcrumb", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, truncateItems: { classPropertyName: "truncateItems", publicName: "truncateItems", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, itemsBeforeCollapse: { classPropertyName: "itemsBeforeCollapse", publicName: "itemsBeforeCollapse", isSignal: true, isRequired: false, transformFunction: null }, itemsAfterCollapse: { classPropertyName: "itemsAfterCollapse", publicName: "itemsAfterCollapse", isSignal: true, isRequired: false, transformFunction: null }, collapsedAriaLabel: { classPropertyName: "collapsedAriaLabel", publicName: "collapsedAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsedClick: "collapsedClick" }, host: { properties: { "class.hub-breadcrumb--truncate": "truncateItems()", "attr.data-variant": "variant() ?? null", "style.--hub-breadcrumb-accent": "customAccent()" }, classAttribute: "hub-breadcrumb" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: HubBreadcrumbItemDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (row of rows(); track $index) {\n\t\t\t@if (row.item; as item) {\n\t\t\t\t<li\n\t\t\t\t\tclass=\"hub-breadcrumb__item\"\n\t\t\t\t\t[class.hub-breadcrumb__item--active]=\"row.isLast\"\n\t\t\t\t\t[attr.aria-current]=\"row.isLast ? 'page' : null\"\n\t\t\t\t>\n\t\t\t\t\t@if (itemTemplate(); as template) {\n\t\t\t\t\t\t<!--\n\t\t\t\t\t\t\tThe clipping box for a custom crumb. Scoped styles never reach the elements\n\t\t\t\t\t\t\ta `hubBreadcrumbItem` template renders \u2014 they belong to the consuming\n\t\t\t\t\t\t\tcomponent \u2014 so `truncateItems` can only clip something this component draws\n\t\t\t\t\t\t\titself. It sits exactly where a built-in label sits, inside the item and\n\t\t\t\t\t\t\toutside the separator, so a projected crumb gets the same width as any other.\n\t\t\t\t\t\t-->\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__custom\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"template\"\n\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t$implicit: item,\n\t\t\t\t\t\t\t\t\tisLast: row.isLast\n\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t} @else if (row.isLast) {\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__text\" hubBreadcrumbLabel>{{ item.label }}</span>\n\t\t\t\t\t} @else if (item.href) {\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclass=\"hub-breadcrumb__link\"\n\t\t\t\t\t\t\thubBreadcrumbLabel\n\t\t\t\t\t\t\t[href]=\"item.href\"\n\t\t\t\t\t\t\t[attr.target]=\"item.target ?? null\"\n\t\t\t\t\t\t\t[attr.rel]=\"row.rel\"\n\t\t\t\t\t\t\t[attr.download]=\"item.download ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<a [routerLink]=\"item.url\" class=\"hub-breadcrumb__link\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t}\n\t\t\t\t</li>\n\t\t\t} @else {\n\t\t\t\t<li class=\"hub-breadcrumb__item hub-breadcrumb__item--collapsed\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"hub-breadcrumb__collapsed\"\n\t\t\t\t\t\t[attr.aria-label]=\"collapsedAriaLabel()\"\n\t\t\t\t\t\t[attr.aria-expanded]=\"expanded()\"\n\t\t\t\t\t\t(click)=\"expand()\"\n\t\t\t\t\t>\n\t\t\t\t\t\t…\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t}\n\t\t}\n\t</ol>\n</nav>\n", styles: [":root,:host{--hub-breadcrumb-padding-x: var(--hub-ref-space-3, 1rem);--hub-breadcrumb-padding-y: .25rem;--hub-breadcrumb-margin-bottom: var(--hub-ref-space-0, 0);--hub-breadcrumb-bg: var(--hub-sys-surface-page, transparent);--hub-breadcrumb-color: var(--hub-sys-text-primary, #212529);--hub-breadcrumb-border-radius: var(--hub-ref-radius-md, .375rem);--hub-breadcrumb-divider-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-item-padding-x: var(--hub-ref-space-1, .25rem);--hub-breadcrumb-item-active-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-accent-emphasis: color-mix(in oklch, var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd)) 80%, var(--hub-sys-color-ink, #212529));--hub-breadcrumb-accent-subtle: color-mix(in oklch, var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd)) 12%, var(--hub-sys-surface-page, #fff));--hub-breadcrumb-accent-on: oklch(from var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd)) clamp(0, (.62 - l) * 1000, 1) 0 h);--hub-breadcrumb-link-color: var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd));--hub-breadcrumb-link-hover-color: var(--hub-breadcrumb-accent-emphasis, var(--hub-sys-link-hover-color, #0a58ca));--hub-breadcrumb-link-decoration: none;--hub-breadcrumb-link-hover-decoration: underline;--hub-breadcrumb-link-focus-color: var(--hub-breadcrumb-accent-emphasis);--hub-breadcrumb-focus-bg: transparent;--hub-breadcrumb-focus-ring-width: var(--hub-sys-focus-ring-width, .25rem);--hub-breadcrumb-focus-ring-color: var(--hub-sys-focus-ring-color, rgba(13, 110, 253, .25));--hub-breadcrumb-focus-ring-radius: var(--hub-ref-radius-sm, .25rem);--hub-breadcrumb-collapsed-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-collapsed-hover-color: var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd));--hub-breadcrumb-collapsed-bg: transparent;--hub-breadcrumb-collapsed-hover-bg: var(--hub-breadcrumb-accent-subtle);--hub-breadcrumb-divider: \">\";--hub-breadcrumb-divider-flipped: \"<\";--hub-breadcrumb-font-size: inherit;--hub-breadcrumb-max-item-width: 12rem}.hub-breadcrumb__nav .hub-breadcrumb__list{display:flex;flex-wrap:wrap;font-size:var(--hub-breadcrumb-font-size, inherit);padding:var(--hub-breadcrumb-padding-y, .25rem) var(--hub-breadcrumb-padding-x, var(--hub-ref-space-3, 1rem));margin-bottom:var(--hub-breadcrumb-margin-bottom, var(--hub-ref-space-0, 0));list-style:none;color:var(--hub-breadcrumb-color, var(--hub-sys-text-primary, #212529));background-color:var(--hub-breadcrumb-bg, var(--hub-sys-surface-page, transparent));border-radius:var(--hub-breadcrumb-border-radius, var(--hub-ref-radius-md, .375rem))}.hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item{padding-inline-start:var(--hub-breadcrumb-item-padding-x, var(--hub-ref-space-1, .25rem))}.hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item:before{padding-inline-end:var(--hub-breadcrumb-item-padding-x, var(--hub-ref-space-1, .25rem));color:var(--hub-breadcrumb-divider-color, var(--hub-sys-text-muted, #6c757d));content:var(--hub-breadcrumb-divider, \">\")}.hub-breadcrumb__nav .hub-breadcrumb__item--active{color:var(--hub-breadcrumb-item-active-color, var(--hub-sys-text-muted, #6c757d))}.hub-breadcrumb__nav .hub-breadcrumb__link{color:var(--hub-breadcrumb-link-color, var(--hub-sys-link-color, #0d6efd));text-decoration:var(--hub-breadcrumb-link-decoration, none)}.hub-breadcrumb__nav .hub-breadcrumb__link:hover{color:var(--hub-breadcrumb-link-hover-color, var(--hub-sys-link-hover-color, #0a58ca));text-decoration:var(--hub-breadcrumb-link-hover-decoration, underline)}.hub-breadcrumb__nav .hub-breadcrumb__collapsed{display:inline-flex;align-items:center;padding:0 .125rem;border:0;border-radius:var(--hub-breadcrumb-focus-ring-radius, var(--hub-ref-radius-sm, .25rem));background-color:var(--hub-breadcrumb-collapsed-bg, transparent);color:var(--hub-breadcrumb-collapsed-color, var(--hub-sys-text-muted, #6c757d));font:inherit;line-height:inherit;cursor:pointer}.hub-breadcrumb__nav .hub-breadcrumb__collapsed:hover{background-color:var(--hub-breadcrumb-collapsed-hover-bg);color:var(--hub-breadcrumb-collapsed-hover-color)}.hub-breadcrumb__nav .hub-breadcrumb__link:focus-visible,.hub-breadcrumb__nav .hub-breadcrumb__collapsed:focus-visible{outline:0;border-radius:var(--hub-breadcrumb-focus-ring-radius, var(--hub-ref-radius-sm, .25rem));background-color:var(--hub-breadcrumb-focus-bg, transparent);color:var(--hub-breadcrumb-link-focus-color);box-shadow:0 0 0 var(--hub-breadcrumb-focus-ring-width, var(--hub-sys-focus-ring-width, .25rem)) var(--hub-breadcrumb-focus-ring-color, var(--hub-sys-focus-ring-color, rgba(13, 110, 253, .25)))}[dir=rtl] .hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item:before{content:var(--hub-breadcrumb-divider-flipped, var(--hub-breadcrumb-divider, \">\"))}:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__link,:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__text,:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__custom,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__link,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__text,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__custom{display:inline-block;max-inline-size:var(--hub-breadcrumb-max-item-width, 12rem);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}:host([data-variant=primary]),.hub-breadcrumb[data-variant=primary]{--hub-breadcrumb-accent: var(--hub-sys-color-primary)}:host([data-variant=secondary]),.hub-breadcrumb[data-variant=secondary]{--hub-breadcrumb-accent: var(--hub-sys-color-secondary)}:host([data-variant=success]),.hub-breadcrumb[data-variant=success]{--hub-breadcrumb-accent: var(--hub-sys-color-success)}:host([data-variant=danger]),.hub-breadcrumb[data-variant=danger]{--hub-breadcrumb-accent: var(--hub-sys-color-danger)}:host([data-variant=warning]),.hub-breadcrumb[data-variant=warning]{--hub-breadcrumb-accent: var(--hub-sys-color-warning)}:host([data-variant=info]),.hub-breadcrumb[data-variant=info]{--hub-breadcrumb-accent: var(--hub-sys-color-info)}:host([data-variant=neutral]),.hub-breadcrumb[data-variant=neutral]{--hub-breadcrumb-accent: var(--hub-sys-color-neutral)}:host([data-variant=light]),.hub-breadcrumb[data-variant=light]{--hub-breadcrumb-accent: var(--hub-sys-color-light)}:host([data-variant=dark]),.hub-breadcrumb[data-variant=dark]{--hub-breadcrumb-accent: var(--hub-sys-color-dark)}:host([data-variant]),.hub-breadcrumb[data-variant]{--hub-breadcrumb-accent-emphasis: color-mix(in oklch, var(--hub-breadcrumb-accent) 80%, var(--hub-sys-color-ink, #212529));--hub-breadcrumb-accent-subtle: color-mix(in oklch, var(--hub-breadcrumb-accent) 12%, var(--hub-sys-surface-page, #fff));--hub-breadcrumb-accent-on: oklch(from var(--hub-breadcrumb-accent) clamp(0, (.62 - l) * 1000, 1) 0 h);--hub-breadcrumb-link-hover-color: var(--hub-breadcrumb-accent-emphasis)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HubBreadcrumbLabelDirective, selector: "[hubBreadcrumbLabel]", inputs: ["hubBreadcrumbLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
325
379
|
}
|
|
326
380
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubBreadcrumbComponent, decorators: [{
|
|
327
381
|
type: Component,
|
|
328
|
-
args: [{ selector: 'hub-breadcrumb', imports: [RouterLink, NgTemplateOutlet, HubBreadcrumbLabelDirective], host: {
|
|
382
|
+
args: [{ selector: 'hub-breadcrumb', imports: [RouterLink, NgTemplateOutlet, HubBreadcrumbLabelDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
329
383
|
class: 'hub-breadcrumb',
|
|
330
384
|
'[class.hub-breadcrumb--truncate]': 'truncateItems()',
|
|
331
385
|
'[attr.data-variant]': 'variant() ?? null',
|
|
332
386
|
'[style.--hub-breadcrumb-accent]': 'customAccent()'
|
|
333
|
-
}, template: "<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (row of rows(); track $index) {\n\t\t\t@if (row.item; as item) {\n\t\t\t\t<li
|
|
387
|
+
}, template: "<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (row of rows(); track $index) {\n\t\t\t@if (row.item; as item) {\n\t\t\t\t<li\n\t\t\t\t\tclass=\"hub-breadcrumb__item\"\n\t\t\t\t\t[class.hub-breadcrumb__item--active]=\"row.isLast\"\n\t\t\t\t\t[attr.aria-current]=\"row.isLast ? 'page' : null\"\n\t\t\t\t>\n\t\t\t\t\t@if (itemTemplate(); as template) {\n\t\t\t\t\t\t<!--\n\t\t\t\t\t\t\tThe clipping box for a custom crumb. Scoped styles never reach the elements\n\t\t\t\t\t\t\ta `hubBreadcrumbItem` template renders \u2014 they belong to the consuming\n\t\t\t\t\t\t\tcomponent \u2014 so `truncateItems` can only clip something this component draws\n\t\t\t\t\t\t\titself. It sits exactly where a built-in label sits, inside the item and\n\t\t\t\t\t\t\toutside the separator, so a projected crumb gets the same width as any other.\n\t\t\t\t\t\t-->\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__custom\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"template\"\n\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t$implicit: item,\n\t\t\t\t\t\t\t\t\tisLast: row.isLast\n\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t} @else if (row.isLast) {\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__text\" hubBreadcrumbLabel>{{ item.label }}</span>\n\t\t\t\t\t} @else if (item.href) {\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclass=\"hub-breadcrumb__link\"\n\t\t\t\t\t\t\thubBreadcrumbLabel\n\t\t\t\t\t\t\t[href]=\"item.href\"\n\t\t\t\t\t\t\t[attr.target]=\"item.target ?? null\"\n\t\t\t\t\t\t\t[attr.rel]=\"row.rel\"\n\t\t\t\t\t\t\t[attr.download]=\"item.download ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<a [routerLink]=\"item.url\" class=\"hub-breadcrumb__link\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t}\n\t\t\t\t</li>\n\t\t\t} @else {\n\t\t\t\t<li class=\"hub-breadcrumb__item hub-breadcrumb__item--collapsed\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"hub-breadcrumb__collapsed\"\n\t\t\t\t\t\t[attr.aria-label]=\"collapsedAriaLabel()\"\n\t\t\t\t\t\t[attr.aria-expanded]=\"expanded()\"\n\t\t\t\t\t\t(click)=\"expand()\"\n\t\t\t\t\t>\n\t\t\t\t\t\t…\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t}\n\t\t}\n\t</ol>\n</nav>\n", styles: [":root,:host{--hub-breadcrumb-padding-x: var(--hub-ref-space-3, 1rem);--hub-breadcrumb-padding-y: .25rem;--hub-breadcrumb-margin-bottom: var(--hub-ref-space-0, 0);--hub-breadcrumb-bg: var(--hub-sys-surface-page, transparent);--hub-breadcrumb-color: var(--hub-sys-text-primary, #212529);--hub-breadcrumb-border-radius: var(--hub-ref-radius-md, .375rem);--hub-breadcrumb-divider-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-item-padding-x: var(--hub-ref-space-1, .25rem);--hub-breadcrumb-item-active-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-accent-emphasis: color-mix(in oklch, var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd)) 80%, var(--hub-sys-color-ink, #212529));--hub-breadcrumb-accent-subtle: color-mix(in oklch, var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd)) 12%, var(--hub-sys-surface-page, #fff));--hub-breadcrumb-accent-on: oklch(from var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd)) clamp(0, (.62 - l) * 1000, 1) 0 h);--hub-breadcrumb-link-color: var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd));--hub-breadcrumb-link-hover-color: var(--hub-breadcrumb-accent-emphasis, var(--hub-sys-link-hover-color, #0a58ca));--hub-breadcrumb-link-decoration: none;--hub-breadcrumb-link-hover-decoration: underline;--hub-breadcrumb-link-focus-color: var(--hub-breadcrumb-accent-emphasis);--hub-breadcrumb-focus-bg: transparent;--hub-breadcrumb-focus-ring-width: var(--hub-sys-focus-ring-width, .25rem);--hub-breadcrumb-focus-ring-color: var(--hub-sys-focus-ring-color, rgba(13, 110, 253, .25));--hub-breadcrumb-focus-ring-radius: var(--hub-ref-radius-sm, .25rem);--hub-breadcrumb-collapsed-color: var(--hub-sys-text-muted, #6c757d);--hub-breadcrumb-collapsed-hover-color: var(--hub-breadcrumb-accent, var(--hub-sys-color-primary, #0d6efd));--hub-breadcrumb-collapsed-bg: transparent;--hub-breadcrumb-collapsed-hover-bg: var(--hub-breadcrumb-accent-subtle);--hub-breadcrumb-divider: \">\";--hub-breadcrumb-divider-flipped: \"<\";--hub-breadcrumb-font-size: inherit;--hub-breadcrumb-max-item-width: 12rem}.hub-breadcrumb__nav .hub-breadcrumb__list{display:flex;flex-wrap:wrap;font-size:var(--hub-breadcrumb-font-size, inherit);padding:var(--hub-breadcrumb-padding-y, .25rem) var(--hub-breadcrumb-padding-x, var(--hub-ref-space-3, 1rem));margin-bottom:var(--hub-breadcrumb-margin-bottom, var(--hub-ref-space-0, 0));list-style:none;color:var(--hub-breadcrumb-color, var(--hub-sys-text-primary, #212529));background-color:var(--hub-breadcrumb-bg, var(--hub-sys-surface-page, transparent));border-radius:var(--hub-breadcrumb-border-radius, var(--hub-ref-radius-md, .375rem))}.hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item{padding-inline-start:var(--hub-breadcrumb-item-padding-x, var(--hub-ref-space-1, .25rem))}.hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item:before{padding-inline-end:var(--hub-breadcrumb-item-padding-x, var(--hub-ref-space-1, .25rem));color:var(--hub-breadcrumb-divider-color, var(--hub-sys-text-muted, #6c757d));content:var(--hub-breadcrumb-divider, \">\")}.hub-breadcrumb__nav .hub-breadcrumb__item--active{color:var(--hub-breadcrumb-item-active-color, var(--hub-sys-text-muted, #6c757d))}.hub-breadcrumb__nav .hub-breadcrumb__link{color:var(--hub-breadcrumb-link-color, var(--hub-sys-link-color, #0d6efd));text-decoration:var(--hub-breadcrumb-link-decoration, none)}.hub-breadcrumb__nav .hub-breadcrumb__link:hover{color:var(--hub-breadcrumb-link-hover-color, var(--hub-sys-link-hover-color, #0a58ca));text-decoration:var(--hub-breadcrumb-link-hover-decoration, underline)}.hub-breadcrumb__nav .hub-breadcrumb__collapsed{display:inline-flex;align-items:center;padding:0 .125rem;border:0;border-radius:var(--hub-breadcrumb-focus-ring-radius, var(--hub-ref-radius-sm, .25rem));background-color:var(--hub-breadcrumb-collapsed-bg, transparent);color:var(--hub-breadcrumb-collapsed-color, var(--hub-sys-text-muted, #6c757d));font:inherit;line-height:inherit;cursor:pointer}.hub-breadcrumb__nav .hub-breadcrumb__collapsed:hover{background-color:var(--hub-breadcrumb-collapsed-hover-bg);color:var(--hub-breadcrumb-collapsed-hover-color)}.hub-breadcrumb__nav .hub-breadcrumb__link:focus-visible,.hub-breadcrumb__nav .hub-breadcrumb__collapsed:focus-visible{outline:0;border-radius:var(--hub-breadcrumb-focus-ring-radius, var(--hub-ref-radius-sm, .25rem));background-color:var(--hub-breadcrumb-focus-bg, transparent);color:var(--hub-breadcrumb-link-focus-color);box-shadow:0 0 0 var(--hub-breadcrumb-focus-ring-width, var(--hub-sys-focus-ring-width, .25rem)) var(--hub-breadcrumb-focus-ring-color, var(--hub-sys-focus-ring-color, rgba(13, 110, 253, .25)))}[dir=rtl] .hub-breadcrumb__nav .hub-breadcrumb__item+.hub-breadcrumb__item:before{content:var(--hub-breadcrumb-divider-flipped, var(--hub-breadcrumb-divider, \">\"))}:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__link,:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__text,:host(.hub-breadcrumb--truncate) .hub-breadcrumb__nav .hub-breadcrumb__custom,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__link,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__text,.hub-breadcrumb--truncate .hub-breadcrumb__nav .hub-breadcrumb__custom{display:inline-block;max-inline-size:var(--hub-breadcrumb-max-item-width, 12rem);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}:host([data-variant=primary]),.hub-breadcrumb[data-variant=primary]{--hub-breadcrumb-accent: var(--hub-sys-color-primary)}:host([data-variant=secondary]),.hub-breadcrumb[data-variant=secondary]{--hub-breadcrumb-accent: var(--hub-sys-color-secondary)}:host([data-variant=success]),.hub-breadcrumb[data-variant=success]{--hub-breadcrumb-accent: var(--hub-sys-color-success)}:host([data-variant=danger]),.hub-breadcrumb[data-variant=danger]{--hub-breadcrumb-accent: var(--hub-sys-color-danger)}:host([data-variant=warning]),.hub-breadcrumb[data-variant=warning]{--hub-breadcrumb-accent: var(--hub-sys-color-warning)}:host([data-variant=info]),.hub-breadcrumb[data-variant=info]{--hub-breadcrumb-accent: var(--hub-sys-color-info)}:host([data-variant=neutral]),.hub-breadcrumb[data-variant=neutral]{--hub-breadcrumb-accent: var(--hub-sys-color-neutral)}:host([data-variant=light]),.hub-breadcrumb[data-variant=light]{--hub-breadcrumb-accent: var(--hub-sys-color-light)}:host([data-variant=dark]),.hub-breadcrumb[data-variant=dark]{--hub-breadcrumb-accent: var(--hub-sys-color-dark)}:host([data-variant]),.hub-breadcrumb[data-variant]{--hub-breadcrumb-accent-emphasis: color-mix(in oklch, var(--hub-breadcrumb-accent) 80%, var(--hub-sys-color-ink, #212529));--hub-breadcrumb-accent-subtle: color-mix(in oklch, var(--hub-breadcrumb-accent) 12%, var(--hub-sys-surface-page, #fff));--hub-breadcrumb-accent-on: oklch(from var(--hub-breadcrumb-accent) clamp(0, (.62 - l) * 1000, 1) 0 h);--hub-breadcrumb-link-hover-color: var(--hub-breadcrumb-accent-emphasis)}\n"] }]
|
|
334
388
|
}], propDecorators: { itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => HubBreadcrumbItemDirective), { ...{ read: TemplateRef }, isSignal: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], truncateItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "truncateItems", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], maxItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxItems", required: false }] }], itemsBeforeCollapse: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsBeforeCollapse", required: false }] }], itemsAfterCollapse: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsAfterCollapse", required: false }] }], collapsedAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedAriaLabel", required: false }] }], collapsedClick: [{ type: i0.Output, args: ["collapsedClick"] }] } });
|
|
335
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Backward-compatibility module for NgModule-based applications.
|
|
392
|
+
*
|
|
393
|
+
* @deprecated Import the standalone `HubBreadcrumbComponent` and `HubBreadcrumbItemDirective`
|
|
394
|
+
* directly; this module only re-exports them and provides nothing of its own. Scheduled for
|
|
395
|
+
* removal in **23.0.0**.
|
|
396
|
+
*/
|
|
336
397
|
class HubBreadcrumbsModule {
|
|
337
398
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: HubBreadcrumbsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
338
399
|
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: HubBreadcrumbsModule, imports: [HubBreadcrumbComponent, HubBreadcrumbItemDirective], exports: [HubBreadcrumbComponent, HubBreadcrumbItemDirective] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ng-hub-ui-breadcrumbs.mjs","sources":["../../../projects/breadcrumbs/src/lib/directives/breadcrumb-item.directive.ts","../../../projects/breadcrumbs/src/lib/breadcrumb-tooltip/breadcrumb-tooltip.token.ts","../../../projects/breadcrumbs/src/lib/directives/breadcrumb-label.directive.ts","../../../projects/breadcrumbs/src/lib/services/breadcrumbs.service.ts","../../../projects/breadcrumbs/src/lib/components/breadcrumb/breadcrumb.component.ts","../../../projects/breadcrumbs/src/lib/components/breadcrumb/breadcrumb.component.html","../../../projects/breadcrumbs/src/lib/breadcrumbs.module.ts","../../../projects/breadcrumbs/src/lib/breadcrumb-tooltip/breadcrumb-tooltip.provider.ts","../../../projects/breadcrumbs/src/public-api.ts","../../../projects/breadcrumbs/src/ng-hub-ui-breadcrumbs.ts"],"sourcesContent":["import { Directive, inject, TemplateRef } from '@angular/core';\nimport { BreadcrumbTemplateContext } from '../models/breadcrumb-template-context';\n\n@Directive({\n\tselector: '[hubBreadcrumbItem]'\n})\nexport class HubBreadcrumbItemDirective {\n\ttemplate = inject(TemplateRef<BreadcrumbTemplateContext>);\n}\n","import { InjectionToken } from '@angular/core';\nimport { HubBreadcrumbTooltipAdapter } from './breadcrumb-tooltip.types';\n\n/**\n * Injection token resolving the optional tooltip adapter used by truncated\n * breadcrumb labels.\n *\n * Inject it with `{ optional: true }`; a `null` value means \"use the native\n * `title` fallback\". Register it through {@link provideHubBreadcrumbTooltip}.\n */\nexport const HUB_BREADCRUMB_TOOLTIP_ADAPTER = new InjectionToken<HubBreadcrumbTooltipAdapter>('HUB_BREADCRUMB_TOOLTIP_ADAPTER');\n","import { afterNextRender, Directive, effect, ElementRef, inject, input, OnDestroy, signal } from '@angular/core';\nimport { HUB_BREADCRUMB_TOOLTIP_ADAPTER } from '../breadcrumb-tooltip/breadcrumb-tooltip.token';\nimport { HubBreadcrumbTooltipHandle } from '../breadcrumb-tooltip/breadcrumb-tooltip.types';\n\n/**\n * Adds an overflow-aware tooltip to a breadcrumb label element.\n *\n * Apply `[hubBreadcrumbLabel]` to the link/text of each breadcrumb item. When the\n * label is truncated (its rendered text is wider than its box — typically because\n * `hub-breadcrumb` truncation is enabled), the directive exposes the full text as\n * a tooltip: the native `title` attribute by default, or the richer hub-ui\n * tooltip when a {@link HUB_BREADCRUMB_TOOLTIP_ADAPTER} is provided. When the\n * label fits, no tooltip is shown.\n */\n@Directive({\n\tselector: '[hubBreadcrumbLabel]'\n})\nexport class HubBreadcrumbLabelDirective implements OnDestroy {\n\t/**\n\t * Explicit tooltip text. When empty, the host's own text content is used, but\n\t * only while it is truncated.\n\t */\n\treadonly tooltip = input('', { alias: 'hubBreadcrumbLabel' });\n\n\tprivate readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n\t/** Optional hub-ui tooltip adapter; absent means native `title` fallback. */\n\tprivate readonly adapter = inject(HUB_BREADCRUMB_TOOLTIP_ADAPTER, { optional: true });\n\n\t/** Whether the rendered label is wider than its clipping box. */\n\tprivate readonly isOverflowing = signal(false);\n\n\t/** Trimmed text content of the label, used as the auto tooltip source. */\n\tprivate readonly text = signal('');\n\n\t/** Becomes true once the browser-only overflow tracking is wired. */\n\tprivate readonly ready = signal(false);\n\n\tprivate resizeObserver: ResizeObserver | null = null;\n\tprivate mutationObserver: MutationObserver | null = null;\n\tprivate handle: HubBreadcrumbTooltipHandle | null = null;\n\n\tconstructor() {\n\t\tafterNextRender(() => this.initOverflowTracking());\n\n\t\teffect(() => {\n\t\t\tif (!this.ready()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst explicit = this.tooltip().trim();\n\t\t\tconst text = explicit || (this.isOverflowing() ? this.text() : '');\n\t\t\tthis.applyTooltip(text);\n\t\t});\n\t}\n\n\tngOnDestroy(): void {\n\t\tthis.resizeObserver?.disconnect();\n\t\tthis.mutationObserver?.disconnect();\n\t\tthis.handle?.destroy();\n\t\tthis.handle = null;\n\t}\n\n\t/** Wires browser-only observers that keep the truncation state in sync. */\n\tprivate initOverflowTracking(): void {\n\t\tconst el = this.host.nativeElement;\n\t\tthis.measure(el);\n\n\t\tif (typeof ResizeObserver !== 'undefined') {\n\t\t\tthis.resizeObserver = new ResizeObserver(() => this.measure(el));\n\t\t\tthis.resizeObserver.observe(el);\n\t\t}\n\n\t\tif (typeof MutationObserver !== 'undefined') {\n\t\t\tthis.mutationObserver = new MutationObserver(() => this.measure(el));\n\t\t\tthis.mutationObserver.observe(el, { childList: true, characterData: true, subtree: true });\n\t\t}\n\n\t\tthis.ready.set(true);\n\t}\n\n\t/** Reads the host's text and truncation state into the signals. */\n\tprivate measure(el: HTMLElement): void {\n\t\tthis.text.set((el.textContent ?? '').trim());\n\t\tthis.isOverflowing.set(el.scrollWidth > el.clientWidth + 1);\n\t}\n\n\t/**\n\t * Applies the effective tooltip text through the hub-ui adapter when present,\n\t * or the native `title` attribute otherwise. An empty text removes both.\n\t */\n\tprivate applyTooltip(text: string): void {\n\t\tconst el = this.host.nativeElement;\n\n\t\tif (this.adapter) {\n\t\t\tel.removeAttribute('title');\n\t\t\tif (text) {\n\t\t\t\tif (this.handle) {\n\t\t\t\t\tthis.handle.update(text);\n\t\t\t\t} else {\n\t\t\t\t\tthis.handle = this.adapter.attach(el, text);\n\t\t\t\t}\n\t\t\t} else if (this.handle) {\n\t\t\t\tthis.handle.destroy();\n\t\t\t\tthis.handle = null;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (text) {\n\t\t\tel.setAttribute('title', text);\n\t\t} else {\n\t\t\tel.removeAttribute('title');\n\t\t}\n\t}\n}\n","import { inject, Injectable } from '@angular/core';\nimport { ActivatedRoute, NavigationEnd, Router } from '@angular/router';\nimport { filter, map, startWith } from 'rxjs';\nimport { BreadcrumbItem, BreadcrumbRouteConfig, BreadcrumbRouteData } from '../models/breadcrumb-item';\n\n@Injectable({\n\tprovidedIn: 'root'\n})\nexport class HubBreadcrumbsService {\n\t#router = inject(Router);\n\t#activatedRoute = inject(ActivatedRoute);\n\n\tbreadcrumbs$ = this.#router.events.pipe(\n\t\tfilter((event) => event instanceof NavigationEnd),\n\t\tstartWith(undefined),\n\t\tmap(() => this.createBreadcrumbs(this.#activatedRoute.root))\n\t);\n\n\tprivate createBreadcrumbs(route: ActivatedRoute, url: string = '', breadcrumbs: BreadcrumbItem[] = []): BreadcrumbItem[] {\n\t\tconst children: ActivatedRoute[] = route.children;\n\n\t\tif (children.length === 0) {\n\t\t\treturn breadcrumbs;\n\t\t}\n\n\t\tfor (const child of children) {\n\t\t\t// A route is recognised before it is activated, and carries `_futureSnapshot`\n\t\t\t// in between while `snapshot` is still unset. `breadcrumbs$` opens with\n\t\t\t// `startWith(undefined)`, so a shell that draws its breadcrumb on the first\n\t\t\t// paint walks the tree inside that window — and reading `.url` there threw,\n\t\t\t// out of a subscription that draws the whole page header, taking the header\n\t\t\t// with it. There is nothing to name yet either: a route with no snapshot has\n\t\t\t// no segments and no resolved data, so it is skipped rather than guessed at.\n\t\t\tif (!child.snapshot) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst routeSegments = child.snapshot.url;\n\n\t\t\t// URL of this level\n\t\t\tconst routeURL: string = routeSegments.map((segment) => segment.path).join('/');\n\n\t\t\tconst nextUrl = routeURL ? `${url}/${routeURL}` : url;\n\n\t\t\t// Only the routes declaring their own breadcrumb become a crumb\n\t\t\tconst hasBreadcrumbData = this.hasOwnBreadcrumbData(child);\n\n\t\t\tif (hasBreadcrumbData) {\n\t\t\t\tbreadcrumbs.push(this.createItem(child, nextUrl));\n\t\t\t}\n\n\t\t\treturn this.createBreadcrumbs(child, nextUrl, breadcrumbs);\n\t\t}\n\n\t\treturn breadcrumbs;\n\t}\n\n\tprivate hasOwnBreadcrumbData(route: ActivatedRoute): boolean {\n\t\tconst routeConfig = route.routeConfig;\n\t\treturn !!(routeConfig && routeConfig.data && routeConfig.data['breadcrumb']);\n\t}\n\n\t/**\n\t * Builds the crumb for a route. The object form of `data.breadcrumb` carries\n\t * anchor metadata for destinations outside the router; whatever accompanies\n\t * `label` there travels to the item untouched, so a new anchor attribute needs\n\t * no change here.\n\t */\n\tprivate createItem(route: ActivatedRoute, url: string): BreadcrumbItem {\n\t\tconst data = route.snapshot.data;\n\t\tconst config: BreadcrumbRouteData = data['breadcrumb'];\n\n\t\tif (this.isRouteConfig(config)) {\n\t\t\tconst { label: labelSource, ...anchor } = config;\n\t\t\treturn { label: this.resolveLabel(labelSource, data), url, data, ...anchor };\n\t\t}\n\n\t\treturn { label: this.resolveLabel(config, data), url, data };\n\t}\n\n\t/** Narrows `data.breadcrumb` to its object form, excluding the function form. */\n\tprivate isRouteConfig(config: BreadcrumbRouteData): config is BreadcrumbRouteConfig {\n\t\treturn typeof config === 'object' && config !== null;\n\t}\n\n\tprivate resolveLabel(source: string | ((data: any) => string), data: any): string {\n\t\tconst label = typeof source === 'function' ? source(data) : source;\n\n\t\treturn data['resolvedData'] ? this.getResolvedBreadcrumb(label, data['resolvedData']) : label;\n\t}\n\n\tprivate getResolvedBreadcrumb(template: string, data: any): string {\n\t\treturn template.replace(/\\{([^}]+)\\}/g, (match, key) => {\n\t\t\treturn data[key] || match;\n\t\t});\n\t}\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport { Component, computed, contentChild, inject, input, linkedSignal, output, TemplateRef } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { RouterLink } from '@angular/router';\nimport { HubBreadcrumbItemDirective } from '../../directives/breadcrumb-item.directive';\nimport { HubBreadcrumbLabelDirective } from '../../directives/breadcrumb-label.directive';\nimport { BreadcrumbItem } from '../../models/breadcrumb-item';\nimport { HubBreadcrumbsService } from '../../services/breadcrumbs.service';\n\n/** Variants with exact design-system token coverage via the SCSS `@each` loop. */\nconst BUILT_IN_VARIANTS = new Set<string>(['primary', 'success', 'danger', 'warning', 'info']);\n\n/**\n * One rendered position of the trail. A `null` item is the collapsed indicator,\n * which occupies a position of its own so the separators fall around it exactly\n * as they do around a crumb.\n */\ninterface BreadcrumbRow {\n\titem: BreadcrumbItem | null;\n\tisLast: boolean;\n\t/** Resolved anchor `rel`, already defended for `_blank` targets. */\n\trel: string | null;\n}\n\n@Component({\n\tselector: 'hub-breadcrumb',\n\timports: [RouterLink, NgTemplateOutlet, HubBreadcrumbLabelDirective],\n\ttemplateUrl: './breadcrumb.component.html',\n\tstyleUrl: './breadcrumb.component.scss',\n\thost: {\n\t\tclass: 'hub-breadcrumb',\n\t\t'[class.hub-breadcrumb--truncate]': 'truncateItems()',\n\t\t'[attr.data-variant]': 'variant() ?? null',\n\t\t'[style.--hub-breadcrumb-accent]': 'customAccent()'\n\t}\n})\nexport class HubBreadcrumbComponent {\n\t#breadcrumbsSvc = inject(HubBreadcrumbsService);\n\n\treadonly itemTemplate = contentChild(HubBreadcrumbItemDirective, { read: TemplateRef });\n\n\tbreadcrumbs$ = this.#breadcrumbsSvc.breadcrumbs$;\n\n\t/**\n\t * Semantic accent for the breadcrumb links: `'primary'` · `'success'` ·\n\t * `'danger'` · `'warning'` · `'info'`, or any custom string (read as\n\t * `--hub-sys-color-<variant>`). Re-bases `--hub-breadcrumb-accent`; the\n\t * current (last) item stays muted. Defaults to the standard link colour.\n\t */\n\treadonly variant = input<string>();\n\n\t/**\n\t * Opt-in per-item truncation. When `true`, each label is clipped to\n\t * `--hub-breadcrumb-max-item-width` with an ellipsis and, if it overflows,\n\t * exposes its full text as a tooltip (native `title`, or the hub-ui tooltip\n\t * when {@link provideHubBreadcrumbTooltip} is wired). Off by default, so the\n\t * standard breadcrumb layout is unchanged.\n\t */\n\treadonly truncateItems = input(false);\n\n\t/**\n\t * Trail supplied by the consumer, replacing the one derived from the router.\n\t * It is the way in for crumbs the route tree cannot express — an ancestor\n\t * served by another application, or a trail assembled by hand. Left `null`,\n\t * the component keeps reading {@link HubBreadcrumbsService}.\n\t */\n\treadonly items = input<BreadcrumbItem[] | null>(null);\n\n\t/**\n\t * Length above which the trail collapses behind an indicator. Undefined (the\n\t * default) never collapses, however long the trail grows.\n\t */\n\treadonly maxItems = input<number | undefined>(undefined);\n\n\t/** Crumbs kept at the head of a collapsed trail. */\n\treadonly itemsBeforeCollapse = input(1);\n\n\t/** Crumbs kept at the tail of a collapsed trail, the current page included. */\n\treadonly itemsAfterCollapse = input(1);\n\n\t/**\n\t * Accessible name of the collapsed indicator. It is an input rather than a\n\t * literal because it is the one string of this component a screen reader\n\t * announces, and the library carries no translations of its own.\n\t */\n\treadonly collapsedAriaLabel = input('Show the hidden breadcrumb items');\n\n\t/**\n\t * Fires when the collapsed indicator is activated. The trail expands in place\n\t * on its own; the event is there for consumers who want to react as well —\n\t * open a menu of the hidden crumbs, log the interaction.\n\t */\n\treadonly collapsedClick = output<void>();\n\n\t/** Trail as published by the service, tracked as a signal. */\n\treadonly #routerTrail = toSignal(this.breadcrumbs$, { initialValue: [] as BreadcrumbItem[] });\n\n\t/** Effective trail: the manual one when supplied, the router's otherwise. */\n\tprotected readonly trail = computed(() => this.items() ?? this.#routerTrail());\n\n\t/**\n\t * Whether the reader has opened a collapsed trail. Derived from the trail so a\n\t * new navigation collapses it again — an expansion answers one trail, not the\n\t * component's whole lifetime.\n\t */\n\tprotected readonly expanded = linkedSignal<BreadcrumbItem[], boolean>({\n\t\tsource: this.trail,\n\t\tcomputation: () => false\n\t});\n\n\t/** Rendered positions, with the collapsed range folded into one indicator. */\n\tprotected readonly rows = computed<BreadcrumbRow[]>(() => {\n\t\tconst items = this.trail();\n\t\tconst before = Math.max(0, this.itemsBeforeCollapse());\n\t\tconst after = Math.max(0, this.itemsAfterCollapse());\n\t\tconst max = this.maxItems();\n\n\t\tconst rowAt = (item: BreadcrumbItem, index: number): BreadcrumbRow => ({\n\t\t\titem,\n\t\t\tisLast: index === items.length - 1,\n\t\t\trel: this.resolveRel(item)\n\t\t});\n\n\t\tconst collapses = max !== undefined && max > 0 && items.length > max && before + after < items.length;\n\n\t\tif (!collapses || this.expanded()) {\n\t\t\treturn items.map(rowAt);\n\t\t}\n\n\t\tconst tailStart = items.length - after;\n\n\t\treturn [\n\t\t\t...items.slice(0, before).map(rowAt),\n\t\t\t{ item: null, isLast: false, rel: null },\n\t\t\t...items.slice(tailStart).map((item, index) => rowAt(item, tailStart + index))\n\t\t];\n\t});\n\n\t/**\n\t * Inline accent for custom (non-built-in) variants — the built-in five are\n\t * resolved by the SCSS `@each` loop, so this returns `null` for them.\n\t */\n\tprotected readonly customAccent = computed(() => {\n\t\tconst v = this.variant();\n\t\treturn v && !BUILT_IN_VARIANTS.has(v) ? `var(--hub-sys-color-${v})` : null;\n\t});\n\n\t/** Opens a collapsed trail and lets the consumer act on the same gesture. */\n\tprotected expand(): void {\n\t\tthis.expanded.set(true);\n\t\tthis.collapsedClick.emit();\n\t}\n\n\t/**\n\t * A crumb opening in a new tab hands the opener to the destination unless it\n\t * says otherwise, so the default closes that door rather than leaving it to\n\t * each consumer to remember.\n\t */\n\tprivate resolveRel(item: BreadcrumbItem): string | null {\n\t\treturn item.rel ?? (item.target === '_blank' ? 'noopener noreferrer' : null);\n\t}\n}\n","<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (row of rows(); track $index) {\n\t\t\t@if (row.item; as item) {\n\t\t\t\t<li class=\"hub-breadcrumb__item\" [class.hub-breadcrumb__item--active]=\"row.isLast\">\n\t\t\t\t\t@if (itemTemplate(); as template) {\n\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t[ngTemplateOutlet]=\"template\"\n\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t$implicit: item,\n\t\t\t\t\t\t\t\tisLast: row.isLast\n\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t} @else if (row.isLast) {\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__text\" hubBreadcrumbLabel aria-current=\"page\">{{ item.label }}</span>\n\t\t\t\t\t} @else if (item.href) {\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclass=\"hub-breadcrumb__link\"\n\t\t\t\t\t\t\thubBreadcrumbLabel\n\t\t\t\t\t\t\t[href]=\"item.href\"\n\t\t\t\t\t\t\t[attr.target]=\"item.target ?? null\"\n\t\t\t\t\t\t\t[attr.rel]=\"row.rel\"\n\t\t\t\t\t\t\t[attr.download]=\"item.download ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<a [routerLink]=\"item.url\" class=\"hub-breadcrumb__link\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t}\n\t\t\t\t</li>\n\t\t\t} @else {\n\t\t\t\t<li class=\"hub-breadcrumb__item hub-breadcrumb__item--collapsed\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"hub-breadcrumb__collapsed\"\n\t\t\t\t\t\t[attr.aria-label]=\"collapsedAriaLabel()\"\n\t\t\t\t\t\t[attr.aria-expanded]=\"expanded()\"\n\t\t\t\t\t\t(click)=\"expand()\"\n\t\t\t\t\t>\n\t\t\t\t\t\t…\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t}\n\t\t}\n\t</ol>\n</nav>\n","import { NgModule } from '@angular/core';\nimport { HubBreadcrumbComponent } from './components/breadcrumb/breadcrumb.component';\nimport { HubBreadcrumbItemDirective } from './directives/breadcrumb-item.directive';\n\n@NgModule({\n\tdeclarations: [],\n\timports: [HubBreadcrumbComponent, HubBreadcrumbItemDirective],\n\texports: [HubBreadcrumbComponent, HubBreadcrumbItemDirective]\n})\nexport class HubBreadcrumbsModule {}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { HUB_BREADCRUMB_TOOLTIP_ADAPTER } from './breadcrumb-tooltip.token';\nimport { HubBreadcrumbTooltipAdapter } from './breadcrumb-tooltip.types';\n\n/**\n * Registers a tooltip adapter so truncated breadcrumb labels render the rich\n * hub-ui tooltip instead of the native `title` fallback.\n *\n * ```ts\n * import { provideHubBreadcrumbTooltip } from 'ng-hub-ui-breadcrumbs';\n * import { hubTooltipAdapter } from 'ng-hub-ui-utils';\n *\n * providers: [provideHubBreadcrumbTooltip(hubTooltipAdapter)];\n * ```\n *\n * @param adapter Tooltip adapter implementation (e.g. `hubTooltipAdapter` from\n * `ng-hub-ui-utils`).\n * @returns Environment providers to add to the application config.\n */\nexport function provideHubBreadcrumbTooltip(adapter: HubBreadcrumbTooltipAdapter): EnvironmentProviders {\n\treturn makeEnvironmentProviders([\n\t\t{\n\t\t\tprovide: HUB_BREADCRUMB_TOOLTIP_ADAPTER,\n\t\t\tuseValue: adapter\n\t\t}\n\t]);\n}\n","/*\n * Public API Surface of breadcrumbs\n */\nexport * from './lib/breadcrumbs.module';\nexport * from './lib/breadcrumb-tooltip';\nexport * from './lib/components/breadcrumb/breadcrumb.component';\nexport * from './lib/directives/breadcrumb-item.directive';\nexport * from './lib/directives/breadcrumb-label.directive';\nexport * from './lib/models/breadcrumb-item';\nexport * from './lib/models/breadcrumb-template-context';\nexport * from './lib/services/breadcrumbs.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ng-hub-ui-breadcrumbs.mjs","sources":["../../../projects/breadcrumbs/src/lib/directives/breadcrumb-item.directive.ts","../../../projects/breadcrumbs/src/lib/breadcrumb-tooltip/breadcrumb-tooltip.token.ts","../../../projects/breadcrumbs/src/lib/directives/breadcrumb-label.directive.ts","../../../projects/breadcrumbs/src/lib/services/breadcrumbs.service.ts","../../../projects/breadcrumbs/src/lib/components/breadcrumb/breadcrumb.component.ts","../../../projects/breadcrumbs/src/lib/components/breadcrumb/breadcrumb.component.html","../../../projects/breadcrumbs/src/lib/breadcrumbs.module.ts","../../../projects/breadcrumbs/src/lib/breadcrumb-tooltip/breadcrumb-tooltip.provider.ts","../../../projects/breadcrumbs/src/public-api.ts","../../../projects/breadcrumbs/src/ng-hub-ui-breadcrumbs.ts"],"sourcesContent":["import { Directive, inject, TemplateRef } from '@angular/core';\nimport { BreadcrumbTemplateContext } from '../models/breadcrumb-template-context';\n\n@Directive({\n\tselector: '[hubBreadcrumbItem]'\n})\nexport class HubBreadcrumbItemDirective {\n\ttemplate = inject(TemplateRef<BreadcrumbTemplateContext>);\n}\n","import { InjectionToken } from '@angular/core';\nimport { HubBreadcrumbTooltipAdapter } from './breadcrumb-tooltip.types';\n\n/**\n * Injection token resolving the optional tooltip adapter used by truncated\n * breadcrumb labels.\n *\n * Inject it with `{ optional: true }`; a `null` value means \"use the native\n * `title` fallback\". Register it through {@link provideHubBreadcrumbTooltip}.\n */\nexport const HUB_BREADCRUMB_TOOLTIP_ADAPTER = new InjectionToken<HubBreadcrumbTooltipAdapter>('HUB_BREADCRUMB_TOOLTIP_ADAPTER');\n","import { afterNextRender, Directive, effect, ElementRef, inject, input, OnDestroy, signal } from '@angular/core';\nimport { HUB_BREADCRUMB_TOOLTIP_ADAPTER } from '../breadcrumb-tooltip/breadcrumb-tooltip.token';\nimport { HubBreadcrumbTooltipHandle } from '../breadcrumb-tooltip/breadcrumb-tooltip.types';\n\n/**\n * Adds an overflow-aware tooltip to a breadcrumb label element.\n *\n * When the label is truncated (its rendered text is wider than its box — typically\n * because `hub-breadcrumb` truncation is enabled), the directive exposes the full\n * text as a tooltip: the native `title` attribute by default, or the richer hub-ui\n * tooltip when a {@link HUB_BREADCRUMB_TOOLTIP_ADAPTER} is provided. When the\n * label fits, no tooltip is shown.\n *\n * `hub-breadcrumb` already applies it to the labels it renders and to the box it\n * wraps a `hubBreadcrumbItem` template in, so applying `[hubBreadcrumbLabel]` by\n * hand is for saying something other than the label — a full path, a spelled-out\n * date — through the directive's own input.\n */\n@Directive({\n\tselector: '[hubBreadcrumbLabel]'\n})\nexport class HubBreadcrumbLabelDirective implements OnDestroy {\n\t/**\n\t * Explicit tooltip text. When empty, the host's own text content is used, but\n\t * only while it is truncated.\n\t */\n\treadonly tooltip = input('', { alias: 'hubBreadcrumbLabel' });\n\n\tprivate readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n\t/** Optional hub-ui tooltip adapter; absent means native `title` fallback. */\n\tprivate readonly adapter = inject(HUB_BREADCRUMB_TOOLTIP_ADAPTER, { optional: true });\n\n\t/** Whether the rendered label is wider than its clipping box. */\n\tprivate readonly isOverflowing = signal(false);\n\n\t/** Trimmed text content of the label, used as the auto tooltip source. */\n\tprivate readonly text = signal('');\n\n\t/** Becomes true once the browser-only overflow tracking is wired. */\n\tprivate readonly ready = signal(false);\n\n\tprivate resizeObserver: ResizeObserver | null = null;\n\tprivate mutationObserver: MutationObserver | null = null;\n\tprivate handle: HubBreadcrumbTooltipHandle | null = null;\n\n\tconstructor() {\n\t\tafterNextRender(() => this.initOverflowTracking());\n\n\t\teffect(() => {\n\t\t\tif (!this.ready()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst explicit = this.tooltip().trim();\n\t\t\tconst text = explicit || (this.isOverflowing() ? this.text() : '');\n\t\t\tthis.applyTooltip(text);\n\t\t});\n\t}\n\n\tngOnDestroy(): void {\n\t\tthis.resizeObserver?.disconnect();\n\t\tthis.mutationObserver?.disconnect();\n\t\tthis.handle?.destroy();\n\t\tthis.handle = null;\n\t}\n\n\t/** Wires browser-only observers that keep the truncation state in sync. */\n\tprivate initOverflowTracking(): void {\n\t\tconst el = this.host.nativeElement;\n\t\tthis.measure(el);\n\n\t\tif (typeof ResizeObserver !== 'undefined') {\n\t\t\tthis.resizeObserver = new ResizeObserver(() => this.measure(el));\n\t\t\tthis.resizeObserver.observe(el);\n\t\t}\n\n\t\tif (typeof MutationObserver !== 'undefined') {\n\t\t\tthis.mutationObserver = new MutationObserver(() => this.measure(el));\n\t\t\tthis.mutationObserver.observe(el, { childList: true, characterData: true, subtree: true });\n\t\t}\n\n\t\tthis.ready.set(true);\n\t}\n\n\t/** Reads the host's text and truncation state into the signals. */\n\tprivate measure(el: HTMLElement): void {\n\t\tthis.text.set((el.textContent ?? '').trim());\n\t\tthis.isOverflowing.set(el.scrollWidth > el.clientWidth + 1);\n\t}\n\n\t/**\n\t * Applies the effective tooltip text through the hub-ui adapter when present,\n\t * or the native `title` attribute otherwise. An empty text removes both.\n\t */\n\tprivate applyTooltip(text: string): void {\n\t\tconst el = this.host.nativeElement;\n\n\t\tif (this.adapter) {\n\t\t\tel.removeAttribute('title');\n\t\t\tif (text) {\n\t\t\t\tif (this.handle) {\n\t\t\t\t\tthis.handle.update(text);\n\t\t\t\t} else {\n\t\t\t\t\tthis.handle = this.adapter.attach(el, text);\n\t\t\t\t}\n\t\t\t} else if (this.handle) {\n\t\t\t\tthis.handle.destroy();\n\t\t\t\tthis.handle = null;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (text) {\n\t\t\tel.setAttribute('title', text);\n\t\t} else {\n\t\t\tel.removeAttribute('title');\n\t\t}\n\t}\n}\n","import { inject, Injectable, Signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { ActivatedRoute, NavigationEnd, Router } from '@angular/router';\nimport { filter, map, startWith } from 'rxjs';\nimport { BreadcrumbItem, BreadcrumbRouteConfig, BreadcrumbRouteData } from '../models/breadcrumb-item';\n\n@Injectable({\n\tprovidedIn: 'root'\n})\nexport class HubBreadcrumbsService {\n\t#router = inject(Router);\n\t#activatedRoute = inject(ActivatedRoute);\n\n\t/** The trail as a stream, for consumers already composing with rxjs. */\n\tbreadcrumbs$ = this.#router.events.pipe(\n\t\tfilter((event) => event instanceof NavigationEnd),\n\t\tstartWith(undefined),\n\t\tmap(() => this.createBreadcrumbs(this.#activatedRoute.root))\n\t);\n\n\t/**\n\t * The trail as a signal, and the surface the component reads. Published here\n\t * rather than left to each consumer, because a stream that only ever carries\n\t * the current trail is one every caller was wrapping in the same `toSignal`\n\t * — the component included. Wrapped once, subscribed once.\n\t */\n\treadonly breadcrumbs: Signal<BreadcrumbItem[]> = toSignal(this.breadcrumbs$, { initialValue: [] as BreadcrumbItem[] });\n\n\tprivate createBreadcrumbs(route: ActivatedRoute, url: string = '', breadcrumbs: BreadcrumbItem[] = []): BreadcrumbItem[] {\n\t\tconst children: ActivatedRoute[] = route.children;\n\n\t\tif (children.length === 0) {\n\t\t\treturn breadcrumbs;\n\t\t}\n\n\t\tfor (const child of children) {\n\t\t\t// A route is recognised before it is activated, and carries `_futureSnapshot`\n\t\t\t// in between while `snapshot` is still unset. `breadcrumbs$` opens with\n\t\t\t// `startWith(undefined)`, so a shell that draws its breadcrumb on the first\n\t\t\t// paint walks the tree inside that window — and reading `.url` there threw,\n\t\t\t// out of a subscription that draws the whole page header, taking the header\n\t\t\t// with it. There is nothing to name yet either: a route with no snapshot has\n\t\t\t// no segments and no resolved data, so it is skipped rather than guessed at.\n\t\t\tif (!child.snapshot) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst routeSegments = child.snapshot.url;\n\n\t\t\t// URL of this level\n\t\t\tconst routeURL: string = routeSegments.map((segment) => segment.path).join('/');\n\n\t\t\tconst nextUrl = routeURL ? `${url}/${routeURL}` : url;\n\n\t\t\t// Only the routes declaring their own breadcrumb become a crumb\n\t\t\tconst hasBreadcrumbData = this.hasOwnBreadcrumbData(child);\n\n\t\t\tif (hasBreadcrumbData) {\n\t\t\t\tbreadcrumbs.push(this.createItem(child, nextUrl));\n\t\t\t}\n\n\t\t\treturn this.createBreadcrumbs(child, nextUrl, breadcrumbs);\n\t\t}\n\n\t\treturn breadcrumbs;\n\t}\n\n\tprivate hasOwnBreadcrumbData(route: ActivatedRoute): boolean {\n\t\tconst routeConfig = route.routeConfig;\n\t\treturn !!(routeConfig && routeConfig.data && routeConfig.data['breadcrumb']);\n\t}\n\n\t/**\n\t * Builds the crumb for a route. The object form of `data.breadcrumb` carries\n\t * anchor metadata for destinations outside the router; whatever accompanies\n\t * `label` there travels to the item untouched, so a new anchor attribute needs\n\t * no change here.\n\t */\n\tprivate createItem(route: ActivatedRoute, url: string): BreadcrumbItem {\n\t\tconst data = route.snapshot.data;\n\t\tconst config: BreadcrumbRouteData = data['breadcrumb'];\n\n\t\tif (this.isRouteConfig(config)) {\n\t\t\tconst { label: labelSource, ...anchor } = config;\n\t\t\treturn { label: this.resolveLabel(labelSource, data), url, data, ...anchor };\n\t\t}\n\n\t\treturn { label: this.resolveLabel(config, data), url, data };\n\t}\n\n\t/** Narrows `data.breadcrumb` to its object form, excluding the function form. */\n\tprivate isRouteConfig(config: BreadcrumbRouteData): config is BreadcrumbRouteConfig {\n\t\treturn typeof config === 'object' && config !== null;\n\t}\n\n\tprivate resolveLabel(source: string | ((data: any) => string), data: any): string {\n\t\tconst label = typeof source === 'function' ? source(data) : source;\n\n\t\treturn data['resolvedData'] ? this.getResolvedBreadcrumb(label, data['resolvedData']) : label;\n\t}\n\n\tprivate getResolvedBreadcrumb(template: string, data: any): string {\n\t\treturn template.replace(/\\{([^}]+)\\}/g, (match, key) => {\n\t\t\treturn data[key] || match;\n\t\t});\n\t}\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n\tafterNextRender,\n\tChangeDetectionStrategy,\n\tComponent,\n\tcomputed,\n\tcontentChild,\n\tElementRef,\n\tinject,\n\tInjector,\n\tinput,\n\tlinkedSignal,\n\toutput,\n\tTemplateRef\n} from '@angular/core';\nimport { RouterLink } from '@angular/router';\nimport { HubBreadcrumbItemDirective } from '../../directives/breadcrumb-item.directive';\nimport { HubBreadcrumbLabelDirective } from '../../directives/breadcrumb-label.directive';\nimport { BreadcrumbItem } from '../../models/breadcrumb-item';\nimport { HubBreadcrumbsService } from '../../services/breadcrumbs.service';\n\n/**\n * Variants with exact design-system token coverage via the SCSS `@each` loop.\n * Kept in step with that loop by hand, because Sass cannot read this file: a name\n * dropped from here is not broken, only paid for twice — once inline and once by\n * the stylesheet.\n */\nconst BUILT_IN_VARIANTS = new Set<string>([\n\t'primary',\n\t'secondary',\n\t'success',\n\t'danger',\n\t'warning',\n\t'info',\n\t'neutral',\n\t'light',\n\t'dark'\n]);\n\n/**\n * One rendered position of the trail. A `null` item is the collapsed indicator,\n * which occupies a position of its own so the separators fall around it exactly\n * as they do around a crumb.\n */\ninterface BreadcrumbRow {\n\titem: BreadcrumbItem | null;\n\tisLast: boolean;\n\t/** Resolved anchor `rel`, already defended for `_blank` targets. */\n\trel: string | null;\n}\n\n@Component({\n\tselector: 'hub-breadcrumb',\n\timports: [RouterLink, NgTemplateOutlet, HubBreadcrumbLabelDirective],\n\ttemplateUrl: './breadcrumb.component.html',\n\tstyleUrl: './breadcrumb.component.scss',\n\tchangeDetection: ChangeDetectionStrategy.OnPush,\n\thost: {\n\t\tclass: 'hub-breadcrumb',\n\t\t'[class.hub-breadcrumb--truncate]': 'truncateItems()',\n\t\t'[attr.data-variant]': 'variant() ?? null',\n\t\t'[style.--hub-breadcrumb-accent]': 'customAccent()'\n\t}\n})\nexport class HubBreadcrumbComponent {\n\t#breadcrumbsSvc = inject(HubBreadcrumbsService);\n\t#host = inject<ElementRef<HTMLElement>>(ElementRef);\n\t#injector = inject(Injector);\n\n\treadonly itemTemplate = contentChild(HubBreadcrumbItemDirective, { read: TemplateRef });\n\n\t/**\n\t * Semantic accent for the breadcrumb links: `'primary'` · `'secondary'` ·\n\t * `'success'` · `'danger'` · `'warning'` · `'info'` · `'neutral'` · `'light'` ·\n\t * `'dark'`, or any custom string (read as `--hub-sys-color-<variant>`).\n\t * Re-bases `--hub-breadcrumb-accent`; the current (last) item stays muted.\n\t * Defaults to the standard link colour.\n\t */\n\treadonly variant = input<string>();\n\n\t/**\n\t * Opt-in per-item truncation. When `true`, each label is clipped to\n\t * `--hub-breadcrumb-max-item-width` with an ellipsis and, if it overflows,\n\t * exposes its full text as a tooltip (native `title`, or the hub-ui tooltip\n\t * when {@link provideHubBreadcrumbTooltip} is wired). Off by default, so the\n\t * standard breadcrumb layout is unchanged.\n\t *\n\t * It reaches a `hubBreadcrumbItem` template as well: the projected elements\n\t * belong to the consuming component, so the template wraps them in a\n\t * `span.hub-breadcrumb__custom` of its own and clips that instead.\n\t */\n\treadonly truncateItems = input(false);\n\n\t/**\n\t * Trail supplied by the consumer, replacing the one derived from the router.\n\t * It is the way in for crumbs the route tree cannot express — an ancestor\n\t * served by another application, or a trail assembled by hand. Left `null`,\n\t * the component keeps reading {@link HubBreadcrumbsService}.\n\t */\n\treadonly items = input<BreadcrumbItem[] | null>(null);\n\n\t/**\n\t * Length above which the trail collapses behind an indicator. Undefined (the\n\t * default) never collapses, however long the trail grows.\n\t */\n\treadonly maxItems = input<number | undefined>(undefined);\n\n\t/** Crumbs kept at the head of a collapsed trail. */\n\treadonly itemsBeforeCollapse = input(1);\n\n\t/** Crumbs kept at the tail of a collapsed trail, the current page included. */\n\treadonly itemsAfterCollapse = input(1);\n\n\t/**\n\t * Accessible name of the collapsed indicator. It is an input rather than a\n\t * literal because it is the one string of this component a screen reader\n\t * announces, and the library carries no translations of its own.\n\t */\n\treadonly collapsedAriaLabel = input('Show the hidden breadcrumb items');\n\n\t/**\n\t * Fires when the collapsed indicator is activated. The trail expands in place\n\t * on its own; the event is there for consumers who want to react as well —\n\t * open a menu of the hidden crumbs, log the interaction.\n\t */\n\treadonly collapsedClick = output<void>();\n\n\t/** Effective trail: the manual one when supplied, the router's otherwise. */\n\tprotected readonly trail = computed(() => this.items() ?? this.#breadcrumbsSvc.breadcrumbs());\n\n\t/**\n\t * Whether the reader has opened a collapsed trail. Derived from the trail so a\n\t * new navigation collapses it again — an expansion answers one trail, not the\n\t * component's whole lifetime.\n\t */\n\tprotected readonly expanded = linkedSignal<BreadcrumbItem[], boolean>({\n\t\tsource: this.trail,\n\t\tcomputation: () => false\n\t});\n\n\t/** Rendered positions, with the collapsed range folded into one indicator. */\n\tprotected readonly rows = computed<BreadcrumbRow[]>(() => {\n\t\tconst items = this.trail();\n\t\tconst before = Math.max(0, this.itemsBeforeCollapse());\n\t\tconst after = Math.max(0, this.itemsAfterCollapse());\n\t\tconst max = this.maxItems();\n\n\t\tconst rowAt = (item: BreadcrumbItem, index: number): BreadcrumbRow => ({\n\t\t\titem,\n\t\t\tisLast: index === items.length - 1,\n\t\t\trel: this.resolveRel(item)\n\t\t});\n\n\t\tconst collapses = max !== undefined && max > 0 && items.length > max && before + after < items.length;\n\n\t\tif (!collapses || this.expanded()) {\n\t\t\treturn items.map(rowAt);\n\t\t}\n\n\t\tconst tailStart = items.length - after;\n\n\t\treturn [\n\t\t\t...items.slice(0, before).map(rowAt),\n\t\t\t{ item: null, isLast: false, rel: null },\n\t\t\t...items.slice(tailStart).map((item, index) => rowAt(item, tailStart + index))\n\t\t];\n\t});\n\n\t/**\n\t * Inline accent for custom (non-built-in) variants — the nine built-in accents\n\t * are resolved by the SCSS `@each` loop, so this returns `null` for them.\n\t */\n\tprotected readonly customAccent = computed(() => {\n\t\tconst v = this.variant();\n\t\treturn v && !BUILT_IN_VARIANTS.has(v) ? `var(--hub-sys-color-${v})` : null;\n\t});\n\n\t/** Opens a collapsed trail and lets the consumer act on the same gesture. */\n\tprotected expand(): void {\n\t\tthis.expanded.set(true);\n\t\tthis.collapsedClick.emit();\n\t\tafterNextRender(() => this.#focusFirstRevealedCrumb(), { injector: this.#injector });\n\t}\n\n\t/**\n\t * Expanding removes the indicator — the element that was holding focus — from the\n\t * DOM, and a browser answers that by focusing `<body>`: whoever opened the trail\n\t * from the keyboard would have to tab from the top of the page to reach the crumbs\n\t * they just asked for. Focus lands on the first revealed crumb instead, which is\n\t * where reading continues.\n\t */\n\t#focusFirstRevealedCrumb(): void {\n\t\tconst crumbs = this.#host.nativeElement.querySelectorAll<HTMLElement>('.hub-breadcrumb__item');\n\t\tconst revealed = crumbs[Math.max(0, this.itemsBeforeCollapse())];\n\n\t\tif (!revealed) {\n\t\t\treturn;\n\t\t}\n\n\t\t// A crumb may render as plain text — the current page, or a custom template with\n\t\t// no control of its own — and text takes no focus. Make that one crumb\n\t\t// programmatically focusable rather than let focus fall back to the body.\n\t\tconst target = revealed.querySelector<HTMLElement>('a, button, [tabindex]') ?? revealed;\n\t\tif (target === revealed) {\n\t\t\trevealed.tabIndex = -1;\n\t\t}\n\n\t\ttarget.focus();\n\t}\n\n\t/**\n\t * A crumb opening in a new tab hands the opener to the destination unless it\n\t * says otherwise, so the default closes that door rather than leaving it to\n\t * each consumer to remember.\n\t */\n\tprivate resolveRel(item: BreadcrumbItem): string | null {\n\t\treturn item.rel ?? (item.target === '_blank' ? 'noopener noreferrer' : null);\n\t}\n}\n","<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (row of rows(); track $index) {\n\t\t\t@if (row.item; as item) {\n\t\t\t\t<li\n\t\t\t\t\tclass=\"hub-breadcrumb__item\"\n\t\t\t\t\t[class.hub-breadcrumb__item--active]=\"row.isLast\"\n\t\t\t\t\t[attr.aria-current]=\"row.isLast ? 'page' : null\"\n\t\t\t\t>\n\t\t\t\t\t@if (itemTemplate(); as template) {\n\t\t\t\t\t\t<!--\n\t\t\t\t\t\t\tThe clipping box for a custom crumb. Scoped styles never reach the elements\n\t\t\t\t\t\t\ta `hubBreadcrumbItem` template renders — they belong to the consuming\n\t\t\t\t\t\t\tcomponent — so `truncateItems` can only clip something this component draws\n\t\t\t\t\t\t\titself. It sits exactly where a built-in label sits, inside the item and\n\t\t\t\t\t\t\toutside the separator, so a projected crumb gets the same width as any other.\n\t\t\t\t\t\t-->\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__custom\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"template\"\n\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t$implicit: item,\n\t\t\t\t\t\t\t\t\tisLast: row.isLast\n\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t} @else if (row.isLast) {\n\t\t\t\t\t\t<span class=\"hub-breadcrumb__text\" hubBreadcrumbLabel>{{ item.label }}</span>\n\t\t\t\t\t} @else if (item.href) {\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tclass=\"hub-breadcrumb__link\"\n\t\t\t\t\t\t\thubBreadcrumbLabel\n\t\t\t\t\t\t\t[href]=\"item.href\"\n\t\t\t\t\t\t\t[attr.target]=\"item.target ?? null\"\n\t\t\t\t\t\t\t[attr.rel]=\"row.rel\"\n\t\t\t\t\t\t\t[attr.download]=\"item.download ?? null\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t} @else {\n\t\t\t\t\t\t<a [routerLink]=\"item.url\" class=\"hub-breadcrumb__link\" hubBreadcrumbLabel>\n\t\t\t\t\t\t\t{{ item.label }}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t}\n\t\t\t\t</li>\n\t\t\t} @else {\n\t\t\t\t<li class=\"hub-breadcrumb__item hub-breadcrumb__item--collapsed\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"hub-breadcrumb__collapsed\"\n\t\t\t\t\t\t[attr.aria-label]=\"collapsedAriaLabel()\"\n\t\t\t\t\t\t[attr.aria-expanded]=\"expanded()\"\n\t\t\t\t\t\t(click)=\"expand()\"\n\t\t\t\t\t>\n\t\t\t\t\t\t…\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t}\n\t\t}\n\t</ol>\n</nav>\n","import { NgModule } from '@angular/core';\nimport { HubBreadcrumbComponent } from './components/breadcrumb/breadcrumb.component';\nimport { HubBreadcrumbItemDirective } from './directives/breadcrumb-item.directive';\n\n/**\n * Backward-compatibility module for NgModule-based applications.\n *\n * @deprecated Import the standalone `HubBreadcrumbComponent` and `HubBreadcrumbItemDirective`\n * directly; this module only re-exports them and provides nothing of its own. Scheduled for\n * removal in **23.0.0**.\n */\n@NgModule({\n\tdeclarations: [],\n\timports: [HubBreadcrumbComponent, HubBreadcrumbItemDirective],\n\texports: [HubBreadcrumbComponent, HubBreadcrumbItemDirective]\n})\nexport class HubBreadcrumbsModule {}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { HUB_BREADCRUMB_TOOLTIP_ADAPTER } from './breadcrumb-tooltip.token';\nimport { HubBreadcrumbTooltipAdapter } from './breadcrumb-tooltip.types';\n\n/**\n * Registers a tooltip adapter so truncated breadcrumb labels render the rich\n * hub-ui tooltip instead of the native `title` fallback.\n *\n * ```ts\n * import { provideHubBreadcrumbTooltip } from 'ng-hub-ui-breadcrumbs';\n * import { hubTooltipAdapter } from 'ng-hub-ui-utils';\n *\n * providers: [provideHubBreadcrumbTooltip(hubTooltipAdapter)];\n * ```\n *\n * @param adapter Tooltip adapter implementation (e.g. `hubTooltipAdapter` from\n * `ng-hub-ui-utils`).\n * @returns Environment providers to add to the application config.\n */\nexport function provideHubBreadcrumbTooltip(adapter: HubBreadcrumbTooltipAdapter): EnvironmentProviders {\n\treturn makeEnvironmentProviders([\n\t\t{\n\t\t\tprovide: HUB_BREADCRUMB_TOOLTIP_ADAPTER,\n\t\t\tuseValue: adapter\n\t\t}\n\t]);\n}\n","/*\n * Public API Surface of breadcrumbs\n */\nexport * from './lib/breadcrumbs.module';\nexport * from './lib/breadcrumb-tooltip';\nexport * from './lib/components/breadcrumb/breadcrumb.component';\nexport * from './lib/directives/breadcrumb-item.directive';\nexport * from './lib/directives/breadcrumb-label.directive';\nexport * from './lib/models/breadcrumb-item';\nexport * from './lib/models/breadcrumb-template-context';\nexport * from './lib/services/breadcrumbs.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ng-hub-ui-breadcrumbs",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.7.0",
|
|
4
4
|
"description": "A flexible and reusable breadcrumb component for Angular applications that automatically generates breadcrumbs based on routing configuration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -11,11 +11,18 @@
|
|
|
11
11
|
// automatically; use this mixin to restyle the shell — surface, spacing,
|
|
12
12
|
// divider, link colours — or to set a brand accent on a custom selector.
|
|
13
13
|
//
|
|
14
|
+
// Include it ON the `<hub-breadcrumb>` element, with a selector that outranks the
|
|
15
|
+
// component's own `:host` defaults — tag plus class does it. A bare class ties on
|
|
16
|
+
// specificity and loses on source order, and the same class on a wrapper never
|
|
17
|
+
// reaches the component, because a declaration on the element beats inheritance.
|
|
18
|
+
// The single exception is an include that passes only `$accent`: that slot is left
|
|
19
|
+
// undeclared on the host on purpose, so it inherits from wherever you set it.
|
|
20
|
+
//
|
|
14
21
|
// @example
|
|
15
22
|
//
|
|
16
23
|
// @use 'ng-hub-ui-breadcrumbs/styles' as *;
|
|
17
24
|
//
|
|
18
|
-
// .docs-breadcrumb {
|
|
25
|
+
// hub-breadcrumb.docs-breadcrumb {
|
|
19
26
|
// @include hub-breadcrumb-theme(
|
|
20
27
|
// $bg: #f8fafc,
|
|
21
28
|
// $padding-x: 0.75rem,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { TemplateRef, InjectionToken, EnvironmentProviders, OnDestroy } from '@angular/core';
|
|
2
|
+
import { TemplateRef, InjectionToken, EnvironmentProviders, OnDestroy, Signal } from '@angular/core';
|
|
3
3
|
import * as rxjs from 'rxjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -53,12 +53,12 @@ interface BreadcrumbRow {
|
|
|
53
53
|
declare class HubBreadcrumbComponent {
|
|
54
54
|
#private;
|
|
55
55
|
readonly itemTemplate: _angular_core.Signal<TemplateRef<any> | undefined>;
|
|
56
|
-
breadcrumbs$: rxjs.Observable<BreadcrumbItem[]>;
|
|
57
56
|
/**
|
|
58
|
-
* Semantic accent for the breadcrumb links: `'primary'` · `'
|
|
59
|
-
* `'danger'` · `'warning'` · `'info'
|
|
60
|
-
* `--hub-sys-color-<variant>`).
|
|
61
|
-
* current (last) item stays muted.
|
|
57
|
+
* Semantic accent for the breadcrumb links: `'primary'` · `'secondary'` ·
|
|
58
|
+
* `'success'` · `'danger'` · `'warning'` · `'info'` · `'neutral'` · `'light'` ·
|
|
59
|
+
* `'dark'`, or any custom string (read as `--hub-sys-color-<variant>`).
|
|
60
|
+
* Re-bases `--hub-breadcrumb-accent`; the current (last) item stays muted.
|
|
61
|
+
* Defaults to the standard link colour.
|
|
62
62
|
*/
|
|
63
63
|
readonly variant: _angular_core.InputSignal<string | undefined>;
|
|
64
64
|
/**
|
|
@@ -67,6 +67,10 @@ declare class HubBreadcrumbComponent {
|
|
|
67
67
|
* exposes its full text as a tooltip (native `title`, or the hub-ui tooltip
|
|
68
68
|
* when {@link provideHubBreadcrumbTooltip} is wired). Off by default, so the
|
|
69
69
|
* standard breadcrumb layout is unchanged.
|
|
70
|
+
*
|
|
71
|
+
* It reaches a `hubBreadcrumbItem` template as well: the projected elements
|
|
72
|
+
* belong to the consuming component, so the template wraps them in a
|
|
73
|
+
* `span.hub-breadcrumb__custom` of its own and clips that instead.
|
|
70
74
|
*/
|
|
71
75
|
readonly truncateItems: _angular_core.InputSignal<boolean>;
|
|
72
76
|
/**
|
|
@@ -108,8 +112,8 @@ declare class HubBreadcrumbComponent {
|
|
|
108
112
|
/** Rendered positions, with the collapsed range folded into one indicator. */
|
|
109
113
|
protected readonly rows: _angular_core.Signal<BreadcrumbRow[]>;
|
|
110
114
|
/**
|
|
111
|
-
* Inline accent for custom (non-built-in) variants — the built-in
|
|
112
|
-
* resolved by the SCSS `@each` loop, so this returns `null` for them.
|
|
115
|
+
* Inline accent for custom (non-built-in) variants — the nine built-in accents
|
|
116
|
+
* are resolved by the SCSS `@each` loop, so this returns `null` for them.
|
|
113
117
|
*/
|
|
114
118
|
protected readonly customAccent: _angular_core.Signal<string | null>;
|
|
115
119
|
/** Opens a collapsed trail and lets the consumer act on the same gesture. */
|
|
@@ -130,6 +134,13 @@ declare class HubBreadcrumbItemDirective {
|
|
|
130
134
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HubBreadcrumbItemDirective, "[hubBreadcrumbItem]", never, {}, {}, never, never, true, never>;
|
|
131
135
|
}
|
|
132
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Backward-compatibility module for NgModule-based applications.
|
|
139
|
+
*
|
|
140
|
+
* @deprecated Import the standalone `HubBreadcrumbComponent` and `HubBreadcrumbItemDirective`
|
|
141
|
+
* directly; this module only re-exports them and provides nothing of its own. Scheduled for
|
|
142
|
+
* removal in **23.0.0**.
|
|
143
|
+
*/
|
|
133
144
|
declare class HubBreadcrumbsModule {
|
|
134
145
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubBreadcrumbsModule, never>;
|
|
135
146
|
static ɵmod: _angular_core.ɵɵNgModuleDeclaration<HubBreadcrumbsModule, never, [typeof HubBreadcrumbComponent, typeof HubBreadcrumbItemDirective], [typeof HubBreadcrumbComponent, typeof HubBreadcrumbItemDirective]>;
|
|
@@ -196,12 +207,16 @@ declare function provideHubBreadcrumbTooltip(adapter: HubBreadcrumbTooltipAdapte
|
|
|
196
207
|
/**
|
|
197
208
|
* Adds an overflow-aware tooltip to a breadcrumb label element.
|
|
198
209
|
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
* `
|
|
202
|
-
* a tooltip: the native `title` attribute by default, or the richer hub-ui
|
|
210
|
+
* When the label is truncated (its rendered text is wider than its box — typically
|
|
211
|
+
* because `hub-breadcrumb` truncation is enabled), the directive exposes the full
|
|
212
|
+
* text as a tooltip: the native `title` attribute by default, or the richer hub-ui
|
|
203
213
|
* tooltip when a {@link HUB_BREADCRUMB_TOOLTIP_ADAPTER} is provided. When the
|
|
204
214
|
* label fits, no tooltip is shown.
|
|
215
|
+
*
|
|
216
|
+
* `hub-breadcrumb` already applies it to the labels it renders and to the box it
|
|
217
|
+
* wraps a `hubBreadcrumbItem` template in, so applying `[hubBreadcrumbLabel]` by
|
|
218
|
+
* hand is for saying something other than the label — a full path, a spelled-out
|
|
219
|
+
* date — through the directive's own input.
|
|
205
220
|
*/
|
|
206
221
|
declare class HubBreadcrumbLabelDirective implements OnDestroy {
|
|
207
222
|
/**
|
|
@@ -243,7 +258,15 @@ interface BreadcrumbTemplateContext {
|
|
|
243
258
|
|
|
244
259
|
declare class HubBreadcrumbsService {
|
|
245
260
|
#private;
|
|
261
|
+
/** The trail as a stream, for consumers already composing with rxjs. */
|
|
246
262
|
breadcrumbs$: rxjs.Observable<BreadcrumbItem[]>;
|
|
263
|
+
/**
|
|
264
|
+
* The trail as a signal, and the surface the component reads. Published here
|
|
265
|
+
* rather than left to each consumer, because a stream that only ever carries
|
|
266
|
+
* the current trail is one every caller was wrapping in the same `toSignal`
|
|
267
|
+
* — the component included. Wrapped once, subscribed once.
|
|
268
|
+
*/
|
|
269
|
+
readonly breadcrumbs: Signal<BreadcrumbItem[]>;
|
|
247
270
|
private createBreadcrumbs;
|
|
248
271
|
private hasOwnBreadcrumbData;
|
|
249
272
|
/**
|