@ojiepermana/angular-navigation 22.0.44 → 22.0.46
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 +9 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-dockbar-menu.component-FKJqBVRX.mjs +432 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-entry-grid.component-DN42NJ2l.mjs +569 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-flyout-menu.component-CjejQibu.mjs +637 -0
- package/fesm2022/ojiepermana-angular-navigation-navigation-horizontal.component-DUJ4HEmh.mjs +423 -0
- package/fesm2022/ojiepermana-angular-navigation-ojiepermana-angular-navigation-Dh4Huk-N.mjs +2225 -0
- package/fesm2022/ojiepermana-angular-navigation-service.mjs +6 -2
- package/fesm2022/ojiepermana-angular-navigation.mjs +1 -4022
- package/package.json +2 -2
- package/types/ojiepermana-angular-navigation-service.d.ts +1 -1
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { inject, input, output, computed, signal, Component } from '@angular/core';
|
|
4
|
+
import { RouterLink, RouterLinkActive } from '@angular/router';
|
|
5
|
+
import { IconComponent } from '@ojiepermana/angular-component/icon';
|
|
6
|
+
import { cn } from '@ojiepermana/angular-component/utils';
|
|
7
|
+
import { N as NavigationItemComponent } from './ojiepermana-angular-navigation-ojiepermana-angular-navigation-Dh4Huk-N.mjs';
|
|
8
|
+
import { NavigationService } from '@ojiepermana/angular-navigation/service';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Grid entry ala flyout: children sebuah branch dirender sebagai entry
|
|
12
|
+
* icon-box + title/subtitle dalam grid responsif (1/sm:2/md:3/lg:4, dibatasi
|
|
13
|
+
* `columns`); entry ber-children tampil terbuka secara default dengan collapse
|
|
14
|
+
* vertical yang icon-nya sejajar satu garis dengan icon induk. Dipakai oleh
|
|
15
|
+
* flyout dan panel mega navbar.
|
|
16
|
+
*/
|
|
17
|
+
class NavigationEntryGridComponent {
|
|
18
|
+
nav = inject(NavigationService);
|
|
19
|
+
navId = input('default', /* @ts-ignore */
|
|
20
|
+
...(ngDevMode ? [{ debugName: "navId" }] : /* istanbul ignore next */ []));
|
|
21
|
+
branch = input.required(/* @ts-ignore */
|
|
22
|
+
...(ngDevMode ? [{ debugName: "branch" }] : /* istanbul ignore next */ []));
|
|
23
|
+
typeStyle = input('flat', /* @ts-ignore */
|
|
24
|
+
...(ngDevMode ? [{ debugName: "typeStyle" }] : /* istanbul ignore next */ []));
|
|
25
|
+
itemClass = input('', /* @ts-ignore */
|
|
26
|
+
...(ngDevMode ? [{ debugName: "itemClass" }] : /* istanbul ignore next */ []));
|
|
27
|
+
activeIds = input(new Set(), /* @ts-ignore */
|
|
28
|
+
...(ngDevMode ? [{ debugName: "activeIds" }] : /* istanbul ignore next */ []));
|
|
29
|
+
activeUrl = input(null, /* @ts-ignore */
|
|
30
|
+
...(ngDevMode ? [{ debugName: "activeUrl" }] : /* istanbul ignore next */ []));
|
|
31
|
+
iconTemplate = input(undefined, /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "iconTemplate" }] : /* istanbul ignore next */ []));
|
|
33
|
+
collapseTree = input('stairs', /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "collapseTree" }] : /* istanbul ignore next */ []));
|
|
35
|
+
openedIds = input([], /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "openedIds" }] : /* istanbul ignore next */ []));
|
|
37
|
+
openedIdsChange = output();
|
|
38
|
+
itemSelected = output();
|
|
39
|
+
isBorderRail = computed(() => this.typeStyle() === 'border-rail', /* @ts-ignore */
|
|
40
|
+
...(ngDevMode ? [{ debugName: "isBorderRail" }] : /* istanbul ignore next */ []));
|
|
41
|
+
/** Kelas tambahan untuk NavigationItem bersarang saat style border-rail aktif. */
|
|
42
|
+
navItemClass = computed(() => cn(this.itemClass(), this.isBorderRail() && 'rounded-none hover:bg-transparent hover:text-primary'), /* @ts-ignore */
|
|
43
|
+
...(ngDevMode ? [{ debugName: "navItemClass" }] : /* istanbul ignore next */ []));
|
|
44
|
+
/**
|
|
45
|
+
* Entry ber-children tampil TERBUKA secara default; set ini hanya menyimpan
|
|
46
|
+
* entry yang sengaja di-collapse pengguna. Instance grid dibuat ulang setiap
|
|
47
|
+
* panel dibuka sehingga state kembali terbuka semua.
|
|
48
|
+
*/
|
|
49
|
+
collapsedEntryKeys = signal(new Set(), /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "collapsedEntryKeys" }] : /* istanbul ignore next */ []));
|
|
51
|
+
isItemActive(item) {
|
|
52
|
+
return this.nav.isItemActive(item, this.activeIds(), this.activeUrl());
|
|
53
|
+
}
|
|
54
|
+
isEntryOpen(item) {
|
|
55
|
+
return !this.collapsedEntryKeys().has(item.stateId);
|
|
56
|
+
}
|
|
57
|
+
toggleEntry(item) {
|
|
58
|
+
if (item.disabled) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const next = new Set(this.collapsedEntryKeys());
|
|
62
|
+
if (next.has(item.stateId)) {
|
|
63
|
+
next.delete(item.stateId);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
next.add(item.stateId);
|
|
67
|
+
}
|
|
68
|
+
this.collapsedEntryKeys.set(next);
|
|
69
|
+
}
|
|
70
|
+
selectEntry(item, event) {
|
|
71
|
+
if (item.disabled) {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
event.stopPropagation();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
item.action?.(item.source);
|
|
77
|
+
this.itemSelected.emit({
|
|
78
|
+
item: item.source,
|
|
79
|
+
key: item.key,
|
|
80
|
+
type: item.type,
|
|
81
|
+
link: item.link,
|
|
82
|
+
external: !!this.nav.hrefFor(item),
|
|
83
|
+
});
|
|
84
|
+
this.nav.closePanel(this.navId());
|
|
85
|
+
this.nav.closeDrawer(this.navId());
|
|
86
|
+
}
|
|
87
|
+
isRouterItem(item) {
|
|
88
|
+
return this.nav.isRouterItem(item);
|
|
89
|
+
}
|
|
90
|
+
hrefFor(item) {
|
|
91
|
+
return this.nav.hrefFor(item);
|
|
92
|
+
}
|
|
93
|
+
relFor(item) {
|
|
94
|
+
return this.nav.relFor(item);
|
|
95
|
+
}
|
|
96
|
+
routerLinkActiveOptions(item) {
|
|
97
|
+
return this.nav.routerLinkActiveOptions(item);
|
|
98
|
+
}
|
|
99
|
+
iconContext(item, active) {
|
|
100
|
+
return this.nav.iconContext(item, active, 1, 'horizontal');
|
|
101
|
+
}
|
|
102
|
+
fallbackInitials(item) {
|
|
103
|
+
return this.nav.compactFallback(item);
|
|
104
|
+
}
|
|
105
|
+
contentGridClasses(branch) {
|
|
106
|
+
// Skala responsif: mobile 1, sm 2, md 3, lg ke atas 4; `columns` membatasi maksimumnya.
|
|
107
|
+
const columns = Math.min(Math.max(branch.columns ?? 4, 1), 4);
|
|
108
|
+
return cn('m-0 grid list-none grid-cols-1 gap-1 p-0', columns >= 2 && 'sm:grid-cols-2', columns >= 3 && 'md:grid-cols-3', columns >= 4 && 'lg:grid-cols-4');
|
|
109
|
+
}
|
|
110
|
+
entryClasses(item, active) {
|
|
111
|
+
return cn('group/nav nav-text flex w-full items-center gap-3 px-3 py-2.5 text-left transition-colors', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', this.isBorderRail()
|
|
112
|
+
? cn('rounded-none', active ? 'text-primary' : 'text-foreground hover:text-primary')
|
|
113
|
+
: cn('rounded-lg', active
|
|
114
|
+
? 'bg-accent text-accent-foreground'
|
|
115
|
+
: 'text-foreground hover:bg-accent hover:text-accent-foreground'), item.disabled && 'pointer-events-none opacity-50', item.classes?.wrapper, this.itemClass());
|
|
116
|
+
}
|
|
117
|
+
entryIconClasses(active) {
|
|
118
|
+
if (this.isBorderRail()) {
|
|
119
|
+
// Kotak icon polos; bingkai digambar oleh rail line yang menjorok melewati sudut.
|
|
120
|
+
return cn('relative flex h-10 w-10 shrink-0 items-center justify-center self-center text-foreground transition-colors group-hover/nav:text-primary', active && 'text-primary');
|
|
121
|
+
}
|
|
122
|
+
return cn('relative flex h-10 w-10 shrink-0 items-center justify-center self-center rounded-lg border bg-background text-foreground shadow-sm transition-colors', active ? 'border-primary text-primary' : 'border-[hsl(var(--border)/var(--opacity-70))]');
|
|
123
|
+
}
|
|
124
|
+
entryIconGlyphClasses(item) {
|
|
125
|
+
return cn('text-current', item.classes?.icon);
|
|
126
|
+
}
|
|
127
|
+
entryTitleClasses(item, active) {
|
|
128
|
+
return cn('block truncate font-medium', this.isBorderRail() ? 'text-current' : 'text-foreground', active && 'font-semibold', item.classes?.title);
|
|
129
|
+
}
|
|
130
|
+
entrySubtitleClasses(item) {
|
|
131
|
+
return cn('mt-0.5 block truncate text-xs text-muted-foreground', item.classes?.subtitle);
|
|
132
|
+
}
|
|
133
|
+
entryChevronClasses(item) {
|
|
134
|
+
return cn('shrink-0 self-center text-muted-foreground transition-transform duration-200', this.isEntryOpen(item) && 'rotate-90');
|
|
135
|
+
}
|
|
136
|
+
nestedListClasses() {
|
|
137
|
+
// Children sejajar satu garis vertical dengan icon induk: rail digambar lewat pseudo-element
|
|
138
|
+
// di x = 32px (px-3 entry + setengah icon box w-10); pl-2.5 membuat icon child (px-3 + slot
|
|
139
|
+
// w-5) ber-center tepat di garis yang sama.
|
|
140
|
+
return cn("relative mt-1 flex list-none flex-col gap-0.5 p-0 pl-2.5 before:pointer-events-none before:absolute before:inset-y-0 before:left-8 before:w-0 before:border-l before:content-['']", this.isBorderRail()
|
|
141
|
+
? 'before:border-dashed before:border-border/40'
|
|
142
|
+
: 'before:border-[hsl(var(--border)/var(--opacity-60))]');
|
|
143
|
+
}
|
|
144
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NavigationEntryGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
145
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NavigationEntryGridComponent, isStandalone: true, selector: "NavigationEntryGrid", inputs: { navId: { classPropertyName: "navId", publicName: "navId", isSignal: true, isRequired: false, transformFunction: null }, branch: { classPropertyName: "branch", publicName: "branch", isSignal: true, isRequired: true, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "typeStyle", isSignal: true, isRequired: false, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null }, activeIds: { classPropertyName: "activeIds", publicName: "activeIds", isSignal: true, isRequired: false, transformFunction: null }, activeUrl: { classPropertyName: "activeUrl", publicName: "activeUrl", isSignal: true, isRequired: false, transformFunction: null }, iconTemplate: { classPropertyName: "iconTemplate", publicName: "iconTemplate", isSignal: true, isRequired: false, transformFunction: null }, collapseTree: { classPropertyName: "collapseTree", publicName: "collapseTree", isSignal: true, isRequired: false, transformFunction: null }, openedIds: { classPropertyName: "openedIds", publicName: "openedIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openedIdsChange: "openedIdsChange", itemSelected: "itemSelected" }, host: { classAttribute: "contents" }, ngImport: i0, template: `
|
|
146
|
+
@let branchItem = branch();
|
|
147
|
+
|
|
148
|
+
<div
|
|
149
|
+
role="group"
|
|
150
|
+
[id]="branchItem.panelId"
|
|
151
|
+
[attr.aria-label]="branchItem.title || null"
|
|
152
|
+
[attr.data-navigation-flyout-content]="branchItem.key"
|
|
153
|
+
class="p-2 md:p-3"
|
|
154
|
+
>
|
|
155
|
+
<ul role="none" [class]="contentGridClasses(branchItem)">
|
|
156
|
+
@for (child of branchItem.children; track child.key) {
|
|
157
|
+
@switch (child.type) {
|
|
158
|
+
@case ('divider') {
|
|
159
|
+
<li role="separator" class="col-span-full my-1 h-px bg-border"></li>
|
|
160
|
+
}
|
|
161
|
+
@case ('spacer') {}
|
|
162
|
+
@default {
|
|
163
|
+
@if (child.children.length > 0) {
|
|
164
|
+
<li role="none" class="min-w-0" [attr.data-navigation-item-key]="child.key">
|
|
165
|
+
<button
|
|
166
|
+
type="button"
|
|
167
|
+
role="menuitem"
|
|
168
|
+
data-navigation-flyout-entry="true"
|
|
169
|
+
[class]="entryClasses(child, isItemActive(child))"
|
|
170
|
+
[attr.aria-expanded]="isEntryOpen(child)"
|
|
171
|
+
[attr.aria-controls]="child.panelId"
|
|
172
|
+
[disabled]="child.disabled || null"
|
|
173
|
+
(click)="toggleEntry(child)"
|
|
174
|
+
>
|
|
175
|
+
<ng-container
|
|
176
|
+
[ngTemplateOutlet]="entryContent"
|
|
177
|
+
[ngTemplateOutletContext]="{ $implicit: child, active: isItemActive(child) }"
|
|
178
|
+
/>
|
|
179
|
+
<Icon name="chevron_right" [size]="16" [class]="entryChevronClasses(child)" />
|
|
180
|
+
</button>
|
|
181
|
+
|
|
182
|
+
@if (isEntryOpen(child)) {
|
|
183
|
+
<ul [id]="child.panelId" role="none" [class]="nestedListClasses()">
|
|
184
|
+
@for (nested of child.children; track nested.key) {
|
|
185
|
+
<li
|
|
186
|
+
NavigationItem
|
|
187
|
+
[navId]="navId()"
|
|
188
|
+
[item]="nested"
|
|
189
|
+
[level]="2"
|
|
190
|
+
[orientation]="'horizontal'"
|
|
191
|
+
[compact]="false"
|
|
192
|
+
[itemClass]="navItemClass()"
|
|
193
|
+
[activeIds]="activeIds()"
|
|
194
|
+
[activeUrl]="activeUrl()"
|
|
195
|
+
[iconTemplate]="iconTemplate()"
|
|
196
|
+
[collapseTree]="collapseTree()"
|
|
197
|
+
[openedIds]="openedIds()"
|
|
198
|
+
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
199
|
+
(itemSelected)="itemSelected.emit($event)"
|
|
200
|
+
></li>
|
|
201
|
+
}
|
|
202
|
+
</ul>
|
|
203
|
+
}
|
|
204
|
+
</li>
|
|
205
|
+
} @else {
|
|
206
|
+
<li role="none" class="min-w-0" [attr.data-navigation-item-key]="child.key">
|
|
207
|
+
@if (isRouterItem(child)) {
|
|
208
|
+
<a
|
|
209
|
+
role="menuitem"
|
|
210
|
+
data-navigation-flyout-entry="true"
|
|
211
|
+
[class]="entryClasses(child, routerActive.isActive || isItemActive(child))"
|
|
212
|
+
[routerLink]="child.link ?? null"
|
|
213
|
+
[queryParams]="child.queryParams ?? null"
|
|
214
|
+
[queryParamsHandling]="child.queryParamsHandling ?? null"
|
|
215
|
+
[fragment]="child.fragment ?? undefined"
|
|
216
|
+
[preserveFragment]="child.preserveFragment ?? false"
|
|
217
|
+
[target]="child.target ?? undefined"
|
|
218
|
+
routerLinkActive
|
|
219
|
+
#routerActive="routerLinkActive"
|
|
220
|
+
[routerLinkActiveOptions]="routerLinkActiveOptions(child)"
|
|
221
|
+
[attr.aria-current]="
|
|
222
|
+
routerActive.isActive || isItemActive(child) ? 'page' : null
|
|
223
|
+
"
|
|
224
|
+
[attr.aria-disabled]="child.disabled || null"
|
|
225
|
+
(click)="selectEntry(child, $event)"
|
|
226
|
+
>
|
|
227
|
+
<ng-container
|
|
228
|
+
[ngTemplateOutlet]="entryContent"
|
|
229
|
+
[ngTemplateOutletContext]="{
|
|
230
|
+
$implicit: child,
|
|
231
|
+
active: routerActive.isActive || isItemActive(child),
|
|
232
|
+
}"
|
|
233
|
+
/>
|
|
234
|
+
</a>
|
|
235
|
+
} @else if (hrefFor(child)) {
|
|
236
|
+
<a
|
|
237
|
+
role="menuitem"
|
|
238
|
+
data-navigation-flyout-entry="true"
|
|
239
|
+
[class]="entryClasses(child, isItemActive(child))"
|
|
240
|
+
[attr.href]="hrefFor(child)"
|
|
241
|
+
[attr.target]="child.target ?? (child.externalLink ? '_blank' : null)"
|
|
242
|
+
[attr.rel]="relFor(child)"
|
|
243
|
+
[attr.aria-current]="isItemActive(child) ? 'page' : null"
|
|
244
|
+
[attr.aria-disabled]="child.disabled || null"
|
|
245
|
+
(click)="selectEntry(child, $event)"
|
|
246
|
+
>
|
|
247
|
+
<ng-container
|
|
248
|
+
[ngTemplateOutlet]="entryContent"
|
|
249
|
+
[ngTemplateOutletContext]="{
|
|
250
|
+
$implicit: child,
|
|
251
|
+
active: isItemActive(child),
|
|
252
|
+
}"
|
|
253
|
+
/>
|
|
254
|
+
</a>
|
|
255
|
+
} @else {
|
|
256
|
+
<button
|
|
257
|
+
type="button"
|
|
258
|
+
role="menuitem"
|
|
259
|
+
data-navigation-flyout-entry="true"
|
|
260
|
+
[class]="entryClasses(child, isItemActive(child))"
|
|
261
|
+
[disabled]="child.disabled || null"
|
|
262
|
+
[attr.aria-current]="isItemActive(child) ? 'page' : null"
|
|
263
|
+
(click)="selectEntry(child, $event)"
|
|
264
|
+
>
|
|
265
|
+
<ng-container
|
|
266
|
+
[ngTemplateOutlet]="entryContent"
|
|
267
|
+
[ngTemplateOutletContext]="{
|
|
268
|
+
$implicit: child,
|
|
269
|
+
active: isItemActive(child),
|
|
270
|
+
}"
|
|
271
|
+
/>
|
|
272
|
+
</button>
|
|
273
|
+
}
|
|
274
|
+
</li>
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
</ul>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
<ng-template #entryContent let-child let-active="active">
|
|
283
|
+
<span [class]="entryIconClasses(active)">
|
|
284
|
+
@if (isBorderRail()) {
|
|
285
|
+
<span
|
|
286
|
+
aria-hidden="true"
|
|
287
|
+
data-navigation-icon-rail="top"
|
|
288
|
+
class="pointer-events-none absolute -inset-x-1.5 top-0 h-px bg-border/50"
|
|
289
|
+
></span>
|
|
290
|
+
<span
|
|
291
|
+
aria-hidden="true"
|
|
292
|
+
data-navigation-icon-rail="bottom"
|
|
293
|
+
class="pointer-events-none absolute -inset-x-1.5 bottom-0 h-px bg-border/50"
|
|
294
|
+
></span>
|
|
295
|
+
<span
|
|
296
|
+
aria-hidden="true"
|
|
297
|
+
data-navigation-icon-rail="left"
|
|
298
|
+
class="pointer-events-none absolute -inset-y-1.5 left-0 w-px bg-border/50"
|
|
299
|
+
></span>
|
|
300
|
+
<span
|
|
301
|
+
aria-hidden="true"
|
|
302
|
+
data-navigation-icon-rail="right"
|
|
303
|
+
class="pointer-events-none absolute -inset-y-1.5 right-0 w-px bg-border/50"
|
|
304
|
+
></span>
|
|
305
|
+
<span
|
|
306
|
+
aria-hidden="true"
|
|
307
|
+
data-navigation-icon-rail="center-horizontal"
|
|
308
|
+
class="pointer-events-none absolute -inset-x-1.5 top-1/2 border-t border-dashed border-border/40"
|
|
309
|
+
></span>
|
|
310
|
+
<span
|
|
311
|
+
aria-hidden="true"
|
|
312
|
+
data-navigation-icon-rail="center-vertical"
|
|
313
|
+
class="pointer-events-none absolute -inset-y-1.5 left-1/2 border-l border-dashed border-border/40"
|
|
314
|
+
></span>
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
@if (child.icon) {
|
|
318
|
+
@if (iconTemplate(); as customIcon) {
|
|
319
|
+
<ng-container
|
|
320
|
+
[ngTemplateOutlet]="customIcon.template"
|
|
321
|
+
[ngTemplateOutletContext]="iconContext(child, active)"
|
|
322
|
+
/>
|
|
323
|
+
} @else {
|
|
324
|
+
<Icon [name]="child.icon" [size]="18" [class]="entryIconGlyphClasses(child)" />
|
|
325
|
+
}
|
|
326
|
+
} @else {
|
|
327
|
+
<span aria-hidden="true" class="text-xs font-semibold uppercase">{{
|
|
328
|
+
fallbackInitials(child)
|
|
329
|
+
}}</span>
|
|
330
|
+
}
|
|
331
|
+
</span>
|
|
332
|
+
|
|
333
|
+
<span class="min-w-0 flex-1">
|
|
334
|
+
<span [class]="entryTitleClasses(child, active)">{{ child.title }}</span>
|
|
335
|
+
@if (child.subtitle) {
|
|
336
|
+
<span [class]="entrySubtitleClasses(child)">{{ child.subtitle }}</span>
|
|
337
|
+
}
|
|
338
|
+
</span>
|
|
339
|
+
|
|
340
|
+
@if (child.badge; as badge) {
|
|
341
|
+
<span
|
|
342
|
+
[class]="
|
|
343
|
+
badge.classes ??
|
|
344
|
+
'nav-badge inline-flex h-5 shrink-0 items-center self-center rounded-full bg-muted px-2 text-muted-foreground'
|
|
345
|
+
"
|
|
346
|
+
>{{ badge.title }}</span
|
|
347
|
+
>
|
|
348
|
+
}
|
|
349
|
+
</ng-template>
|
|
350
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: IconComponent, selector: "Icon", inputs: ["name", "class", "size", "fill", "weight", "grade", "opticalSize"] }, { kind: "component", type: NavigationItemComponent, selector: "li[NavigationItem]", inputs: ["navId", "item", "level", "orientation", "compact", "itemClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "straightRail", "straightRailActive", "firstInBranch", "lastInBranch", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }] });
|
|
351
|
+
}
|
|
352
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NavigationEntryGridComponent, decorators: [{
|
|
353
|
+
type: Component,
|
|
354
|
+
args: [{
|
|
355
|
+
selector: 'NavigationEntryGrid',
|
|
356
|
+
imports: [NgTemplateOutlet, RouterLink, RouterLinkActive, IconComponent, NavigationItemComponent],
|
|
357
|
+
host: {
|
|
358
|
+
class: 'contents',
|
|
359
|
+
},
|
|
360
|
+
template: `
|
|
361
|
+
@let branchItem = branch();
|
|
362
|
+
|
|
363
|
+
<div
|
|
364
|
+
role="group"
|
|
365
|
+
[id]="branchItem.panelId"
|
|
366
|
+
[attr.aria-label]="branchItem.title || null"
|
|
367
|
+
[attr.data-navigation-flyout-content]="branchItem.key"
|
|
368
|
+
class="p-2 md:p-3"
|
|
369
|
+
>
|
|
370
|
+
<ul role="none" [class]="contentGridClasses(branchItem)">
|
|
371
|
+
@for (child of branchItem.children; track child.key) {
|
|
372
|
+
@switch (child.type) {
|
|
373
|
+
@case ('divider') {
|
|
374
|
+
<li role="separator" class="col-span-full my-1 h-px bg-border"></li>
|
|
375
|
+
}
|
|
376
|
+
@case ('spacer') {}
|
|
377
|
+
@default {
|
|
378
|
+
@if (child.children.length > 0) {
|
|
379
|
+
<li role="none" class="min-w-0" [attr.data-navigation-item-key]="child.key">
|
|
380
|
+
<button
|
|
381
|
+
type="button"
|
|
382
|
+
role="menuitem"
|
|
383
|
+
data-navigation-flyout-entry="true"
|
|
384
|
+
[class]="entryClasses(child, isItemActive(child))"
|
|
385
|
+
[attr.aria-expanded]="isEntryOpen(child)"
|
|
386
|
+
[attr.aria-controls]="child.panelId"
|
|
387
|
+
[disabled]="child.disabled || null"
|
|
388
|
+
(click)="toggleEntry(child)"
|
|
389
|
+
>
|
|
390
|
+
<ng-container
|
|
391
|
+
[ngTemplateOutlet]="entryContent"
|
|
392
|
+
[ngTemplateOutletContext]="{ $implicit: child, active: isItemActive(child) }"
|
|
393
|
+
/>
|
|
394
|
+
<Icon name="chevron_right" [size]="16" [class]="entryChevronClasses(child)" />
|
|
395
|
+
</button>
|
|
396
|
+
|
|
397
|
+
@if (isEntryOpen(child)) {
|
|
398
|
+
<ul [id]="child.panelId" role="none" [class]="nestedListClasses()">
|
|
399
|
+
@for (nested of child.children; track nested.key) {
|
|
400
|
+
<li
|
|
401
|
+
NavigationItem
|
|
402
|
+
[navId]="navId()"
|
|
403
|
+
[item]="nested"
|
|
404
|
+
[level]="2"
|
|
405
|
+
[orientation]="'horizontal'"
|
|
406
|
+
[compact]="false"
|
|
407
|
+
[itemClass]="navItemClass()"
|
|
408
|
+
[activeIds]="activeIds()"
|
|
409
|
+
[activeUrl]="activeUrl()"
|
|
410
|
+
[iconTemplate]="iconTemplate()"
|
|
411
|
+
[collapseTree]="collapseTree()"
|
|
412
|
+
[openedIds]="openedIds()"
|
|
413
|
+
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
414
|
+
(itemSelected)="itemSelected.emit($event)"
|
|
415
|
+
></li>
|
|
416
|
+
}
|
|
417
|
+
</ul>
|
|
418
|
+
}
|
|
419
|
+
</li>
|
|
420
|
+
} @else {
|
|
421
|
+
<li role="none" class="min-w-0" [attr.data-navigation-item-key]="child.key">
|
|
422
|
+
@if (isRouterItem(child)) {
|
|
423
|
+
<a
|
|
424
|
+
role="menuitem"
|
|
425
|
+
data-navigation-flyout-entry="true"
|
|
426
|
+
[class]="entryClasses(child, routerActive.isActive || isItemActive(child))"
|
|
427
|
+
[routerLink]="child.link ?? null"
|
|
428
|
+
[queryParams]="child.queryParams ?? null"
|
|
429
|
+
[queryParamsHandling]="child.queryParamsHandling ?? null"
|
|
430
|
+
[fragment]="child.fragment ?? undefined"
|
|
431
|
+
[preserveFragment]="child.preserveFragment ?? false"
|
|
432
|
+
[target]="child.target ?? undefined"
|
|
433
|
+
routerLinkActive
|
|
434
|
+
#routerActive="routerLinkActive"
|
|
435
|
+
[routerLinkActiveOptions]="routerLinkActiveOptions(child)"
|
|
436
|
+
[attr.aria-current]="
|
|
437
|
+
routerActive.isActive || isItemActive(child) ? 'page' : null
|
|
438
|
+
"
|
|
439
|
+
[attr.aria-disabled]="child.disabled || null"
|
|
440
|
+
(click)="selectEntry(child, $event)"
|
|
441
|
+
>
|
|
442
|
+
<ng-container
|
|
443
|
+
[ngTemplateOutlet]="entryContent"
|
|
444
|
+
[ngTemplateOutletContext]="{
|
|
445
|
+
$implicit: child,
|
|
446
|
+
active: routerActive.isActive || isItemActive(child),
|
|
447
|
+
}"
|
|
448
|
+
/>
|
|
449
|
+
</a>
|
|
450
|
+
} @else if (hrefFor(child)) {
|
|
451
|
+
<a
|
|
452
|
+
role="menuitem"
|
|
453
|
+
data-navigation-flyout-entry="true"
|
|
454
|
+
[class]="entryClasses(child, isItemActive(child))"
|
|
455
|
+
[attr.href]="hrefFor(child)"
|
|
456
|
+
[attr.target]="child.target ?? (child.externalLink ? '_blank' : null)"
|
|
457
|
+
[attr.rel]="relFor(child)"
|
|
458
|
+
[attr.aria-current]="isItemActive(child) ? 'page' : null"
|
|
459
|
+
[attr.aria-disabled]="child.disabled || null"
|
|
460
|
+
(click)="selectEntry(child, $event)"
|
|
461
|
+
>
|
|
462
|
+
<ng-container
|
|
463
|
+
[ngTemplateOutlet]="entryContent"
|
|
464
|
+
[ngTemplateOutletContext]="{
|
|
465
|
+
$implicit: child,
|
|
466
|
+
active: isItemActive(child),
|
|
467
|
+
}"
|
|
468
|
+
/>
|
|
469
|
+
</a>
|
|
470
|
+
} @else {
|
|
471
|
+
<button
|
|
472
|
+
type="button"
|
|
473
|
+
role="menuitem"
|
|
474
|
+
data-navigation-flyout-entry="true"
|
|
475
|
+
[class]="entryClasses(child, isItemActive(child))"
|
|
476
|
+
[disabled]="child.disabled || null"
|
|
477
|
+
[attr.aria-current]="isItemActive(child) ? 'page' : null"
|
|
478
|
+
(click)="selectEntry(child, $event)"
|
|
479
|
+
>
|
|
480
|
+
<ng-container
|
|
481
|
+
[ngTemplateOutlet]="entryContent"
|
|
482
|
+
[ngTemplateOutletContext]="{
|
|
483
|
+
$implicit: child,
|
|
484
|
+
active: isItemActive(child),
|
|
485
|
+
}"
|
|
486
|
+
/>
|
|
487
|
+
</button>
|
|
488
|
+
}
|
|
489
|
+
</li>
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
</ul>
|
|
495
|
+
</div>
|
|
496
|
+
|
|
497
|
+
<ng-template #entryContent let-child let-active="active">
|
|
498
|
+
<span [class]="entryIconClasses(active)">
|
|
499
|
+
@if (isBorderRail()) {
|
|
500
|
+
<span
|
|
501
|
+
aria-hidden="true"
|
|
502
|
+
data-navigation-icon-rail="top"
|
|
503
|
+
class="pointer-events-none absolute -inset-x-1.5 top-0 h-px bg-border/50"
|
|
504
|
+
></span>
|
|
505
|
+
<span
|
|
506
|
+
aria-hidden="true"
|
|
507
|
+
data-navigation-icon-rail="bottom"
|
|
508
|
+
class="pointer-events-none absolute -inset-x-1.5 bottom-0 h-px bg-border/50"
|
|
509
|
+
></span>
|
|
510
|
+
<span
|
|
511
|
+
aria-hidden="true"
|
|
512
|
+
data-navigation-icon-rail="left"
|
|
513
|
+
class="pointer-events-none absolute -inset-y-1.5 left-0 w-px bg-border/50"
|
|
514
|
+
></span>
|
|
515
|
+
<span
|
|
516
|
+
aria-hidden="true"
|
|
517
|
+
data-navigation-icon-rail="right"
|
|
518
|
+
class="pointer-events-none absolute -inset-y-1.5 right-0 w-px bg-border/50"
|
|
519
|
+
></span>
|
|
520
|
+
<span
|
|
521
|
+
aria-hidden="true"
|
|
522
|
+
data-navigation-icon-rail="center-horizontal"
|
|
523
|
+
class="pointer-events-none absolute -inset-x-1.5 top-1/2 border-t border-dashed border-border/40"
|
|
524
|
+
></span>
|
|
525
|
+
<span
|
|
526
|
+
aria-hidden="true"
|
|
527
|
+
data-navigation-icon-rail="center-vertical"
|
|
528
|
+
class="pointer-events-none absolute -inset-y-1.5 left-1/2 border-l border-dashed border-border/40"
|
|
529
|
+
></span>
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
@if (child.icon) {
|
|
533
|
+
@if (iconTemplate(); as customIcon) {
|
|
534
|
+
<ng-container
|
|
535
|
+
[ngTemplateOutlet]="customIcon.template"
|
|
536
|
+
[ngTemplateOutletContext]="iconContext(child, active)"
|
|
537
|
+
/>
|
|
538
|
+
} @else {
|
|
539
|
+
<Icon [name]="child.icon" [size]="18" [class]="entryIconGlyphClasses(child)" />
|
|
540
|
+
}
|
|
541
|
+
} @else {
|
|
542
|
+
<span aria-hidden="true" class="text-xs font-semibold uppercase">{{
|
|
543
|
+
fallbackInitials(child)
|
|
544
|
+
}}</span>
|
|
545
|
+
}
|
|
546
|
+
</span>
|
|
547
|
+
|
|
548
|
+
<span class="min-w-0 flex-1">
|
|
549
|
+
<span [class]="entryTitleClasses(child, active)">{{ child.title }}</span>
|
|
550
|
+
@if (child.subtitle) {
|
|
551
|
+
<span [class]="entrySubtitleClasses(child)">{{ child.subtitle }}</span>
|
|
552
|
+
}
|
|
553
|
+
</span>
|
|
554
|
+
|
|
555
|
+
@if (child.badge; as badge) {
|
|
556
|
+
<span
|
|
557
|
+
[class]="
|
|
558
|
+
badge.classes ??
|
|
559
|
+
'nav-badge inline-flex h-5 shrink-0 items-center self-center rounded-full bg-muted px-2 text-muted-foreground'
|
|
560
|
+
"
|
|
561
|
+
>{{ badge.title }}</span
|
|
562
|
+
>
|
|
563
|
+
}
|
|
564
|
+
</ng-template>
|
|
565
|
+
`,
|
|
566
|
+
}]
|
|
567
|
+
}], propDecorators: { navId: [{ type: i0.Input, args: [{ isSignal: true, alias: "navId", required: false }] }], branch: [{ type: i0.Input, args: [{ isSignal: true, alias: "branch", required: true }] }], typeStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "typeStyle", required: false }] }], itemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClass", required: false }] }], activeIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIds", required: false }] }], activeUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeUrl", required: false }] }], iconTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconTemplate", required: false }] }], collapseTree: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseTree", required: false }] }], openedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "openedIds", required: false }] }], openedIdsChange: [{ type: i0.Output, args: ["openedIdsChange"] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }] } });
|
|
568
|
+
|
|
569
|
+
export { NavigationEntryGridComponent as N };
|