@ojiepermana/angular 21.1.9 → 21.1.12
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 +13 -0
- package/brand/etos/README.md +16 -69
- package/etos/styles/color.css +52 -0
- package/etos/styles/layout.css +0 -165
- package/fesm2022/ojiepermana-angular-brand-etos.mjs +398 -234
- package/fesm2022/ojiepermana-angular-brand-etos.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-chart.mjs +72 -72
- package/fesm2022/ojiepermana-angular-chart.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-component.mjs +306 -296
- package/fesm2022/ojiepermana-angular-component.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-layout.mjs +75 -56
- package/fesm2022/ojiepermana-angular-layout.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-navigation.mjs +279 -258
- package/fesm2022/ojiepermana-angular-navigation.mjs.map +1 -1
- package/fesm2022/ojiepermana-angular-theme.mjs +3 -3
- package/fesm2022/ojiepermana-angular-theme.mjs.map +1 -1
- package/generator/api/README.md +17 -10
- package/generator/api/bin/schematics/sdk/index.js +18 -0
- package/generator/api/bin/src/layout/per-domain.js +15 -7
- package/generator/api/bin/src/writer/index.js +24 -11
- package/package.json +1 -1
- package/theme/styles/themes/taildwind.css +3 -0
- package/types/ojiepermana-angular-brand-etos.d.ts +30 -53
- package/types/ojiepermana-angular-component.d.ts +2 -1
- package/types/ojiepermana-angular-layout.d.ts +18 -11
- package/types/ojiepermana-angular-navigation.d.ts +28 -15
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { DOCUMENT, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
1
2
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, DestroyRef, signal, computed, Injectable, PLATFORM_ID, input, ChangeDetectionStrategy, Component, ViewContainerRef, viewChild,
|
|
3
|
+
import { inject, DestroyRef, signal, computed, effect, Injectable, PLATFORM_ID, input, ChangeDetectionStrategy, Component, ViewContainerRef, viewChild, ElementRef } from '@angular/core';
|
|
3
4
|
import { Router, NavigationEnd, RouterLink, RouterLinkActive } from '@angular/router';
|
|
4
5
|
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
5
6
|
import { filter, map } from 'rxjs/operators';
|
|
6
|
-
import { DOCUMENT, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
7
7
|
import { MatTooltip } from '@angular/material/tooltip';
|
|
8
8
|
import { clsx } from 'clsx';
|
|
9
9
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -15,26 +15,42 @@ import { merge } from 'rxjs';
|
|
|
15
15
|
|
|
16
16
|
/** Default registry key used when no id is specified. */
|
|
17
17
|
const DEFAULT_NAVIGATION_ID = 'main';
|
|
18
|
+
const SIDEBAR_COLLAPSE_STORAGE_KEY = 'sidebar-collapse';
|
|
19
|
+
const LEGACY_SIDEBAR_APPEARANCE_STORAGE_KEY = 'sidebar-appearance';
|
|
20
|
+
function parseSidebarCollapsed(value) {
|
|
21
|
+
if (value === 'true')
|
|
22
|
+
return true;
|
|
23
|
+
if (value === 'false')
|
|
24
|
+
return false;
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
18
27
|
/**
|
|
19
28
|
* Signal-based global state untuk navigation (sidebar/topbar).
|
|
20
29
|
*
|
|
21
30
|
* Items disimpan dalam registry ber-key. Key default adalah `'main'`.
|
|
22
|
-
* Komponen `
|
|
31
|
+
* Komponen `sidebar` / `topbar` memilih registry via input `navigationId`.
|
|
23
32
|
*/
|
|
24
33
|
class NavigationService {
|
|
34
|
+
doc = inject(DOCUMENT);
|
|
25
35
|
router = inject(Router);
|
|
26
36
|
destroyRef = inject(DestroyRef);
|
|
37
|
+
persistedSidebarCollapsed = this.readPersistedSidebarCollapsed();
|
|
27
38
|
/** Internal version counter — incremented on every registry mutation. */
|
|
28
39
|
_version = signal(0, ...(ngDevMode ? [{ debugName: "_version" }] : /* istanbul ignore next */ []));
|
|
29
40
|
/** Internal map of registered navigation trees. */
|
|
30
41
|
_registry = new Map();
|
|
42
|
+
_collapsed = signal(this.persistedSidebarCollapsed ?? false, ...(ngDevMode ? [{ debugName: "_collapsed" }] : /* istanbul ignore next */ []));
|
|
43
|
+
_hasStoredSidebarCollapse = signal(this.persistedSidebarCollapsed !== null, ...(ngDevMode ? [{ debugName: "_hasStoredSidebarCollapse" }] : /* istanbul ignore next */ []));
|
|
31
44
|
/**
|
|
32
45
|
* Backward-compatible accessor — returns items for the default (`'main'`) key.
|
|
33
46
|
* Prefer `getItems(id)` when working with named registries.
|
|
34
47
|
*/
|
|
35
48
|
items = computed(() => this.getItems(DEFAULT_NAVIGATION_ID)(), ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
49
|
+
/** Sidebar appearance preference (`default` or `thin`). */
|
|
50
|
+
sidebarAppearance = computed(() => (this._collapsed() ? 'thin' : 'default'), ...(ngDevMode ? [{ debugName: "sidebarAppearance" }] : /* istanbul ignore next */ []));
|
|
51
|
+
hasStoredSidebarCollapse = this._hasStoredSidebarCollapse.asReadonly();
|
|
36
52
|
/** Sidebar collapsed (default ↔ thin) toggle untuk desktop. */
|
|
37
|
-
collapsed =
|
|
53
|
+
collapsed = this._collapsed.asReadonly();
|
|
38
54
|
/** Sheet drawer terbuka di mobile. */
|
|
39
55
|
mobileOpen = signal(false, ...(ngDevMode ? [{ debugName: "mobileOpen" }] : /* istanbul ignore next */ []));
|
|
40
56
|
/** Set id grup / collapsable yang sedang terbuka. */
|
|
@@ -74,6 +90,12 @@ class NavigationService {
|
|
|
74
90
|
return trail;
|
|
75
91
|
}, ...(ngDevMode ? [{ debugName: "activeTrail" }] : /* istanbul ignore next */ []));
|
|
76
92
|
constructor() {
|
|
93
|
+
effect(() => {
|
|
94
|
+
if (!this._hasStoredSidebarCollapse()) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
this.persistSidebarCollapsed(this._collapsed());
|
|
98
|
+
});
|
|
77
99
|
this.router.events
|
|
78
100
|
.pipe(filter((e) => e instanceof NavigationEnd), takeUntilDestroyed(this.destroyRef))
|
|
79
101
|
.subscribe((e) => this.activeUrl.set(e.urlAfterRedirects));
|
|
@@ -98,12 +120,19 @@ class NavigationService {
|
|
|
98
120
|
return this._registry.get(id) ?? [];
|
|
99
121
|
});
|
|
100
122
|
}
|
|
123
|
+
setSidebarAppearance(value) {
|
|
124
|
+
this.setCollapsed(value === 'thin');
|
|
125
|
+
}
|
|
126
|
+
toggleSidebarAppearance(currentAppearance = this.sidebarAppearance()) {
|
|
127
|
+
this.setCollapsed(currentAppearance !== 'thin');
|
|
128
|
+
}
|
|
101
129
|
/** Toggle sidebar collapsed (default ↔ thin). */
|
|
102
130
|
toggleCollapsed() {
|
|
103
|
-
this.
|
|
131
|
+
this.setCollapsed(!this._collapsed());
|
|
104
132
|
}
|
|
105
133
|
setCollapsed(value) {
|
|
106
|
-
this.
|
|
134
|
+
this._collapsed.set(value);
|
|
135
|
+
this._hasStoredSidebarCollapse.set(true);
|
|
107
136
|
}
|
|
108
137
|
openMobile() {
|
|
109
138
|
this.mobileOpen.set(true);
|
|
@@ -137,10 +166,40 @@ class NavigationService {
|
|
|
137
166
|
isActive(id) {
|
|
138
167
|
return !!id && this.activeTrail().has(id);
|
|
139
168
|
}
|
|
140
|
-
|
|
141
|
-
|
|
169
|
+
readPersistedSidebarCollapsed() {
|
|
170
|
+
try {
|
|
171
|
+
const storage = this.doc.defaultView?.localStorage;
|
|
172
|
+
const collapsed = parseSidebarCollapsed(storage?.getItem(SIDEBAR_COLLAPSE_STORAGE_KEY));
|
|
173
|
+
if (collapsed !== null) {
|
|
174
|
+
return collapsed;
|
|
175
|
+
}
|
|
176
|
+
const legacyAppearance = storage?.getItem(LEGACY_SIDEBAR_APPEARANCE_STORAGE_KEY);
|
|
177
|
+
if (legacyAppearance === 'thin') {
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
if (legacyAppearance === 'default') {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
persistSidebarCollapsed(value) {
|
|
190
|
+
try {
|
|
191
|
+
const storage = this.doc.defaultView?.localStorage;
|
|
192
|
+
storage?.setItem(SIDEBAR_COLLAPSE_STORAGE_KEY, String(value));
|
|
193
|
+
storage?.removeItem(LEGACY_SIDEBAR_APPEARANCE_STORAGE_KEY);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
/* ignore */
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: NavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
200
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: NavigationService, providedIn: 'root' });
|
|
142
201
|
}
|
|
143
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
202
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: NavigationService, decorators: [{
|
|
144
203
|
type: Injectable,
|
|
145
204
|
args: [{ providedIn: 'root' }]
|
|
146
205
|
}], ctorParameters: () => [] });
|
|
@@ -180,10 +239,10 @@ class UiNavIconComponent {
|
|
|
180
239
|
link.setAttribute(MATERIAL_SYMBOLS_FONT_ATTR, MATERIAL_SYMBOLS_FONT_ID);
|
|
181
240
|
this.doc.head.appendChild(link);
|
|
182
241
|
}
|
|
183
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
184
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.
|
|
242
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UiNavIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
243
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.11", type: UiNavIconComponent, isStandalone: true, selector: "ui-nav-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true", "translate": "no" }, properties: { "class": "classes()", "style.font-size.px": "size()", "style.font-variation-settings": "fontVariationSettings" } }, ngImport: i0, template: `{{ name() }}`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
185
244
|
}
|
|
186
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
245
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UiNavIconComponent, decorators: [{
|
|
187
246
|
type: Component,
|
|
188
247
|
args: [{
|
|
189
248
|
selector: 'ui-nav-icon',
|
|
@@ -263,8 +322,8 @@ class UiNavItemComponent {
|
|
|
263
322
|
item.action(item);
|
|
264
323
|
}
|
|
265
324
|
}
|
|
266
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
267
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
325
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UiNavItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
326
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: UiNavItemComponent, isStandalone: true, selector: "ui-nav-item", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
268
327
|
@switch (type()) {
|
|
269
328
|
@case ('divider') {
|
|
270
329
|
<hr class="my-2 border-t border-border" role="separator" />
|
|
@@ -273,9 +332,9 @@ class UiNavItemComponent {
|
|
|
273
332
|
<div class="flex-1"></div>
|
|
274
333
|
}
|
|
275
334
|
@case ('group') {
|
|
276
|
-
<div
|
|
335
|
+
<div role="group" [attr.aria-labelledby]="headingId()">
|
|
277
336
|
@if (!compact()) {
|
|
278
|
-
<div class="sticky top-0 z-10
|
|
337
|
+
<div class="sticky top-0 z-10 p-3 text-muted-foreground backdrop-blur-3xl bg-transparent">
|
|
279
338
|
<div [id]="headingId()" [class]="cn('ui-nav-heading text-muted-foreground', item().classes?.title)">
|
|
280
339
|
{{ item().title }}
|
|
281
340
|
</div>
|
|
@@ -295,7 +354,7 @@ class UiNavItemComponent {
|
|
|
295
354
|
type="button"
|
|
296
355
|
[class]="
|
|
297
356
|
cn(
|
|
298
|
-
'ui-nav-text group/ni flex w-full items-center gap-3 rounded-
|
|
357
|
+
'ui-nav-text group/ni flex w-full items-center gap-3 rounded-full p-3 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
299
358
|
isTrailActive() && 'text-primary',
|
|
300
359
|
item().classes?.wrapper
|
|
301
360
|
)
|
|
@@ -308,7 +367,15 @@ class UiNavItemComponent {
|
|
|
308
367
|
[matTooltipDisabled]="!compact()"
|
|
309
368
|
(click)="toggleGroup()">
|
|
310
369
|
@if (collapsableItem().icon) {
|
|
311
|
-
<
|
|
370
|
+
<span
|
|
371
|
+
[class]="
|
|
372
|
+
cn(
|
|
373
|
+
'inline-flex shrink-0 items-center justify-center',
|
|
374
|
+
open && 'h-7 w-7 rounded-full border border-brand'
|
|
375
|
+
)
|
|
376
|
+
">
|
|
377
|
+
<ui-nav-icon [name]="collapsableItem().icon!" [size]="18" [class]="item().classes?.icon ?? ''" />
|
|
378
|
+
</span>
|
|
312
379
|
}
|
|
313
380
|
@if (!compact()) {
|
|
314
381
|
<span [class]="cn('flex-1 truncate text-left', item().classes?.title)">
|
|
@@ -324,7 +391,10 @@ class UiNavItemComponent {
|
|
|
324
391
|
}
|
|
325
392
|
</button>
|
|
326
393
|
@if (!compact() && open) {
|
|
327
|
-
<div
|
|
394
|
+
<div
|
|
395
|
+
[id]="id + '-panel'"
|
|
396
|
+
role="region"
|
|
397
|
+
class="relative ml-6.5 mt-0.5 flex flex-col gap-0.5 pl-3 before:absolute before:bottom-0 before:left-0 before:-top-3.5 before:w-px before:bg-border before:content-['']">
|
|
328
398
|
@for (child of collapsableItem().children; track child.id) {
|
|
329
399
|
<ui-nav-item [item]="child" [level]="level() + 1" [compact]="false" />
|
|
330
400
|
}
|
|
@@ -456,7 +526,7 @@ class UiNavItemComponent {
|
|
|
456
526
|
}
|
|
457
527
|
`, isInline: true, dependencies: [{ kind: "component", type: UiNavItemComponent, selector: "ui-nav-item", inputs: ["item", "level", "compact"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: UiNavIconComponent, selector: "ui-nav-icon", inputs: ["name", "class", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
458
528
|
}
|
|
459
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
529
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: UiNavItemComponent, decorators: [{
|
|
460
530
|
type: Component,
|
|
461
531
|
args: [{
|
|
462
532
|
selector: 'ui-nav-item',
|
|
@@ -471,9 +541,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
471
541
|
<div class="flex-1"></div>
|
|
472
542
|
}
|
|
473
543
|
@case ('group') {
|
|
474
|
-
<div
|
|
544
|
+
<div role="group" [attr.aria-labelledby]="headingId()">
|
|
475
545
|
@if (!compact()) {
|
|
476
|
-
<div class="sticky top-0 z-10
|
|
546
|
+
<div class="sticky top-0 z-10 p-3 text-muted-foreground backdrop-blur-3xl bg-transparent">
|
|
477
547
|
<div [id]="headingId()" [class]="cn('ui-nav-heading text-muted-foreground', item().classes?.title)">
|
|
478
548
|
{{ item().title }}
|
|
479
549
|
</div>
|
|
@@ -493,7 +563,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
493
563
|
type="button"
|
|
494
564
|
[class]="
|
|
495
565
|
cn(
|
|
496
|
-
'ui-nav-text group/ni flex w-full items-center gap-3 rounded-
|
|
566
|
+
'ui-nav-text group/ni flex w-full items-center gap-3 rounded-full p-3 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
497
567
|
isTrailActive() && 'text-primary',
|
|
498
568
|
item().classes?.wrapper
|
|
499
569
|
)
|
|
@@ -506,7 +576,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
506
576
|
[matTooltipDisabled]="!compact()"
|
|
507
577
|
(click)="toggleGroup()">
|
|
508
578
|
@if (collapsableItem().icon) {
|
|
509
|
-
<
|
|
579
|
+
<span
|
|
580
|
+
[class]="
|
|
581
|
+
cn(
|
|
582
|
+
'inline-flex shrink-0 items-center justify-center',
|
|
583
|
+
open && 'h-7 w-7 rounded-full border border-brand'
|
|
584
|
+
)
|
|
585
|
+
">
|
|
586
|
+
<ui-nav-icon [name]="collapsableItem().icon!" [size]="18" [class]="item().classes?.icon ?? ''" />
|
|
587
|
+
</span>
|
|
510
588
|
}
|
|
511
589
|
@if (!compact()) {
|
|
512
590
|
<span [class]="cn('flex-1 truncate text-left', item().classes?.title)">
|
|
@@ -522,7 +600,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
522
600
|
}
|
|
523
601
|
</button>
|
|
524
602
|
@if (!compact() && open) {
|
|
525
|
-
<div
|
|
603
|
+
<div
|
|
604
|
+
[id]="id + '-panel'"
|
|
605
|
+
role="region"
|
|
606
|
+
class="relative ml-6.5 mt-0.5 flex flex-col gap-0.5 pl-3 before:absolute before:bottom-0 before:left-0 before:-top-3.5 before:w-px before:bg-border before:content-['']">
|
|
526
607
|
@for (child of collapsableItem().children; track child.id) {
|
|
527
608
|
<ui-nav-item [item]="child" [level]="level() + 1" [compact]="false" />
|
|
528
609
|
}
|
|
@@ -693,6 +774,7 @@ class SidebarComponent {
|
|
|
693
774
|
return explicit.length > 0 ? explicit : this.nav.getItems(this.navigationId())();
|
|
694
775
|
}, ...(ngDevMode ? [{ debugName: "resolvedItems" }] : /* istanbul ignore next */ []));
|
|
695
776
|
hovered = signal(false, ...(ngDevMode ? [{ debugName: "hovered" }] : /* istanbul ignore next */ []));
|
|
777
|
+
suppressHoverUntilLeave = signal(false, ...(ngDevMode ? [{ debugName: "suppressHoverUntilLeave" }] : /* istanbul ignore next */ []));
|
|
696
778
|
drawerTpl = viewChild.required('drawerTpl');
|
|
697
779
|
drawerRef = null;
|
|
698
780
|
focusTrap = null;
|
|
@@ -702,8 +784,19 @@ class SidebarComponent {
|
|
|
702
784
|
initialValue: false,
|
|
703
785
|
});
|
|
704
786
|
isMobile = computed(() => this.autoMobile() && this.isMobileMedia(), ...(ngDevMode ? [{ debugName: "isMobile" }] : /* istanbul ignore next */ []));
|
|
705
|
-
|
|
706
|
-
|
|
787
|
+
resolvedCollapsed = computed(() => {
|
|
788
|
+
if (this.nav.hasStoredSidebarCollapse()) {
|
|
789
|
+
return this.nav.collapsed();
|
|
790
|
+
}
|
|
791
|
+
return this.appearance() === 'thin';
|
|
792
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedCollapsed" }] : /* istanbul ignore next */ []));
|
|
793
|
+
resolvedAppearance = computed(() => {
|
|
794
|
+
return this.resolvedCollapsed() ? 'thin' : 'default';
|
|
795
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedAppearance" }] : /* istanbul ignore next */ []));
|
|
796
|
+
hoverActive = computed(() => this.hovered() && !this.suppressHoverUntilLeave(), ...(ngDevMode ? [{ debugName: "hoverActive" }] : /* istanbul ignore next */ []));
|
|
797
|
+
isExpanded = computed(() => !this.resolvedCollapsed() || this.hoverActive(), ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
|
|
798
|
+
isCompact = computed(() => !this.isMobile() && this.resolvedCollapsed() && !this.hoverActive(), ...(ngDevMode ? [{ debugName: "isCompact" }] : /* istanbul ignore next */ []));
|
|
799
|
+
toggleButtonLabel = computed(() => this.resolvedCollapsed() ? 'Expand sidebar' : 'Collapse sidebar', ...(ngDevMode ? [{ debugName: "toggleButtonLabel" }] : /* istanbul ignore next */ []));
|
|
707
800
|
constructor() {
|
|
708
801
|
// Auto-register items ke service untuk active trail (hanya jika input non-kosong).
|
|
709
802
|
effect(() => {
|
|
@@ -723,24 +816,64 @@ class SidebarComponent {
|
|
|
723
816
|
this.destroyRef.onDestroy(() => this.closeDrawer());
|
|
724
817
|
}
|
|
725
818
|
hostClasses = computed(() => {
|
|
726
|
-
const base = ['relative flex shrink-0
|
|
727
|
-
|
|
728
|
-
if (appearance === 'thin')
|
|
819
|
+
const base = ['relative flex shrink-0 text-foreground', 'transition-[width] duration-200 ease-out'];
|
|
820
|
+
if (this.resolvedCollapsed())
|
|
729
821
|
base.push('w-16');
|
|
730
822
|
else
|
|
731
823
|
base.push('[width:17.5rem]');
|
|
732
824
|
if (this.position() === 'right')
|
|
733
|
-
base.push('border-l');
|
|
734
|
-
else
|
|
735
|
-
base.push('border-r');
|
|
736
|
-
base.push('border-border');
|
|
825
|
+
base.push('border-l', 'border-brand');
|
|
737
826
|
return [...base, this.class()].join(' ');
|
|
738
827
|
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
828
|
+
headerClasses = computed(() => {
|
|
829
|
+
const base = ['flex h-12 items-center gap-2 border-b border-brand'];
|
|
830
|
+
if (this.isCompact()) {
|
|
831
|
+
base.push('justify-center px-2');
|
|
832
|
+
}
|
|
833
|
+
return base.join(' ');
|
|
834
|
+
}, ...(ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []));
|
|
835
|
+
headerSlotClasses = computed(() => {
|
|
836
|
+
const base = ['min-w-0'];
|
|
837
|
+
if (this.isCompact()) {
|
|
838
|
+
base.push('flex flex-1 items-center justify-center overflow-hidden', '[&>[sidebar-header]>*]:mx-auto', '[&>[sidebar-header]>*]:max-w-full', '[&>[sidebar-header]>*]:shrink-0');
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
base.push('flex min-w-0 flex-1 items-center');
|
|
842
|
+
}
|
|
843
|
+
return base.join(' ');
|
|
844
|
+
}, ...(ngDevMode ? [{ debugName: "headerSlotClasses" }] : /* istanbul ignore next */ []));
|
|
845
|
+
navClasses = computed(() => {
|
|
846
|
+
const base = ['flex-1 overflow-y-auto overflow-x-hidden'];
|
|
847
|
+
if (this.isCompact()) {
|
|
848
|
+
base.push('px-2', '[&_.ui-nav-text]:mx-auto', '[&_.ui-nav-text]:w-10', '[&_.ui-nav-text]:justify-center', '[&_.ui-nav-text]:px-0');
|
|
849
|
+
}
|
|
850
|
+
return base.join(' ');
|
|
851
|
+
}, ...(ngDevMode ? [{ debugName: "navClasses" }] : /* istanbul ignore next */ []));
|
|
852
|
+
footerClasses = computed(() => {
|
|
853
|
+
const base = ['h-12 border-t border-brand'];
|
|
854
|
+
if (this.isCompact()) {
|
|
855
|
+
base.push('flex items-center justify-center px-2');
|
|
856
|
+
}
|
|
857
|
+
return base.join(' ');
|
|
858
|
+
}, ...(ngDevMode ? [{ debugName: "footerClasses" }] : /* istanbul ignore next */ []));
|
|
859
|
+
footerSlotClasses = computed(() => {
|
|
860
|
+
const base = ['h-full'];
|
|
861
|
+
if (this.isCompact()) {
|
|
862
|
+
base.push('flex h-full items-center justify-center overflow-hidden', '[&>[sidebar-footer]>*]:mx-auto', '[&>[sidebar-footer]>*]:w-auto', '[&>[sidebar-footer]>*]:max-w-full', '[&>[sidebar-footer]>*]:justify-center', '[&>[sidebar-footer]>*]:gap-0', '[&>[sidebar-footer]>*]:px-0', '[&>[sidebar-footer]>*>*:first-child]:mx-auto', '[&>[sidebar-footer]>*>*:nth-child(n+2)]:hidden');
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
base.push('w-full');
|
|
866
|
+
}
|
|
867
|
+
return base.join(' ');
|
|
868
|
+
}, ...(ngDevMode ? [{ debugName: "footerSlotClasses" }] : /* istanbul ignore next */ []));
|
|
739
869
|
innerClasses = computed(() => {
|
|
740
|
-
const overlayActive = this.
|
|
870
|
+
const overlayActive = this.resolvedCollapsed() && this.hoverActive();
|
|
741
871
|
const base = ['flex h-full flex-col transition-[width] duration-200 ease-out'];
|
|
872
|
+
if (this.resolvedCollapsed()) {
|
|
873
|
+
base.push('bg-background');
|
|
874
|
+
}
|
|
742
875
|
if (overlayActive) {
|
|
743
|
-
base.push('absolute inset-y-0 z-30
|
|
876
|
+
base.push('absolute inset-y-0 z-30 shadow-xl [width:17.5rem]', this.position() === 'right' ? 'right-0 border-l border-brand' : 'left-0 border-r border-brand');
|
|
744
877
|
}
|
|
745
878
|
else {
|
|
746
879
|
base.push('w-full');
|
|
@@ -748,16 +881,25 @@ class SidebarComponent {
|
|
|
748
881
|
return base.join(' ');
|
|
749
882
|
}, ...(ngDevMode ? [{ debugName: "innerClasses" }] : /* istanbul ignore next */ []));
|
|
750
883
|
onHoverEnter() {
|
|
751
|
-
if (this.
|
|
752
|
-
|
|
884
|
+
if (!this.resolvedCollapsed() || this.isMobile() || this.suppressHoverUntilLeave())
|
|
885
|
+
return;
|
|
886
|
+
this.hovered.set(true);
|
|
753
887
|
}
|
|
754
888
|
onHoverLeave() {
|
|
755
|
-
|
|
889
|
+
this.suppressHoverUntilLeave.set(false);
|
|
890
|
+
if (this.resolvedCollapsed())
|
|
756
891
|
this.hovered.set(false);
|
|
757
892
|
}
|
|
893
|
+
toggleAppearance(event) {
|
|
894
|
+
event.stopPropagation();
|
|
895
|
+
const nextCollapsed = !this.resolvedCollapsed();
|
|
896
|
+
this.nav.setCollapsed(nextCollapsed);
|
|
897
|
+
this.hovered.set(false);
|
|
898
|
+
this.suppressHoverUntilLeave.set(nextCollapsed);
|
|
899
|
+
}
|
|
758
900
|
/** Touch fallback: tap pada strip thin (ketika belum expanded) untuk expand. */
|
|
759
901
|
onHostClick(event) {
|
|
760
|
-
if (this.
|
|
902
|
+
if (!this.resolvedCollapsed() || this.isMobile())
|
|
761
903
|
return;
|
|
762
904
|
if (this.hovered())
|
|
763
905
|
return;
|
|
@@ -782,7 +924,7 @@ class SidebarComponent {
|
|
|
782
924
|
hasBackdrop: true,
|
|
783
925
|
backdropClass: 'cdk-overlay-dark-backdrop',
|
|
784
926
|
scrollStrategy: this.overlay.scrollStrategies.block(),
|
|
785
|
-
panelClass: ['
|
|
927
|
+
panelClass: ['sidebar-drawer'],
|
|
786
928
|
});
|
|
787
929
|
const portal = new TemplatePortal(this.drawerTpl(), this.vcr);
|
|
788
930
|
const viewRef = this.drawerRef.attach(portal);
|
|
@@ -810,25 +952,41 @@ class SidebarComponent {
|
|
|
810
952
|
this.previouslyFocused?.focus?.();
|
|
811
953
|
this.previouslyFocused = null;
|
|
812
954
|
}
|
|
813
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
814
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
955
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
956
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: SidebarComponent, isStandalone: true, selector: "sidebar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, navigationId: { classPropertyName: "navigationId", publicName: "navigationId", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, autoMobile: { classPropertyName: "autoMobile", publicName: "autoMobile", isSignal: true, isRequired: false, transformFunction: null }, autoRegister: { classPropertyName: "autoRegister", publicName: "autoRegister", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, listeners: { "mouseenter": "onHoverEnter()", "mouseleave": "onHoverLeave()", "focusin": "onHoverEnter()", "click": "onHostClick($event)" }, properties: { "attr.aria-label": "ariaLabel()", "class": "hostClasses()", "attr.data-appearance": "resolvedAppearance()", "attr.data-position": "position()", "attr.data-expanded": "isExpanded()", "hidden": "isMobile()" } }, viewQueries: [{ propertyName: "drawerTpl", first: true, predicate: ["drawerTpl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
815
957
|
<div [class]="innerClasses()">
|
|
816
958
|
<ng-container [ngTemplateOutlet]="body" />
|
|
817
959
|
</div>
|
|
818
960
|
|
|
819
961
|
<ng-template #body>
|
|
820
962
|
@if (header()) {
|
|
821
|
-
<div class="
|
|
822
|
-
<
|
|
963
|
+
<div [class]="headerClasses()">
|
|
964
|
+
<div [class]="headerSlotClasses()">
|
|
965
|
+
<ng-content select="[sidebar-header]" />
|
|
966
|
+
</div>
|
|
967
|
+
@if (!isMobile() && !isCompact()) {
|
|
968
|
+
<button
|
|
969
|
+
type="button"
|
|
970
|
+
data-sidebar-toggle
|
|
971
|
+
class="ml-auto mr-2 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
|
972
|
+
[attr.aria-label]="toggleButtonLabel()"
|
|
973
|
+
[attr.title]="toggleButtonLabel()"
|
|
974
|
+
[attr.aria-pressed]="resolvedAppearance() === 'thin'"
|
|
975
|
+
(click)="toggleAppearance($event)">
|
|
976
|
+
<ui-nav-icon name="view_sidebar" [size]="18" class="text-current" />
|
|
977
|
+
</button>
|
|
978
|
+
}
|
|
823
979
|
</div>
|
|
824
980
|
}
|
|
825
|
-
<nav class="
|
|
981
|
+
<nav [class]="navClasses()">
|
|
826
982
|
@for (item of resolvedItems(); track item.id) {
|
|
827
983
|
<ui-nav-item [item]="item" [compact]="isCompact()" />
|
|
828
984
|
}
|
|
829
985
|
</nav>
|
|
830
|
-
<div class="
|
|
831
|
-
<
|
|
986
|
+
<div [class]="footerClasses()">
|
|
987
|
+
<div [class]="footerSlotClasses()">
|
|
988
|
+
<ng-content select="[sidebar-footer]" />
|
|
989
|
+
</div>
|
|
832
990
|
</div>
|
|
833
991
|
</ng-template>
|
|
834
992
|
|
|
@@ -837,25 +995,25 @@ class SidebarComponent {
|
|
|
837
995
|
role="dialog"
|
|
838
996
|
aria-modal="true"
|
|
839
997
|
[attr.aria-label]="ariaLabel()"
|
|
840
|
-
class="flex h-full w-72 max-w-[85vw] flex-col
|
|
998
|
+
class="flex h-full w-72 max-w-[85vw] flex-col text-foreground shadow-xl"
|
|
841
999
|
[class.border-l]="position() === 'right'"
|
|
842
|
-
[class.border-
|
|
1000
|
+
[class.border-brand]="position() === 'right'">
|
|
843
1001
|
<ng-container [ngTemplateOutlet]="body" />
|
|
844
1002
|
</div>
|
|
845
1003
|
</ng-template>
|
|
846
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: UiNavItemComponent, selector: "ui-nav-item", inputs: ["item", "level", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1004
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: UiNavIconComponent, selector: "ui-nav-icon", inputs: ["name", "class", "size"] }, { kind: "component", type: UiNavItemComponent, selector: "ui-nav-item", inputs: ["item", "level", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
847
1005
|
}
|
|
848
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1006
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: SidebarComponent, decorators: [{
|
|
849
1007
|
type: Component,
|
|
850
1008
|
args: [{
|
|
851
|
-
selector: '
|
|
1009
|
+
selector: 'sidebar',
|
|
852
1010
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
853
|
-
imports: [NgTemplateOutlet, UiNavItemComponent],
|
|
1011
|
+
imports: [NgTemplateOutlet, UiNavIconComponent, UiNavItemComponent],
|
|
854
1012
|
host: {
|
|
855
1013
|
role: 'navigation',
|
|
856
1014
|
'[attr.aria-label]': 'ariaLabel()',
|
|
857
1015
|
'[class]': 'hostClasses()',
|
|
858
|
-
'[attr.data-appearance]': '
|
|
1016
|
+
'[attr.data-appearance]': 'resolvedAppearance()',
|
|
859
1017
|
'[attr.data-position]': 'position()',
|
|
860
1018
|
'[attr.data-expanded]': 'isExpanded()',
|
|
861
1019
|
'[hidden]': 'isMobile()',
|
|
@@ -871,17 +1029,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
871
1029
|
|
|
872
1030
|
<ng-template #body>
|
|
873
1031
|
@if (header()) {
|
|
874
|
-
<div class="
|
|
875
|
-
<
|
|
1032
|
+
<div [class]="headerClasses()">
|
|
1033
|
+
<div [class]="headerSlotClasses()">
|
|
1034
|
+
<ng-content select="[sidebar-header]" />
|
|
1035
|
+
</div>
|
|
1036
|
+
@if (!isMobile() && !isCompact()) {
|
|
1037
|
+
<button
|
|
1038
|
+
type="button"
|
|
1039
|
+
data-sidebar-toggle
|
|
1040
|
+
class="ml-auto mr-2 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
|
1041
|
+
[attr.aria-label]="toggleButtonLabel()"
|
|
1042
|
+
[attr.title]="toggleButtonLabel()"
|
|
1043
|
+
[attr.aria-pressed]="resolvedAppearance() === 'thin'"
|
|
1044
|
+
(click)="toggleAppearance($event)">
|
|
1045
|
+
<ui-nav-icon name="view_sidebar" [size]="18" class="text-current" />
|
|
1046
|
+
</button>
|
|
1047
|
+
}
|
|
876
1048
|
</div>
|
|
877
1049
|
}
|
|
878
|
-
<nav class="
|
|
1050
|
+
<nav [class]="navClasses()">
|
|
879
1051
|
@for (item of resolvedItems(); track item.id) {
|
|
880
1052
|
<ui-nav-item [item]="item" [compact]="isCompact()" />
|
|
881
1053
|
}
|
|
882
1054
|
</nav>
|
|
883
|
-
<div class="
|
|
884
|
-
<
|
|
1055
|
+
<div [class]="footerClasses()">
|
|
1056
|
+
<div [class]="footerSlotClasses()">
|
|
1057
|
+
<ng-content select="[sidebar-footer]" />
|
|
1058
|
+
</div>
|
|
885
1059
|
</div>
|
|
886
1060
|
</ng-template>
|
|
887
1061
|
|
|
@@ -890,9 +1064,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
890
1064
|
role="dialog"
|
|
891
1065
|
aria-modal="true"
|
|
892
1066
|
[attr.aria-label]="ariaLabel()"
|
|
893
|
-
class="flex h-full w-72 max-w-[85vw] flex-col
|
|
1067
|
+
class="flex h-full w-72 max-w-[85vw] flex-col text-foreground shadow-xl"
|
|
894
1068
|
[class.border-l]="position() === 'right'"
|
|
895
|
-
[class.border-
|
|
1069
|
+
[class.border-brand]="position() === 'right'">
|
|
896
1070
|
<ng-container [ngTemplateOutlet]="body" />
|
|
897
1071
|
</div>
|
|
898
1072
|
</ng-template>
|
|
@@ -902,10 +1076,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
902
1076
|
|
|
903
1077
|
/**
|
|
904
1078
|
* Horizontal navigation (topbar) — shadcn-styled.
|
|
905
|
-
*
|
|
906
|
-
* Variants:
|
|
907
|
-
* - `default`: horizontal list; item `collapsable` buka dropdown
|
|
908
|
-
* - `megamenu`: item `mega` buka panel full-width multi-kolom
|
|
909
1079
|
*/
|
|
910
1080
|
class TopbarComponent {
|
|
911
1081
|
nav = inject(NavigationService);
|
|
@@ -924,7 +1094,6 @@ class TopbarComponent {
|
|
|
924
1094
|
/** Tampilkan hamburger di `< md` yang men-toggle mobile drawer sidebar. */
|
|
925
1095
|
showHamburger = input(true, ...(ngDevMode ? [{ debugName: "showHamburger" }] : /* istanbul ignore next */ []));
|
|
926
1096
|
hamburgerLabel = input('Open navigation', ...(ngDevMode ? [{ debugName: "hamburgerLabel" }] : /* istanbul ignore next */ []));
|
|
927
|
-
topbarHeight = 'var(--layout-topbar-height)';
|
|
928
1097
|
/** Resolved items: input jika disediakan, fallback ke registry NavigationService. */
|
|
929
1098
|
resolvedItems = computed(() => {
|
|
930
1099
|
const explicit = this.items();
|
|
@@ -933,7 +1102,6 @@ class TopbarComponent {
|
|
|
933
1102
|
openId = signal(null, ...(ngDevMode ? [{ debugName: "openId" }] : /* istanbul ignore next */ []));
|
|
934
1103
|
active = null;
|
|
935
1104
|
dropdownTpl = viewChild.required('dropdownTpl');
|
|
936
|
-
megaTpl = viewChild.required('megaTpl');
|
|
937
1105
|
constructor() {
|
|
938
1106
|
effect(() => {
|
|
939
1107
|
const explicit = this.items();
|
|
@@ -943,11 +1111,13 @@ class TopbarComponent {
|
|
|
943
1111
|
this.destroyRef.onDestroy(() => this.closeAll());
|
|
944
1112
|
}
|
|
945
1113
|
hostClasses = computed(() => {
|
|
946
|
-
return [
|
|
947
|
-
'sticky top-0 z-20 flex w-full items-center border-b border-border bg-background text-foreground',
|
|
948
|
-
this.class(),
|
|
949
|
-
].join(' ');
|
|
1114
|
+
return ['sticky top-0 z-20 flex h-11 w-full items-center', this.class()].join(' ');
|
|
950
1115
|
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
1116
|
+
endSlotClasses = computed(() => {
|
|
1117
|
+
const base = ['flex h-full shrink-0 items-center justify-end gap-2 overflow-hidden'];
|
|
1118
|
+
base.push('[&>[topbar-end]]:flex', '[&>[topbar-end]]:min-w-0', '[&>[topbar-end]]:max-w-full', '[&>[topbar-end]]:items-center', '[&>[topbar-end]]:justify-end', '[&>[topbar-end]]:gap-2', '[&>[topbar-end]>*]:w-auto', '[&>[topbar-end]>*]:max-w-full', '[&>[topbar-end]>*]:justify-end', '[&>[topbar-end]>*]:gap-0', '[&>[topbar-end]>*]:px-2', '[&>[topbar-end]>*>*:first-child]:ml-auto', '[&>[topbar-end]>*>*:nth-child(n+2)]:hidden');
|
|
1119
|
+
return base.join(' ');
|
|
1120
|
+
}, ...(ngDevMode ? [{ debugName: "endSlotClasses" }] : /* istanbul ignore next */ []));
|
|
951
1121
|
asBasic(i) {
|
|
952
1122
|
return i;
|
|
953
1123
|
}
|
|
@@ -957,36 +1127,9 @@ class TopbarComponent {
|
|
|
957
1127
|
asGroup(i) {
|
|
958
1128
|
return i;
|
|
959
1129
|
}
|
|
960
|
-
asMega(i) {
|
|
961
|
-
return i;
|
|
962
|
-
}
|
|
963
1130
|
isItemActive(id) {
|
|
964
1131
|
return this.nav.isActive(id);
|
|
965
1132
|
}
|
|
966
|
-
megaGridClasses(columns) {
|
|
967
|
-
const c = Math.min(Math.max(columns ?? 4, 1), 6);
|
|
968
|
-
const classes = ['grid', 'gap-6'];
|
|
969
|
-
switch (c) {
|
|
970
|
-
case 1:
|
|
971
|
-
classes.push('grid-cols-1');
|
|
972
|
-
break;
|
|
973
|
-
case 2:
|
|
974
|
-
classes.push('md:grid-cols-2');
|
|
975
|
-
break;
|
|
976
|
-
case 3:
|
|
977
|
-
classes.push('md:grid-cols-3');
|
|
978
|
-
break;
|
|
979
|
-
case 5:
|
|
980
|
-
classes.push('md:grid-cols-5');
|
|
981
|
-
break;
|
|
982
|
-
case 6:
|
|
983
|
-
classes.push('md:grid-cols-6');
|
|
984
|
-
break;
|
|
985
|
-
default:
|
|
986
|
-
classes.push('md:grid-cols-4');
|
|
987
|
-
}
|
|
988
|
-
return classes.join(' ');
|
|
989
|
-
}
|
|
990
1133
|
toggleDropdown(trigger, item) {
|
|
991
1134
|
if (this.openId() === item.id)
|
|
992
1135
|
this.closeAll();
|
|
@@ -997,67 +1140,36 @@ class TopbarComponent {
|
|
|
997
1140
|
if (this.openId() === item.id)
|
|
998
1141
|
return;
|
|
999
1142
|
this.closeAll();
|
|
1000
|
-
this.attach(trigger, item, this.dropdownTpl()
|
|
1143
|
+
this.attach(trigger, item, this.dropdownTpl());
|
|
1001
1144
|
}
|
|
1002
|
-
|
|
1003
|
-
if (this.openId() === item.id)
|
|
1004
|
-
this.closeAll();
|
|
1005
|
-
else
|
|
1006
|
-
this.openMega(trigger, item);
|
|
1007
|
-
}
|
|
1008
|
-
openMega(trigger, item) {
|
|
1009
|
-
if (this.openId() === item.id)
|
|
1010
|
-
return;
|
|
1011
|
-
this.closeAll();
|
|
1012
|
-
this.attach(trigger, item, this.megaTpl(), /*fullWidth*/ true);
|
|
1013
|
-
}
|
|
1014
|
-
attach(trigger, item, tpl, fullWidth) {
|
|
1145
|
+
attach(trigger, item, tpl) {
|
|
1015
1146
|
const strategy = this.overlay
|
|
1016
1147
|
.position()
|
|
1017
1148
|
.flexibleConnectedTo(trigger)
|
|
1018
1149
|
.withFlexibleDimensions(false)
|
|
1019
1150
|
.withPush(false)
|
|
1020
|
-
.withPositions(
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
]
|
|
1037
|
-
: [
|
|
1038
|
-
{
|
|
1039
|
-
originX: 'start',
|
|
1040
|
-
originY: 'bottom',
|
|
1041
|
-
overlayX: 'start',
|
|
1042
|
-
overlayY: 'top',
|
|
1043
|
-
offsetY: 4,
|
|
1044
|
-
},
|
|
1045
|
-
{
|
|
1046
|
-
originX: 'start',
|
|
1047
|
-
originY: 'top',
|
|
1048
|
-
overlayX: 'start',
|
|
1049
|
-
overlayY: 'bottom',
|
|
1050
|
-
offsetY: -4,
|
|
1051
|
-
},
|
|
1052
|
-
]);
|
|
1151
|
+
.withPositions([
|
|
1152
|
+
{
|
|
1153
|
+
originX: 'start',
|
|
1154
|
+
originY: 'bottom',
|
|
1155
|
+
overlayX: 'start',
|
|
1156
|
+
overlayY: 'top',
|
|
1157
|
+
offsetY: 4,
|
|
1158
|
+
},
|
|
1159
|
+
{
|
|
1160
|
+
originX: 'start',
|
|
1161
|
+
originY: 'top',
|
|
1162
|
+
overlayX: 'start',
|
|
1163
|
+
overlayY: 'bottom',
|
|
1164
|
+
offsetY: -4,
|
|
1165
|
+
},
|
|
1166
|
+
]);
|
|
1053
1167
|
const ref = this.overlay.create({
|
|
1054
1168
|
positionStrategy: strategy,
|
|
1055
1169
|
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
1056
1170
|
hasBackdrop: true,
|
|
1057
1171
|
backdropClass: 'cdk-overlay-transparent-backdrop',
|
|
1058
|
-
panelClass:
|
|
1059
|
-
width: fullWidth ? '100vw' : undefined,
|
|
1060
|
-
maxWidth: fullWidth ? '100vw' : undefined,
|
|
1172
|
+
panelClass: ['ui-dropdown-panel'],
|
|
1061
1173
|
});
|
|
1062
1174
|
const portal = new TemplatePortal(tpl, this.vcr, { $implicit: item });
|
|
1063
1175
|
ref.attach(portal);
|
|
@@ -1107,7 +1219,7 @@ class TopbarComponent {
|
|
|
1107
1219
|
triggers[nextIndex].focus();
|
|
1108
1220
|
}
|
|
1109
1221
|
}
|
|
1110
|
-
/** Arrow-key navigation dalam dropdown
|
|
1222
|
+
/** Arrow-key navigation dalam dropdown panel. */
|
|
1111
1223
|
onPanelKeydown(event) {
|
|
1112
1224
|
const key = event.key;
|
|
1113
1225
|
if (key !== 'ArrowDown' &&
|
|
@@ -1148,10 +1260,10 @@ class TopbarComponent {
|
|
|
1148
1260
|
const items = this.collectPanelFocusables(panel);
|
|
1149
1261
|
items[0]?.focus();
|
|
1150
1262
|
}
|
|
1151
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.
|
|
1152
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.
|
|
1263
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: TopbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1264
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: TopbarComponent, isStandalone: true, selector: "topbar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, navigationId: { classPropertyName: "navigationId", publicName: "navigationId", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, autoRegister: { classPropertyName: "autoRegister", publicName: "autoRegister", isSignal: true, isRequired: false, transformFunction: null }, showHamburger: { classPropertyName: "showHamburger", publicName: "showHamburger", isSignal: true, isRequired: false, transformFunction: null }, hamburgerLabel: { classPropertyName: "hamburgerLabel", publicName: "hamburgerLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "navigation" }, properties: { "attr.aria-label": "ariaLabel()", "class": "hostClasses()", "attr.data-appearance": "appearance()" } }, viewQueries: [{ propertyName: "dropdownTpl", first: true, predicate: ["dropdownTpl"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1153
1265
|
<div class="flex h-full w-full items-center gap-3 px-1">
|
|
1154
|
-
<div data-
|
|
1266
|
+
<div data-topbar-slot="start" class="flex shrink-0 items-center gap-2">
|
|
1155
1267
|
@if (showHamburger()) {
|
|
1156
1268
|
<button
|
|
1157
1269
|
type="button"
|
|
@@ -1162,10 +1274,10 @@ class TopbarComponent {
|
|
|
1162
1274
|
<ui-nav-icon name="menu" [size]="18" />
|
|
1163
1275
|
</button>
|
|
1164
1276
|
}
|
|
1165
|
-
<ng-content select="[
|
|
1277
|
+
<ng-content select="[topbar-start]" />
|
|
1166
1278
|
</div>
|
|
1167
1279
|
|
|
1168
|
-
<div data-
|
|
1280
|
+
<div data-topbar-slot="nav" class="flex min-w-0 flex-1 items-center justify-center">
|
|
1169
1281
|
<ul
|
|
1170
1282
|
class="flex min-w-0 flex-1 items-center justify-center gap-1"
|
|
1171
1283
|
role="menubar"
|
|
@@ -1228,25 +1340,6 @@ class TopbarComponent {
|
|
|
1228
1340
|
<ui-nav-icon name="expand_more" [size]="18" />
|
|
1229
1341
|
</button>
|
|
1230
1342
|
}
|
|
1231
|
-
@case ('mega') {
|
|
1232
|
-
@let mega = asMega(item);
|
|
1233
|
-
<button
|
|
1234
|
-
#trigger
|
|
1235
|
-
type="button"
|
|
1236
|
-
role="menuitem"
|
|
1237
|
-
class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
1238
|
-
[class.text-primary]="isItemActive(mega.id)"
|
|
1239
|
-
[attr.aria-expanded]="openId() === mega.id"
|
|
1240
|
-
[attr.aria-haspopup]="'menu'"
|
|
1241
|
-
(click)="toggleMega(trigger, item)"
|
|
1242
|
-
(mouseenter)="openMega(trigger, item)">
|
|
1243
|
-
@if (mega.icon) {
|
|
1244
|
-
<ui-nav-icon [name]="mega.icon" [size]="18" />
|
|
1245
|
-
}
|
|
1246
|
-
<span>{{ mega.title }}</span>
|
|
1247
|
-
<ui-nav-icon name="expand_more" [size]="18" />
|
|
1248
|
-
</button>
|
|
1249
|
-
}
|
|
1250
1343
|
@default {
|
|
1251
1344
|
<span class="ui-nav-heading px-3 py-2 text-muted-foreground">
|
|
1252
1345
|
{{ item.title }}
|
|
@@ -1258,51 +1351,25 @@ class TopbarComponent {
|
|
|
1258
1351
|
</ul>
|
|
1259
1352
|
</div>
|
|
1260
1353
|
|
|
1261
|
-
<div data-
|
|
1262
|
-
<ng-content select="[
|
|
1354
|
+
<div data-topbar-slot="end" [class]="endSlotClasses()">
|
|
1355
|
+
<ng-content select="[topbar-end]" />
|
|
1263
1356
|
</div>
|
|
1264
1357
|
</div>
|
|
1265
1358
|
|
|
1266
1359
|
<!-- Dropdown template -->
|
|
1267
1360
|
<ng-template #dropdownTpl let-item>
|
|
1268
|
-
<div
|
|
1269
|
-
role="menu"
|
|
1270
|
-
class="min-w-56 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md"
|
|
1271
|
-
(keydown)="onPanelKeydown($event)">
|
|
1361
|
+
<div role="menu" class="min-w-56 border border-brand bg-background/95 p-1" (keydown)="onPanelKeydown($event)">
|
|
1272
1362
|
@for (child of item.children; track child.id) {
|
|
1273
1363
|
<ui-nav-item [item]="child" />
|
|
1274
1364
|
}
|
|
1275
1365
|
</div>
|
|
1276
1366
|
</ng-template>
|
|
1277
|
-
|
|
1278
|
-
<!-- Mega panel template -->
|
|
1279
|
-
<ng-template #megaTpl let-item>
|
|
1280
|
-
<div
|
|
1281
|
-
role="menu"
|
|
1282
|
-
class="w-screen max-w-[min(90vw,72rem)] rounded-md border border-border bg-popover p-6 text-popover-foreground shadow-lg"
|
|
1283
|
-
(keydown)="onPanelKeydown($event)">
|
|
1284
|
-
<div [class]="megaGridClasses(item.columns)">
|
|
1285
|
-
@for (col of item.children; track col.id) {
|
|
1286
|
-
<div>
|
|
1287
|
-
<div class="ui-nav-heading mb-2 text-muted-foreground">
|
|
1288
|
-
{{ col.title }}
|
|
1289
|
-
</div>
|
|
1290
|
-
<div class="flex flex-col gap-0.5">
|
|
1291
|
-
@for (leaf of col.children ?? []; track leaf.id) {
|
|
1292
|
-
<ui-nav-item [item]="leaf" />
|
|
1293
|
-
}
|
|
1294
|
-
</div>
|
|
1295
|
-
</div>
|
|
1296
|
-
}
|
|
1297
|
-
</div>
|
|
1298
|
-
</div>
|
|
1299
|
-
</ng-template>
|
|
1300
1367
|
`, isInline: true, dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: UiNavIconComponent, selector: "ui-nav-icon", inputs: ["name", "class", "size"] }, { kind: "component", type: UiNavItemComponent, selector: "ui-nav-item", inputs: ["item", "level", "compact"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1301
1368
|
}
|
|
1302
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.
|
|
1369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: TopbarComponent, decorators: [{
|
|
1303
1370
|
type: Component,
|
|
1304
1371
|
args: [{
|
|
1305
|
-
selector: '
|
|
1372
|
+
selector: 'topbar',
|
|
1306
1373
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1307
1374
|
imports: [RouterLink, RouterLinkActive, UiNavIconComponent, UiNavItemComponent],
|
|
1308
1375
|
host: {
|
|
@@ -1310,11 +1377,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1310
1377
|
'[attr.aria-label]': 'ariaLabel()',
|
|
1311
1378
|
'[class]': 'hostClasses()',
|
|
1312
1379
|
'[attr.data-appearance]': 'appearance()',
|
|
1313
|
-
'[style.height]': 'topbarHeight',
|
|
1314
1380
|
},
|
|
1315
1381
|
template: `
|
|
1316
1382
|
<div class="flex h-full w-full items-center gap-3 px-1">
|
|
1317
|
-
<div data-
|
|
1383
|
+
<div data-topbar-slot="start" class="flex shrink-0 items-center gap-2">
|
|
1318
1384
|
@if (showHamburger()) {
|
|
1319
1385
|
<button
|
|
1320
1386
|
type="button"
|
|
@@ -1325,10 +1391,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1325
1391
|
<ui-nav-icon name="menu" [size]="18" />
|
|
1326
1392
|
</button>
|
|
1327
1393
|
}
|
|
1328
|
-
<ng-content select="[
|
|
1394
|
+
<ng-content select="[topbar-start]" />
|
|
1329
1395
|
</div>
|
|
1330
1396
|
|
|
1331
|
-
<div data-
|
|
1397
|
+
<div data-topbar-slot="nav" class="flex min-w-0 flex-1 items-center justify-center">
|
|
1332
1398
|
<ul
|
|
1333
1399
|
class="flex min-w-0 flex-1 items-center justify-center gap-1"
|
|
1334
1400
|
role="menubar"
|
|
@@ -1391,25 +1457,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1391
1457
|
<ui-nav-icon name="expand_more" [size]="18" />
|
|
1392
1458
|
</button>
|
|
1393
1459
|
}
|
|
1394
|
-
@case ('mega') {
|
|
1395
|
-
@let mega = asMega(item);
|
|
1396
|
-
<button
|
|
1397
|
-
#trigger
|
|
1398
|
-
type="button"
|
|
1399
|
-
role="menuitem"
|
|
1400
|
-
class="ui-nav-text inline-flex items-center gap-2 rounded-md px-3 py-2 text-foreground/80 hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
1401
|
-
[class.text-primary]="isItemActive(mega.id)"
|
|
1402
|
-
[attr.aria-expanded]="openId() === mega.id"
|
|
1403
|
-
[attr.aria-haspopup]="'menu'"
|
|
1404
|
-
(click)="toggleMega(trigger, item)"
|
|
1405
|
-
(mouseenter)="openMega(trigger, item)">
|
|
1406
|
-
@if (mega.icon) {
|
|
1407
|
-
<ui-nav-icon [name]="mega.icon" [size]="18" />
|
|
1408
|
-
}
|
|
1409
|
-
<span>{{ mega.title }}</span>
|
|
1410
|
-
<ui-nav-icon name="expand_more" [size]="18" />
|
|
1411
|
-
</button>
|
|
1412
|
-
}
|
|
1413
1460
|
@default {
|
|
1414
1461
|
<span class="ui-nav-heading px-3 py-2 text-muted-foreground">
|
|
1415
1462
|
{{ item.title }}
|
|
@@ -1421,48 +1468,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1421
1468
|
</ul>
|
|
1422
1469
|
</div>
|
|
1423
1470
|
|
|
1424
|
-
<div data-
|
|
1425
|
-
<ng-content select="[
|
|
1471
|
+
<div data-topbar-slot="end" [class]="endSlotClasses()">
|
|
1472
|
+
<ng-content select="[topbar-end]" />
|
|
1426
1473
|
</div>
|
|
1427
1474
|
</div>
|
|
1428
1475
|
|
|
1429
1476
|
<!-- Dropdown template -->
|
|
1430
1477
|
<ng-template #dropdownTpl let-item>
|
|
1431
|
-
<div
|
|
1432
|
-
role="menu"
|
|
1433
|
-
class="min-w-56 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md"
|
|
1434
|
-
(keydown)="onPanelKeydown($event)">
|
|
1478
|
+
<div role="menu" class="min-w-56 border border-brand bg-background/95 p-1" (keydown)="onPanelKeydown($event)">
|
|
1435
1479
|
@for (child of item.children; track child.id) {
|
|
1436
1480
|
<ui-nav-item [item]="child" />
|
|
1437
1481
|
}
|
|
1438
1482
|
</div>
|
|
1439
1483
|
</ng-template>
|
|
1440
|
-
|
|
1441
|
-
<!-- Mega panel template -->
|
|
1442
|
-
<ng-template #megaTpl let-item>
|
|
1443
|
-
<div
|
|
1444
|
-
role="menu"
|
|
1445
|
-
class="w-screen max-w-[min(90vw,72rem)] rounded-md border border-border bg-popover p-6 text-popover-foreground shadow-lg"
|
|
1446
|
-
(keydown)="onPanelKeydown($event)">
|
|
1447
|
-
<div [class]="megaGridClasses(item.columns)">
|
|
1448
|
-
@for (col of item.children; track col.id) {
|
|
1449
|
-
<div>
|
|
1450
|
-
<div class="ui-nav-heading mb-2 text-muted-foreground">
|
|
1451
|
-
{{ col.title }}
|
|
1452
|
-
</div>
|
|
1453
|
-
<div class="flex flex-col gap-0.5">
|
|
1454
|
-
@for (leaf of col.children ?? []; track leaf.id) {
|
|
1455
|
-
<ui-nav-item [item]="leaf" />
|
|
1456
|
-
}
|
|
1457
|
-
</div>
|
|
1458
|
-
</div>
|
|
1459
|
-
}
|
|
1460
|
-
</div>
|
|
1461
|
-
</div>
|
|
1462
|
-
</ng-template>
|
|
1463
1484
|
`,
|
|
1464
1485
|
}]
|
|
1465
|
-
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], navigationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationId", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], autoRegister: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoRegister", required: false }] }], showHamburger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHamburger", required: false }] }], hamburgerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hamburgerLabel", required: false }] }], dropdownTpl: [{ type: i0.ViewChild, args: ['dropdownTpl', { isSignal: true }] }]
|
|
1486
|
+
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], navigationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "navigationId", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], autoRegister: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoRegister", required: false }] }], showHamburger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHamburger", required: false }] }], hamburgerLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hamburgerLabel", required: false }] }], dropdownTpl: [{ type: i0.ViewChild, args: ['dropdownTpl', { isSignal: true }] }] } });
|
|
1466
1487
|
|
|
1467
1488
|
const DemoNavigationData = [
|
|
1468
1489
|
{
|