@cdevhub/ngx-tw 0.2.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/LICENSE +21 -0
- package/README.md +134 -0
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +108 -0
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-alert.mjs +240 -0
- package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +287 -0
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +332 -0
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +452 -0
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-button.mjs +227 -0
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +417 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +232 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +4482 -0
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-card.mjs +157 -0
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +1454 -0
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +593 -0
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +228 -0
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +510 -0
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +1721 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +721 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-core.mjs +861 -0
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +1558 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +1833 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +693 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +331 -0
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +289 -0
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +572 -0
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs +36 -0
- package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +278 -0
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-input.mjs +355 -0
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-item.mjs +241 -0
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +433 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +691 -0
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +678 -0
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +335 -0
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +708 -0
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +319 -0
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs +1722 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-separator.mjs +115 -0
- package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +768 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-skeleton.mjs +149 -0
- package/fesm2022/cdevhub-ngx-tw-skeleton.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +1147 -0
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +346 -0
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-spinner.mjs +186 -0
- package/fesm2022/cdevhub-ngx-tw-spinner.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-split.mjs +1082 -0
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +579 -0
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +443 -0
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +391 -0
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +315 -0
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-table.mjs +994 -0
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +508 -0
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +147 -0
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +178 -0
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +1344 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +1136 -0
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +1311 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +533 -0
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw.mjs +61 -0
- package/fesm2022/cdevhub-ngx-tw.mjs.map +1 -0
- package/package.json +265 -0
- package/theme/_base.css +394 -0
- package/theme/_dark.css +510 -0
- package/theme/_high-contrast.css +290 -0
- package/theme/_semantic.css +317 -0
- package/theme/_typography.css +9 -0
- package/theme/index.css +54 -0
- package/types/cdevhub-ngx-tw-accordion.d.ts +48 -0
- package/types/cdevhub-ngx-tw-alert.d.ts +67 -0
- package/types/cdevhub-ngx-tw-avatar.d.ts +79 -0
- package/types/cdevhub-ngx-tw-badge.d.ts +94 -0
- package/types/cdevhub-ngx-tw-breadcrumbs.d.ts +227 -0
- package/types/cdevhub-ngx-tw-button.d.ts +74 -0
- package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +200 -0
- package/types/cdevhub-ngx-tw-calendar-testing.d.ts +113 -0
- package/types/cdevhub-ngx-tw-calendar.d.ts +1704 -0
- package/types/cdevhub-ngx-tw-card.d.ts +48 -0
- package/types/cdevhub-ngx-tw-carousel.d.ts +406 -0
- package/types/cdevhub-ngx-tw-checkbox.d.ts +136 -0
- package/types/cdevhub-ngx-tw-code-block.d.ts +93 -0
- package/types/cdevhub-ngx-tw-collapsible.d.ts +151 -0
- package/types/cdevhub-ngx-tw-combobox.d.ts +389 -0
- package/types/cdevhub-ngx-tw-command-palette.d.ts +215 -0
- package/types/cdevhub-ngx-tw-core.d.ts +719 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +317 -0
- package/types/cdevhub-ngx-tw-date-range-picker.d.ts +313 -0
- package/types/cdevhub-ngx-tw-dialog.d.ts +303 -0
- package/types/cdevhub-ngx-tw-empty-state.d.ts +104 -0
- package/types/cdevhub-ngx-tw-flip-card.d.ts +95 -0
- package/types/cdevhub-ngx-tw-form-field.d.ts +210 -0
- package/types/cdevhub-ngx-tw-icon-lucide.d.ts +29 -0
- package/types/cdevhub-ngx-tw-icon.d.ts +134 -0
- package/types/cdevhub-ngx-tw-input.d.ts +110 -0
- package/types/cdevhub-ngx-tw-item.d.ts +70 -0
- package/types/cdevhub-ngx-tw-menu.d.ts +99 -0
- package/types/cdevhub-ngx-tw-paginator.d.ts +305 -0
- package/types/cdevhub-ngx-tw-popover.d.ts +157 -0
- package/types/cdevhub-ngx-tw-progress-bar.d.ts +100 -0
- package/types/cdevhub-ngx-tw-radio.d.ts +174 -0
- package/types/cdevhub-ngx-tw-segmented-control.d.ts +66 -0
- package/types/cdevhub-ngx-tw-select.d.ts +384 -0
- package/types/cdevhub-ngx-tw-separator.d.ts +28 -0
- package/types/cdevhub-ngx-tw-sheet.d.ts +335 -0
- package/types/cdevhub-ngx-tw-skeleton.d.ts +52 -0
- package/types/cdevhub-ngx-tw-slider.d.ts +258 -0
- package/types/cdevhub-ngx-tw-sort.d.ts +136 -0
- package/types/cdevhub-ngx-tw-spinner.d.ts +50 -0
- package/types/cdevhub-ngx-tw-split.d.ts +265 -0
- package/types/cdevhub-ngx-tw-stat.d.ts +140 -0
- package/types/cdevhub-ngx-tw-stepper.d.ts +127 -0
- package/types/cdevhub-ngx-tw-switch.d.ts +88 -0
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +107 -0
- package/types/cdevhub-ngx-tw-table.d.ts +479 -0
- package/types/cdevhub-ngx-tw-tabs.d.ts +121 -0
- package/types/cdevhub-ngx-tw-textarea.d.ts +62 -0
- package/types/cdevhub-ngx-tw-theme.d.ts +106 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +303 -0
- package/types/cdevhub-ngx-tw-timeline.d.ts +278 -0
- package/types/cdevhub-ngx-tw-toast.d.ts +388 -0
- package/types/cdevhub-ngx-tw-tooltip.d.ts +95 -0
- package/types/cdevhub-ngx-tw.d.ts +49 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { inject, TemplateRef, Directive, input, forwardRef, computed, contentChild, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
|
+
import { tv } from 'tailwind-variants';
|
|
5
|
+
import { IconComponent } from '@cdevhub/ngx-tw/icon';
|
|
6
|
+
import { MenuComponent, MenuItemDirective, MenuTriggerDirective } from '@cdevhub/ngx-tw/menu';
|
|
7
|
+
|
|
8
|
+
// ── tv() config ──
|
|
9
|
+
const breadcrumbs = tv({
|
|
10
|
+
slots: {
|
|
11
|
+
// The host outer element (<tw-breadcrumbs>) is a custom element; we wrap
|
|
12
|
+
// the actual landmark <nav> inside the template. The list is a real <ol>
|
|
13
|
+
// so the trail keeps its semantic ordering for assistive tech.
|
|
14
|
+
list: 'flex flex-wrap items-center m-0 p-0 list-none min-w-0',
|
|
15
|
+
item: 'inline-flex items-center min-w-0',
|
|
16
|
+
link: 'inline-flex items-center text-fg-muted hover:text-fg transition-colors duration-200 motion-reduce:transition-none ' +
|
|
17
|
+
'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 rounded-md no-underline truncate',
|
|
18
|
+
current: 'inline-flex items-center text-fg font-medium truncate',
|
|
19
|
+
disabled: 'inline-flex items-center text-fg-subtle opacity-50 cursor-not-allowed truncate',
|
|
20
|
+
// Separator carries rtl:rotate-180 so the chevron flips for RTL layouts;
|
|
21
|
+
// requires a `dir="rtl"` ancestor for Tailwind's rtl: variant to match.
|
|
22
|
+
separator: 'inline-flex items-center text-fg-subtle shrink-0 select-none rtl:rotate-180',
|
|
23
|
+
overflowTrigger: 'inline-flex items-center justify-center rounded-md text-fg-muted hover:text-fg hover:bg-surface-muted ' +
|
|
24
|
+
'transition-colors duration-200 motion-reduce:transition-none ' +
|
|
25
|
+
'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 cursor-pointer',
|
|
26
|
+
},
|
|
27
|
+
variants: {
|
|
28
|
+
size: {
|
|
29
|
+
xs: {
|
|
30
|
+
list: 'gap-1',
|
|
31
|
+
link: 'text-xs',
|
|
32
|
+
current: 'text-xs',
|
|
33
|
+
disabled: 'text-xs',
|
|
34
|
+
separator: 'text-xs',
|
|
35
|
+
overflowTrigger: 'size-6 text-xs',
|
|
36
|
+
},
|
|
37
|
+
sm: {
|
|
38
|
+
list: 'gap-1',
|
|
39
|
+
link: 'text-sm',
|
|
40
|
+
current: 'text-sm',
|
|
41
|
+
disabled: 'text-sm',
|
|
42
|
+
separator: 'text-sm',
|
|
43
|
+
overflowTrigger: 'size-7 text-sm',
|
|
44
|
+
},
|
|
45
|
+
md: {
|
|
46
|
+
list: 'gap-1.5',
|
|
47
|
+
link: 'text-sm',
|
|
48
|
+
current: 'text-sm',
|
|
49
|
+
disabled: 'text-sm',
|
|
50
|
+
separator: 'text-sm',
|
|
51
|
+
overflowTrigger: 'size-8 text-sm',
|
|
52
|
+
},
|
|
53
|
+
lg: {
|
|
54
|
+
list: 'gap-2',
|
|
55
|
+
link: 'text-base',
|
|
56
|
+
current: 'text-base',
|
|
57
|
+
disabled: 'text-base',
|
|
58
|
+
separator: 'text-base',
|
|
59
|
+
overflowTrigger: 'size-9 text-base',
|
|
60
|
+
},
|
|
61
|
+
xl: {
|
|
62
|
+
list: 'gap-2',
|
|
63
|
+
link: 'text-base',
|
|
64
|
+
current: 'text-base',
|
|
65
|
+
disabled: 'text-base',
|
|
66
|
+
separator: 'text-base',
|
|
67
|
+
overflowTrigger: 'size-9 text-base',
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
defaultVariants: { size: 'md' },
|
|
72
|
+
}, { twMerge: true });
|
|
73
|
+
// Separator glyph size mirrors the menu-item icon scale: keep the chevron one
|
|
74
|
+
// step below the text-size step so it reads as a quiet hint, not a glyph.
|
|
75
|
+
const ICON_SIZE_FOR_BREADCRUMB = {
|
|
76
|
+
xs: 'xs',
|
|
77
|
+
sm: 'sm',
|
|
78
|
+
md: 'sm',
|
|
79
|
+
lg: 'md',
|
|
80
|
+
xl: 'md',
|
|
81
|
+
};
|
|
82
|
+
// ── Template slot directives ──
|
|
83
|
+
/**
|
|
84
|
+
* Structural directive applied to an `<ng-template>` projected into
|
|
85
|
+
* `tw-breadcrumbs`. Replaces the default per-item rendering so consumers can
|
|
86
|
+
* wire their own anchors (typically `routerLink`-bound). The template receives
|
|
87
|
+
* `$implicit` (the item), `item`, `index`, and `isCurrent` in its context.
|
|
88
|
+
*/
|
|
89
|
+
class BreadcrumbsItemTemplateDirective {
|
|
90
|
+
/** @internal */
|
|
91
|
+
templateRef = inject(TemplateRef);
|
|
92
|
+
/** Type-narrows the template context for `let-` destructuring in templates. */
|
|
93
|
+
static ngTemplateContextGuard(_dir, _ctx) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsItemTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
97
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: BreadcrumbsItemTemplateDirective, isStandalone: true, selector: "[twBreadcrumbsItem]", ngImport: i0 });
|
|
98
|
+
}
|
|
99
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsItemTemplateDirective, decorators: [{
|
|
100
|
+
type: Directive,
|
|
101
|
+
args: [{
|
|
102
|
+
selector: '[twBreadcrumbsItem]',
|
|
103
|
+
}]
|
|
104
|
+
}] });
|
|
105
|
+
/**
|
|
106
|
+
* Structural directive applied to an `<ng-template>` projected into
|
|
107
|
+
* `tw-breadcrumbs`. Replaces the default chevron separator with custom
|
|
108
|
+
* content (any element — icon, text, dot, etc.).
|
|
109
|
+
*/
|
|
110
|
+
class BreadcrumbsSeparatorTemplateDirective {
|
|
111
|
+
/** @internal */
|
|
112
|
+
templateRef = inject(TemplateRef);
|
|
113
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsSeparatorTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
114
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: BreadcrumbsSeparatorTemplateDirective, isStandalone: true, selector: "[twBreadcrumbsSeparator]", ngImport: i0 });
|
|
115
|
+
}
|
|
116
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsSeparatorTemplateDirective, decorators: [{
|
|
117
|
+
type: Directive,
|
|
118
|
+
args: [{
|
|
119
|
+
selector: '[twBreadcrumbsSeparator]',
|
|
120
|
+
}]
|
|
121
|
+
}] });
|
|
122
|
+
// ── Link styling directive ──
|
|
123
|
+
/**
|
|
124
|
+
* Applies the parent `tw-breadcrumbs` link / current / disabled styling to a
|
|
125
|
+
* consumer-projected anchor (or span) inside `*twBreadcrumbsItem`. Without
|
|
126
|
+
* this directive, projected content renders unstyled — only the layout `<li>`
|
|
127
|
+
* is provided by the component.
|
|
128
|
+
*
|
|
129
|
+
* The directive sets `aria-current="page"` when `current` is true. It does
|
|
130
|
+
* NOT itself swap the element tag; the consumer should still pick `<a>` for
|
|
131
|
+
* link items and `<span>` for the current item.
|
|
132
|
+
*/
|
|
133
|
+
class BreadcrumbsLinkDirective {
|
|
134
|
+
/** When true, this element is the current page: styled bold and gets `aria-current="page"`. Defaults to `false`. */
|
|
135
|
+
current = input(false, ...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
|
|
136
|
+
/** When true, applies disabled styling (muted, not-allowed cursor). Defaults to `false`. */
|
|
137
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
138
|
+
parent = inject(forwardRef(() => BreadcrumbsComponent));
|
|
139
|
+
/** @internal Combined classes pulled from the parent component's slot tokens. */
|
|
140
|
+
classes = computed(() => {
|
|
141
|
+
const slots = this.parent.slotResult();
|
|
142
|
+
if (this.disabled())
|
|
143
|
+
return slots.disabled();
|
|
144
|
+
if (this.current())
|
|
145
|
+
return slots.current();
|
|
146
|
+
return slots.link();
|
|
147
|
+
}, ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
148
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsLinkDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
149
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.14", type: BreadcrumbsLinkDirective, isStandalone: true, selector: "[twBreadcrumbsLink]", inputs: { current: { classPropertyName: "current", publicName: "current", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.aria-current": "current() ? \"page\" : null" } }, ngImport: i0 });
|
|
150
|
+
}
|
|
151
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsLinkDirective, decorators: [{
|
|
152
|
+
type: Directive,
|
|
153
|
+
args: [{
|
|
154
|
+
selector: '[twBreadcrumbsLink]',
|
|
155
|
+
host: {
|
|
156
|
+
'[class]': 'classes()',
|
|
157
|
+
'[attr.aria-current]': 'current() ? "page" : null',
|
|
158
|
+
},
|
|
159
|
+
}]
|
|
160
|
+
}], propDecorators: { current: [{ type: i0.Input, args: [{ isSignal: true, alias: "current", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
161
|
+
// ── BreadcrumbsComponent ──
|
|
162
|
+
/**
|
|
163
|
+
* Breadcrumb trail rendered as a `<nav>` landmark with an ordered list of
|
|
164
|
+
* navigation hops. The last entry in `items` is the current page (gets
|
|
165
|
+
* `aria-current="page"`, never an anchor). Items beyond `maxItems` are
|
|
166
|
+
* collapsed behind an ellipsis trigger that opens an overflow menu.
|
|
167
|
+
*
|
|
168
|
+
* Customize per-item rendering with `*twBreadcrumbsItem` (consumer projects
|
|
169
|
+
* router-aware anchors), and the separator with `*twBreadcrumbsSeparator` or
|
|
170
|
+
* the `separator` input (Lucide icon name).
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```html
|
|
174
|
+
* <tw-breadcrumbs [items]="trail" />
|
|
175
|
+
*
|
|
176
|
+
* <tw-breadcrumbs [items]="trail" [maxItems]="3" separator="slash">
|
|
177
|
+
* <ng-template twBreadcrumbsItem let-item let-isCurrent="isCurrent">
|
|
178
|
+
* @if (isCurrent) {
|
|
179
|
+
* <span twBreadcrumbsLink [current]="true">{{ item.label }}</span>
|
|
180
|
+
* } @else {
|
|
181
|
+
* <a twBreadcrumbsLink [routerLink]="item.data?.routerLink">{{ item.label }}</a>
|
|
182
|
+
* }
|
|
183
|
+
* </ng-template>
|
|
184
|
+
* </tw-breadcrumbs>
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
class BreadcrumbsComponent {
|
|
188
|
+
/** The full breadcrumb trail. The last entry is treated as the current page. Defaults to `[]`. */
|
|
189
|
+
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
190
|
+
/** Density of the trail — drives font size, gap, icon size, and the overflow-button square. Defaults to `'md'`. */
|
|
191
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
192
|
+
/**
|
|
193
|
+
* When greater than `0`, the trail collapses any middle items past this
|
|
194
|
+
* threshold behind an overflow menu. The first item and the current (last)
|
|
195
|
+
* item are always visible. Values `< 2` are clamped to `2`. Defaults to `0`
|
|
196
|
+
* (no collapsing).
|
|
197
|
+
*/
|
|
198
|
+
maxItems = input(0, ...(ngDevMode ? [{ debugName: "maxItems" }] : /* istanbul ignore next */ []));
|
|
199
|
+
/**
|
|
200
|
+
* Lucide icon name used for the default separator between items. Ignored
|
|
201
|
+
* when a `*twBreadcrumbsSeparator` template is projected. Defaults to
|
|
202
|
+
* `'chevron-right'`. Requires the consumer to register the icon via
|
|
203
|
+
* `provideTwLucideIcons({ ChevronRight, ... })`.
|
|
204
|
+
*/
|
|
205
|
+
separator = input('chevron-right', ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
|
|
206
|
+
/** Accessible label applied to the `<nav>` landmark. Defaults to `'Breadcrumb'`. Aliased as `aria-label`. */
|
|
207
|
+
ariaLabel = input('Breadcrumb', { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
208
|
+
/** Custom per-item template projected via `*twBreadcrumbsItem`. */
|
|
209
|
+
itemTemplate = contentChild((BreadcrumbsItemTemplateDirective), ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
210
|
+
/** Custom separator template projected via `*twBreadcrumbsSeparator`. */
|
|
211
|
+
separatorTemplate = contentChild(BreadcrumbsSeparatorTemplateDirective, ...(ngDevMode ? [{ debugName: "separatorTemplate" }] : /* istanbul ignore next */ []));
|
|
212
|
+
/** @internal Materialised tv() slot result; exposed so `BreadcrumbsLinkDirective` can pull link/current/disabled classes. */
|
|
213
|
+
slotResult = computed(() => breadcrumbs({ size: this.size() }), ...(ngDevMode ? [{ debugName: "slotResult" }] : /* istanbul ignore next */ []));
|
|
214
|
+
/** @internal Icon size for the default chevron separator. */
|
|
215
|
+
iconSize = computed(() => ICON_SIZE_FOR_BREADCRUMB[this.size()], ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
216
|
+
/** @internal Class strings per slot, memoised. */
|
|
217
|
+
listClasses = computed(() => this.slotResult().list(), ...(ngDevMode ? [{ debugName: "listClasses" }] : /* istanbul ignore next */ []));
|
|
218
|
+
itemClasses = computed(() => this.slotResult().item(), ...(ngDevMode ? [{ debugName: "itemClasses" }] : /* istanbul ignore next */ []));
|
|
219
|
+
linkClasses = computed(() => this.slotResult().link(), ...(ngDevMode ? [{ debugName: "linkClasses" }] : /* istanbul ignore next */ []));
|
|
220
|
+
currentClasses = computed(() => this.slotResult().current(), ...(ngDevMode ? [{ debugName: "currentClasses" }] : /* istanbul ignore next */ []));
|
|
221
|
+
disabledClasses = computed(() => this.slotResult().disabled(), ...(ngDevMode ? [{ debugName: "disabledClasses" }] : /* istanbul ignore next */ []));
|
|
222
|
+
separatorClasses = computed(() => this.slotResult().separator(), ...(ngDevMode ? [{ debugName: "separatorClasses" }] : /* istanbul ignore next */ []));
|
|
223
|
+
overflowTriggerClasses = computed(() => this.slotResult().overflowTrigger(), ...(ngDevMode ? [{ debugName: "overflowTriggerClasses" }] : /* istanbul ignore next */ []));
|
|
224
|
+
/** @internal Items hidden behind the overflow menu. Empty when no collapsing is active. */
|
|
225
|
+
collapsedItems = computed(() => {
|
|
226
|
+
const all = this.items();
|
|
227
|
+
const max = this.maxItems();
|
|
228
|
+
if (max <= 0 || all.length <= 2 || all.length <= max)
|
|
229
|
+
return [];
|
|
230
|
+
const effectiveMax = Math.max(max, 2);
|
|
231
|
+
if (all.length <= effectiveMax)
|
|
232
|
+
return [];
|
|
233
|
+
const tailCount = effectiveMax - 1;
|
|
234
|
+
const hiddenEnd = all.length - tailCount;
|
|
235
|
+
return all.slice(1, hiddenEnd);
|
|
236
|
+
}, ...(ngDevMode ? [{ debugName: "collapsedItems" }] : /* istanbul ignore next */ []));
|
|
237
|
+
/** @internal Flat sequence of items + separators + overflow used by the template's @for. */
|
|
238
|
+
renderedEntries = computed(() => {
|
|
239
|
+
const all = this.items();
|
|
240
|
+
const max = this.maxItems();
|
|
241
|
+
if (all.length === 0)
|
|
242
|
+
return [];
|
|
243
|
+
const entries = [];
|
|
244
|
+
const lastIndex = all.length - 1;
|
|
245
|
+
const pushSeparator = (key) => entries.push({ kind: 'separator', key: `sep-${key}` });
|
|
246
|
+
const collapsing = max > 0 && all.length > 2 && all.length > max;
|
|
247
|
+
const effectiveMax = Math.max(max, 2);
|
|
248
|
+
const shouldCollapse = collapsing && all.length > effectiveMax;
|
|
249
|
+
if (!shouldCollapse) {
|
|
250
|
+
for (let i = 0; i < all.length; i++) {
|
|
251
|
+
if (i > 0)
|
|
252
|
+
pushSeparator(`${i}`);
|
|
253
|
+
entries.push({
|
|
254
|
+
kind: 'item',
|
|
255
|
+
item: all[i],
|
|
256
|
+
index: i,
|
|
257
|
+
isCurrent: i === lastIndex,
|
|
258
|
+
key: `item-${i}`,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
return entries;
|
|
262
|
+
}
|
|
263
|
+
const tailCount = effectiveMax - 1;
|
|
264
|
+
const tailStart = all.length - tailCount;
|
|
265
|
+
// First item.
|
|
266
|
+
entries.push({
|
|
267
|
+
kind: 'item',
|
|
268
|
+
item: all[0],
|
|
269
|
+
index: 0,
|
|
270
|
+
isCurrent: lastIndex === 0,
|
|
271
|
+
key: 'item-0',
|
|
272
|
+
});
|
|
273
|
+
pushSeparator('after-first');
|
|
274
|
+
// Overflow trigger.
|
|
275
|
+
entries.push({ kind: 'overflow', key: 'overflow' });
|
|
276
|
+
pushSeparator('after-overflow');
|
|
277
|
+
// Tail items.
|
|
278
|
+
for (let i = tailStart; i < all.length; i++) {
|
|
279
|
+
if (i > tailStart)
|
|
280
|
+
pushSeparator(`${i}`);
|
|
281
|
+
entries.push({
|
|
282
|
+
kind: 'item',
|
|
283
|
+
item: all[i],
|
|
284
|
+
index: i,
|
|
285
|
+
isCurrent: i === lastIndex,
|
|
286
|
+
key: `item-${i}`,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
return entries;
|
|
290
|
+
}, ...(ngDevMode ? [{ debugName: "renderedEntries" }] : /* istanbul ignore next */ []));
|
|
291
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
292
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: BreadcrumbsComponent, isStandalone: true, selector: "tw-breadcrumbs", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, maxItems: { classPropertyName: "maxItems", publicName: "maxItems", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block min-w-0" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: (BreadcrumbsItemTemplateDirective), descendants: true, isSignal: true }, { propertyName: "separatorTemplate", first: true, predicate: BreadcrumbsSeparatorTemplateDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
293
|
+
<nav [attr.aria-label]="ariaLabel()">
|
|
294
|
+
<ol [class]="listClasses()">
|
|
295
|
+
@for (entry of renderedEntries(); track entry.key) {
|
|
296
|
+
@if (entry.kind === 'item') {
|
|
297
|
+
<li [class]="itemClasses()">
|
|
298
|
+
@if (itemTemplate(); as tpl) {
|
|
299
|
+
<ng-container
|
|
300
|
+
*ngTemplateOutlet="
|
|
301
|
+
tpl.templateRef;
|
|
302
|
+
context: {
|
|
303
|
+
$implicit: entry.item,
|
|
304
|
+
item: entry.item,
|
|
305
|
+
index: entry.index,
|
|
306
|
+
isCurrent: entry.isCurrent
|
|
307
|
+
}
|
|
308
|
+
"
|
|
309
|
+
/>
|
|
310
|
+
} @else {
|
|
311
|
+
@if (entry.isCurrent) {
|
|
312
|
+
<span [class]="currentClasses()" aria-current="page">{{ entry.item.label }}</span>
|
|
313
|
+
} @else if (entry.item.disabled) {
|
|
314
|
+
<span [class]="disabledClasses()" aria-disabled="true">{{ entry.item.label }}</span>
|
|
315
|
+
} @else if (entry.item.href) {
|
|
316
|
+
<a [class]="linkClasses()" [attr.href]="entry.item.href">{{ entry.item.label }}</a>
|
|
317
|
+
} @else {
|
|
318
|
+
<span [class]="linkClasses()">{{ entry.item.label }}</span>
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
</li>
|
|
322
|
+
} @else if (entry.kind === 'separator') {
|
|
323
|
+
<li [class]="separatorClasses()" aria-hidden="true">
|
|
324
|
+
@if (separatorTemplate(); as sepTpl) {
|
|
325
|
+
<ng-container *ngTemplateOutlet="sepTpl.templateRef" />
|
|
326
|
+
} @else {
|
|
327
|
+
<tw-icon [name]="separator()" [size]="iconSize()" />
|
|
328
|
+
}
|
|
329
|
+
</li>
|
|
330
|
+
} @else {
|
|
331
|
+
<li [class]="itemClasses()">
|
|
332
|
+
<button
|
|
333
|
+
type="button"
|
|
334
|
+
[class]="overflowTriggerClasses()"
|
|
335
|
+
[twMenuTrigger]="overflowMenuTpl"
|
|
336
|
+
aria-label="Show more breadcrumbs"
|
|
337
|
+
>
|
|
338
|
+
<span aria-hidden="true">…</span>
|
|
339
|
+
</button>
|
|
340
|
+
<ng-template #overflowMenuTpl>
|
|
341
|
+
<tw-menu aria-label="Hidden breadcrumb items">
|
|
342
|
+
@for (hidden of collapsedItems(); track hidden) {
|
|
343
|
+
@if (hidden.disabled || !hidden.href) {
|
|
344
|
+
<span twMenuItem [attr.aria-disabled]="hidden.disabled ? 'true' : null">
|
|
345
|
+
{{ hidden.label }}
|
|
346
|
+
</span>
|
|
347
|
+
} @else {
|
|
348
|
+
<a twMenuItem [attr.href]="hidden.href">{{ hidden.label }}</a>
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
</tw-menu>
|
|
352
|
+
</ng-template>
|
|
353
|
+
</li>
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
</ol>
|
|
357
|
+
</nav>
|
|
358
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconComponent, selector: "tw-icon", inputs: ["name", "img", "color", "size", "ariaLabel", "svg"] }, { kind: "component", type: MenuComponent, selector: "tw-menu", inputs: ["size", "aria-label", "aria-labelledby"] }, { kind: "directive", type: MenuItemDirective, selector: "[twMenuItem]", inputs: ["color", "disabled"] }, { kind: "directive", type: MenuTriggerDirective, selector: "[twMenuTrigger]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
359
|
+
}
|
|
360
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: BreadcrumbsComponent, decorators: [{
|
|
361
|
+
type: Component,
|
|
362
|
+
args: [{
|
|
363
|
+
selector: 'tw-breadcrumbs',
|
|
364
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
365
|
+
imports: [
|
|
366
|
+
NgTemplateOutlet,
|
|
367
|
+
IconComponent,
|
|
368
|
+
MenuComponent,
|
|
369
|
+
MenuItemDirective,
|
|
370
|
+
MenuTriggerDirective,
|
|
371
|
+
],
|
|
372
|
+
host: {
|
|
373
|
+
// Custom elements default to inline; force a block layout so the trail
|
|
374
|
+
// behaves predictably inside flex / grid containers.
|
|
375
|
+
class: 'block min-w-0',
|
|
376
|
+
},
|
|
377
|
+
template: `
|
|
378
|
+
<nav [attr.aria-label]="ariaLabel()">
|
|
379
|
+
<ol [class]="listClasses()">
|
|
380
|
+
@for (entry of renderedEntries(); track entry.key) {
|
|
381
|
+
@if (entry.kind === 'item') {
|
|
382
|
+
<li [class]="itemClasses()">
|
|
383
|
+
@if (itemTemplate(); as tpl) {
|
|
384
|
+
<ng-container
|
|
385
|
+
*ngTemplateOutlet="
|
|
386
|
+
tpl.templateRef;
|
|
387
|
+
context: {
|
|
388
|
+
$implicit: entry.item,
|
|
389
|
+
item: entry.item,
|
|
390
|
+
index: entry.index,
|
|
391
|
+
isCurrent: entry.isCurrent
|
|
392
|
+
}
|
|
393
|
+
"
|
|
394
|
+
/>
|
|
395
|
+
} @else {
|
|
396
|
+
@if (entry.isCurrent) {
|
|
397
|
+
<span [class]="currentClasses()" aria-current="page">{{ entry.item.label }}</span>
|
|
398
|
+
} @else if (entry.item.disabled) {
|
|
399
|
+
<span [class]="disabledClasses()" aria-disabled="true">{{ entry.item.label }}</span>
|
|
400
|
+
} @else if (entry.item.href) {
|
|
401
|
+
<a [class]="linkClasses()" [attr.href]="entry.item.href">{{ entry.item.label }}</a>
|
|
402
|
+
} @else {
|
|
403
|
+
<span [class]="linkClasses()">{{ entry.item.label }}</span>
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
</li>
|
|
407
|
+
} @else if (entry.kind === 'separator') {
|
|
408
|
+
<li [class]="separatorClasses()" aria-hidden="true">
|
|
409
|
+
@if (separatorTemplate(); as sepTpl) {
|
|
410
|
+
<ng-container *ngTemplateOutlet="sepTpl.templateRef" />
|
|
411
|
+
} @else {
|
|
412
|
+
<tw-icon [name]="separator()" [size]="iconSize()" />
|
|
413
|
+
}
|
|
414
|
+
</li>
|
|
415
|
+
} @else {
|
|
416
|
+
<li [class]="itemClasses()">
|
|
417
|
+
<button
|
|
418
|
+
type="button"
|
|
419
|
+
[class]="overflowTriggerClasses()"
|
|
420
|
+
[twMenuTrigger]="overflowMenuTpl"
|
|
421
|
+
aria-label="Show more breadcrumbs"
|
|
422
|
+
>
|
|
423
|
+
<span aria-hidden="true">…</span>
|
|
424
|
+
</button>
|
|
425
|
+
<ng-template #overflowMenuTpl>
|
|
426
|
+
<tw-menu aria-label="Hidden breadcrumb items">
|
|
427
|
+
@for (hidden of collapsedItems(); track hidden) {
|
|
428
|
+
@if (hidden.disabled || !hidden.href) {
|
|
429
|
+
<span twMenuItem [attr.aria-disabled]="hidden.disabled ? 'true' : null">
|
|
430
|
+
{{ hidden.label }}
|
|
431
|
+
</span>
|
|
432
|
+
} @else {
|
|
433
|
+
<a twMenuItem [attr.href]="hidden.href">{{ hidden.label }}</a>
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
</tw-menu>
|
|
437
|
+
</ng-template>
|
|
438
|
+
</li>
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
</ol>
|
|
442
|
+
</nav>
|
|
443
|
+
`,
|
|
444
|
+
}]
|
|
445
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], maxItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxItems", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BreadcrumbsItemTemplateDirective), { isSignal: true }] }], separatorTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BreadcrumbsSeparatorTemplateDirective), { isSignal: true }] }] } });
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Generated bundle index. Do not edit.
|
|
449
|
+
*/
|
|
450
|
+
|
|
451
|
+
export { BreadcrumbsComponent, BreadcrumbsItemTemplateDirective, BreadcrumbsLinkDirective, BreadcrumbsSeparatorTemplateDirective };
|
|
452
|
+
//# sourceMappingURL=cdevhub-ngx-tw-breadcrumbs.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdevhub-ngx-tw-breadcrumbs.mjs","sources":["../../../projects/ngx-tw/breadcrumbs/breadcrumbs.ts","../../../projects/ngx-tw/breadcrumbs/cdevhub-ngx-tw-breadcrumbs.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n Directive,\n TemplateRef,\n computed,\n contentChild,\n forwardRef,\n inject,\n input,\n} from '@angular/core';\nimport { tv } from 'tailwind-variants';\nimport type { TwSize } from '@cdevhub/ngx-tw/core';\nimport { IconComponent } from '@cdevhub/ngx-tw/icon';\nimport {\n MenuComponent,\n MenuItemDirective,\n MenuTriggerDirective,\n} from '@cdevhub/ngx-tw/menu';\n\n// ── Public types ──\n\n/**\n * Describes a single hop in a breadcrumb trail. The last entry in `items` is\n * always treated as the current page (rendered with `aria-current=\"page\"`,\n * never as an anchor).\n *\n * The generic `T` types the optional `data` payload — useful for forwarding\n * routerLink commands or any other consumer-defined metadata to the custom\n * item template without unsafe casts.\n */\nexport interface TwBreadcrumbsItem<T = unknown> {\n /** Visible label shown for this hop. */\n label: string;\n /**\n * Optional href used to render the default anchor. Omit on the current item\n * (the last entry). Ignored when a custom `*twBreadcrumbsItem` template is\n * projected — the consumer owns the anchor in that case.\n */\n href?: string;\n /**\n * Opaque payload forwarded to the consumer's `*twBreadcrumbsItem` template\n * via the template context. Use this to carry router commands or any other\n * data your template needs.\n */\n data?: T;\n /**\n * When true, the item renders as muted text without an anchor (even if\n * `href` is set). Receives `aria-disabled=\"true\"`.\n */\n disabled?: boolean;\n}\n\n/**\n * Template context passed to `*twBreadcrumbsItem` for each rendered item.\n */\nexport interface TwBreadcrumbsItemContext<T = unknown> {\n /** The item record (also exposed via `let-item=\"$implicit\"`). */\n $implicit: TwBreadcrumbsItem<T>;\n /** Same as `$implicit`. Available via `let-item=\"item\"` for readability. */\n item: TwBreadcrumbsItem<T>;\n /** Zero-based index of this item in the original `items` input. */\n index: number;\n /** `true` only for the last entry — the current page. */\n isCurrent: boolean;\n}\n\n// ── tv() config ──\n\nconst breadcrumbs = tv(\n {\n slots: {\n // The host outer element (<tw-breadcrumbs>) is a custom element; we wrap\n // the actual landmark <nav> inside the template. The list is a real <ol>\n // so the trail keeps its semantic ordering for assistive tech.\n list: 'flex flex-wrap items-center m-0 p-0 list-none min-w-0',\n item: 'inline-flex items-center min-w-0',\n link:\n 'inline-flex items-center text-fg-muted hover:text-fg transition-colors duration-200 motion-reduce:transition-none ' +\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 rounded-md no-underline truncate',\n current: 'inline-flex items-center text-fg font-medium truncate',\n disabled:\n 'inline-flex items-center text-fg-subtle opacity-50 cursor-not-allowed truncate',\n // Separator carries rtl:rotate-180 so the chevron flips for RTL layouts;\n // requires a `dir=\"rtl\"` ancestor for Tailwind's rtl: variant to match.\n separator:\n 'inline-flex items-center text-fg-subtle shrink-0 select-none rtl:rotate-180',\n overflowTrigger:\n 'inline-flex items-center justify-center rounded-md text-fg-muted hover:text-fg hover:bg-surface-muted ' +\n 'transition-colors duration-200 motion-reduce:transition-none ' +\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500 cursor-pointer',\n },\n variants: {\n size: {\n xs: {\n list: 'gap-1',\n link: 'text-xs',\n current: 'text-xs',\n disabled: 'text-xs',\n separator: 'text-xs',\n overflowTrigger: 'size-6 text-xs',\n },\n sm: {\n list: 'gap-1',\n link: 'text-sm',\n current: 'text-sm',\n disabled: 'text-sm',\n separator: 'text-sm',\n overflowTrigger: 'size-7 text-sm',\n },\n md: {\n list: 'gap-1.5',\n link: 'text-sm',\n current: 'text-sm',\n disabled: 'text-sm',\n separator: 'text-sm',\n overflowTrigger: 'size-8 text-sm',\n },\n lg: {\n list: 'gap-2',\n link: 'text-base',\n current: 'text-base',\n disabled: 'text-base',\n separator: 'text-base',\n overflowTrigger: 'size-9 text-base',\n },\n xl: {\n list: 'gap-2',\n link: 'text-base',\n current: 'text-base',\n disabled: 'text-base',\n separator: 'text-base',\n overflowTrigger: 'size-9 text-base',\n },\n },\n },\n defaultVariants: { size: 'md' },\n },\n { twMerge: true },\n);\n\n// Separator glyph size mirrors the menu-item icon scale: keep the chevron one\n// step below the text-size step so it reads as a quiet hint, not a glyph.\nconst ICON_SIZE_FOR_BREADCRUMB: Record<TwSize, TwSize> = {\n xs: 'xs',\n sm: 'sm',\n md: 'sm',\n lg: 'md',\n xl: 'md',\n};\n\n// ── Template slot directives ──\n\n/**\n * Structural directive applied to an `<ng-template>` projected into\n * `tw-breadcrumbs`. Replaces the default per-item rendering so consumers can\n * wire their own anchors (typically `routerLink`-bound). The template receives\n * `$implicit` (the item), `item`, `index`, and `isCurrent` in its context.\n */\n@Directive({\n selector: '[twBreadcrumbsItem]',\n})\nexport class BreadcrumbsItemTemplateDirective<T = unknown> {\n /** @internal */\n readonly templateRef = inject<TemplateRef<TwBreadcrumbsItemContext<T>>>(TemplateRef);\n\n /** Type-narrows the template context for `let-` destructuring in templates. */\n static ngTemplateContextGuard<T>(\n _dir: BreadcrumbsItemTemplateDirective<T>,\n _ctx: unknown,\n ): _ctx is TwBreadcrumbsItemContext<T> {\n return true;\n }\n}\n\n/**\n * Structural directive applied to an `<ng-template>` projected into\n * `tw-breadcrumbs`. Replaces the default chevron separator with custom\n * content (any element — icon, text, dot, etc.).\n */\n@Directive({\n selector: '[twBreadcrumbsSeparator]',\n})\nexport class BreadcrumbsSeparatorTemplateDirective {\n /** @internal */\n readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);\n}\n\n// ── Link styling directive ──\n\n/**\n * Applies the parent `tw-breadcrumbs` link / current / disabled styling to a\n * consumer-projected anchor (or span) inside `*twBreadcrumbsItem`. Without\n * this directive, projected content renders unstyled — only the layout `<li>`\n * is provided by the component.\n *\n * The directive sets `aria-current=\"page\"` when `current` is true. It does\n * NOT itself swap the element tag; the consumer should still pick `<a>` for\n * link items and `<span>` for the current item.\n */\n@Directive({\n selector: '[twBreadcrumbsLink]',\n host: {\n '[class]': 'classes()',\n '[attr.aria-current]': 'current() ? \"page\" : null',\n },\n})\nexport class BreadcrumbsLinkDirective {\n /** When true, this element is the current page: styled bold and gets `aria-current=\"page\"`. Defaults to `false`. */\n readonly current = input(false);\n\n /** When true, applies disabled styling (muted, not-allowed cursor). Defaults to `false`. */\n readonly disabled = input(false);\n\n private readonly parent = inject<BreadcrumbsComponent<unknown>>(\n forwardRef(() => BreadcrumbsComponent),\n );\n\n /** @internal Combined classes pulled from the parent component's slot tokens. */\n readonly classes = computed(() => {\n const slots = this.parent.slotResult();\n if (this.disabled()) return slots.disabled();\n if (this.current()) return slots.current();\n return slots.link();\n });\n}\n\n// ── Rendered entry types (internal) ──\n\ninterface RenderedItem<T> {\n readonly kind: 'item';\n readonly item: TwBreadcrumbsItem<T>;\n readonly index: number;\n readonly isCurrent: boolean;\n readonly key: string;\n}\n\ninterface RenderedSeparator {\n readonly kind: 'separator';\n readonly key: string;\n}\n\ninterface RenderedOverflow {\n readonly kind: 'overflow';\n readonly key: string;\n}\n\ntype RenderedEntry<T> = RenderedItem<T> | RenderedSeparator | RenderedOverflow;\n\n// ── BreadcrumbsComponent ──\n\n/**\n * Breadcrumb trail rendered as a `<nav>` landmark with an ordered list of\n * navigation hops. The last entry in `items` is the current page (gets\n * `aria-current=\"page\"`, never an anchor). Items beyond `maxItems` are\n * collapsed behind an ellipsis trigger that opens an overflow menu.\n *\n * Customize per-item rendering with `*twBreadcrumbsItem` (consumer projects\n * router-aware anchors), and the separator with `*twBreadcrumbsSeparator` or\n * the `separator` input (Lucide icon name).\n *\n * @example\n * ```html\n * <tw-breadcrumbs [items]=\"trail\" />\n *\n * <tw-breadcrumbs [items]=\"trail\" [maxItems]=\"3\" separator=\"slash\">\n * <ng-template twBreadcrumbsItem let-item let-isCurrent=\"isCurrent\">\n * @if (isCurrent) {\n * <span twBreadcrumbsLink [current]=\"true\">{{ item.label }}</span>\n * } @else {\n * <a twBreadcrumbsLink [routerLink]=\"item.data?.routerLink\">{{ item.label }}</a>\n * }\n * </ng-template>\n * </tw-breadcrumbs>\n * ```\n */\n@Component({\n selector: 'tw-breadcrumbs',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [\n NgTemplateOutlet,\n IconComponent,\n MenuComponent,\n MenuItemDirective,\n MenuTriggerDirective,\n ],\n host: {\n // Custom elements default to inline; force a block layout so the trail\n // behaves predictably inside flex / grid containers.\n class: 'block min-w-0',\n },\n template: `\n <nav [attr.aria-label]=\"ariaLabel()\">\n <ol [class]=\"listClasses()\">\n @for (entry of renderedEntries(); track entry.key) {\n @if (entry.kind === 'item') {\n <li [class]=\"itemClasses()\">\n @if (itemTemplate(); as tpl) {\n <ng-container\n *ngTemplateOutlet=\"\n tpl.templateRef;\n context: {\n $implicit: entry.item,\n item: entry.item,\n index: entry.index,\n isCurrent: entry.isCurrent\n }\n \"\n />\n } @else {\n @if (entry.isCurrent) {\n <span [class]=\"currentClasses()\" aria-current=\"page\">{{ entry.item.label }}</span>\n } @else if (entry.item.disabled) {\n <span [class]=\"disabledClasses()\" aria-disabled=\"true\">{{ entry.item.label }}</span>\n } @else if (entry.item.href) {\n <a [class]=\"linkClasses()\" [attr.href]=\"entry.item.href\">{{ entry.item.label }}</a>\n } @else {\n <span [class]=\"linkClasses()\">{{ entry.item.label }}</span>\n }\n }\n </li>\n } @else if (entry.kind === 'separator') {\n <li [class]=\"separatorClasses()\" aria-hidden=\"true\">\n @if (separatorTemplate(); as sepTpl) {\n <ng-container *ngTemplateOutlet=\"sepTpl.templateRef\" />\n } @else {\n <tw-icon [name]=\"separator()\" [size]=\"iconSize()\" />\n }\n </li>\n } @else {\n <li [class]=\"itemClasses()\">\n <button\n type=\"button\"\n [class]=\"overflowTriggerClasses()\"\n [twMenuTrigger]=\"overflowMenuTpl\"\n aria-label=\"Show more breadcrumbs\"\n >\n <span aria-hidden=\"true\">…</span>\n </button>\n <ng-template #overflowMenuTpl>\n <tw-menu aria-label=\"Hidden breadcrumb items\">\n @for (hidden of collapsedItems(); track hidden) {\n @if (hidden.disabled || !hidden.href) {\n <span twMenuItem [attr.aria-disabled]=\"hidden.disabled ? 'true' : null\">\n {{ hidden.label }}\n </span>\n } @else {\n <a twMenuItem [attr.href]=\"hidden.href\">{{ hidden.label }}</a>\n }\n }\n </tw-menu>\n </ng-template>\n </li>\n }\n }\n </ol>\n </nav>\n `,\n})\nexport class BreadcrumbsComponent<T = unknown> {\n /** The full breadcrumb trail. The last entry is treated as the current page. Defaults to `[]`. */\n readonly items = input<readonly TwBreadcrumbsItem<T>[]>([]);\n\n /** Density of the trail — drives font size, gap, icon size, and the overflow-button square. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /**\n * When greater than `0`, the trail collapses any middle items past this\n * threshold behind an overflow menu. The first item and the current (last)\n * item are always visible. Values `< 2` are clamped to `2`. Defaults to `0`\n * (no collapsing).\n */\n readonly maxItems = input<number>(0);\n\n /**\n * Lucide icon name used for the default separator between items. Ignored\n * when a `*twBreadcrumbsSeparator` template is projected. Defaults to\n * `'chevron-right'`. Requires the consumer to register the icon via\n * `provideTwLucideIcons({ ChevronRight, ... })`.\n */\n readonly separator = input<string>('chevron-right');\n\n /** Accessible label applied to the `<nav>` landmark. Defaults to `'Breadcrumb'`. Aliased as `aria-label`. */\n readonly ariaLabel = input<string>('Breadcrumb', { alias: 'aria-label' });\n\n /** Custom per-item template projected via `*twBreadcrumbsItem`. */\n readonly itemTemplate = contentChild(BreadcrumbsItemTemplateDirective<T>);\n\n /** Custom separator template projected via `*twBreadcrumbsSeparator`. */\n readonly separatorTemplate = contentChild(BreadcrumbsSeparatorTemplateDirective);\n\n /** @internal Materialised tv() slot result; exposed so `BreadcrumbsLinkDirective` can pull link/current/disabled classes. */\n readonly slotResult = computed(() => breadcrumbs({ size: this.size() }));\n\n /** @internal Icon size for the default chevron separator. */\n readonly iconSize = computed(() => ICON_SIZE_FOR_BREADCRUMB[this.size()]);\n\n /** @internal Class strings per slot, memoised. */\n readonly listClasses = computed(() => this.slotResult().list());\n readonly itemClasses = computed(() => this.slotResult().item());\n readonly linkClasses = computed(() => this.slotResult().link());\n readonly currentClasses = computed(() => this.slotResult().current());\n readonly disabledClasses = computed(() => this.slotResult().disabled());\n readonly separatorClasses = computed(() => this.slotResult().separator());\n readonly overflowTriggerClasses = computed(() => this.slotResult().overflowTrigger());\n\n /** @internal Items hidden behind the overflow menu. Empty when no collapsing is active. */\n readonly collapsedItems = computed<readonly TwBreadcrumbsItem<T>[]>(() => {\n const all = this.items();\n const max = this.maxItems();\n if (max <= 0 || all.length <= 2 || all.length <= max) return [];\n const effectiveMax = Math.max(max, 2);\n if (all.length <= effectiveMax) return [];\n const tailCount = effectiveMax - 1;\n const hiddenEnd = all.length - tailCount;\n return all.slice(1, hiddenEnd);\n });\n\n /** @internal Flat sequence of items + separators + overflow used by the template's @for. */\n readonly renderedEntries = computed<RenderedEntry<T>[]>(() => {\n const all = this.items();\n const max = this.maxItems();\n if (all.length === 0) return [];\n\n const entries: RenderedEntry<T>[] = [];\n const lastIndex = all.length - 1;\n const pushSeparator = (key: string) =>\n entries.push({ kind: 'separator', key: `sep-${key}` });\n\n const collapsing = max > 0 && all.length > 2 && all.length > max;\n const effectiveMax = Math.max(max, 2);\n const shouldCollapse = collapsing && all.length > effectiveMax;\n\n if (!shouldCollapse) {\n for (let i = 0; i < all.length; i++) {\n if (i > 0) pushSeparator(`${i}`);\n entries.push({\n kind: 'item',\n item: all[i],\n index: i,\n isCurrent: i === lastIndex,\n key: `item-${i}`,\n });\n }\n return entries;\n }\n\n const tailCount = effectiveMax - 1;\n const tailStart = all.length - tailCount;\n\n // First item.\n entries.push({\n kind: 'item',\n item: all[0],\n index: 0,\n isCurrent: lastIndex === 0,\n key: 'item-0',\n });\n pushSeparator('after-first');\n\n // Overflow trigger.\n entries.push({ kind: 'overflow', key: 'overflow' });\n pushSeparator('after-overflow');\n\n // Tail items.\n for (let i = tailStart; i < all.length; i++) {\n if (i > tailStart) pushSeparator(`${i}`);\n entries.push({\n kind: 'item',\n item: all[i],\n index: i,\n isCurrent: i === lastIndex,\n key: `item-${i}`,\n });\n }\n\n return entries;\n });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|