@ojiepermana/angular-navigation 22.0.29 → 22.0.33
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 +7 -9
- package/fesm2022/ojiepermana-angular-navigation-service.mjs +0 -86
- package/fesm2022/ojiepermana-angular-navigation.mjs +704 -257
- package/package.json +2 -2
- package/types/ojiepermana-angular-navigation-service.d.ts +0 -4
- package/types/ojiepermana-angular-navigation.d.ts +148 -16
|
@@ -43,7 +43,8 @@ function toKeyPart(value) {
|
|
|
43
43
|
.replace(/^-+|-+$/g, '');
|
|
44
44
|
}
|
|
45
45
|
function itemFallbackKey(item, index) {
|
|
46
|
-
return toKeyPart(item.title ?? item.link?.toString() ?? item.href ?? `item-${index}`) ||
|
|
46
|
+
return (toKeyPart(item.title ?? item.link?.toString() ?? item.href ?? `item-${index}`) ||
|
|
47
|
+
`item-${index}`);
|
|
47
48
|
}
|
|
48
49
|
function normalizeItem(item, index, path) {
|
|
49
50
|
if (item.isHidden?.(item)) {
|
|
@@ -82,10 +83,7 @@ function injectNavigationController(inputs) {
|
|
|
82
83
|
...(ngDevMode ? [{ debugName: "normalizedNavId" }] : /* istanbul ignore next */ []));
|
|
83
84
|
const collapsedPreference = computed(() => inputs.collapsed() ?? (inputs.compact() ? true : null), /* @ts-ignore */
|
|
84
85
|
...(ngDevMode ? [{ debugName: "collapsedPreference" }] : /* istanbul ignore next */ []));
|
|
85
|
-
const normalizedItems = computed(() =>
|
|
86
|
-
const data = inputs.data();
|
|
87
|
-
return normalizeUiNavItems(data.length > 0 ? data : inputs.items());
|
|
88
|
-
}, /* @ts-ignore */
|
|
86
|
+
const normalizedItems = computed(() => normalizeUiNavItems(inputs.data()), /* @ts-ignore */
|
|
89
87
|
...(ngDevMode ? [{ debugName: "normalizedItems" }] : /* istanbul ignore next */ []));
|
|
90
88
|
const fallbackState = computed(() => ({
|
|
91
89
|
id: normalizedNavId(),
|
|
@@ -172,8 +170,6 @@ class NavigationContainerComponent {
|
|
|
172
170
|
navId = input('default', { ...(ngDevMode ? { debugName: "navId" } : /* istanbul ignore next */ {}), alias: 'id' });
|
|
173
171
|
data = input([], /* @ts-ignore */
|
|
174
172
|
...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
175
|
-
items = input([], /* @ts-ignore */
|
|
176
|
-
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
177
173
|
ariaLabel = input('Primary navigation', /* @ts-ignore */
|
|
178
174
|
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
179
175
|
compact = input(false, /* @ts-ignore */
|
|
@@ -212,7 +208,7 @@ class NavigationContainerComponent {
|
|
|
212
208
|
...(ngDevMode ? [{ debugName: "sidebarCollapse" }] : /* istanbul ignore next */ []));
|
|
213
209
|
previewExpanded = computed(() => this.typeConfig()?.previewExpanded?.() ?? false, /* @ts-ignore */
|
|
214
210
|
...(ngDevMode ? [{ debugName: "previewExpanded" }] : /* istanbul ignore next */ []));
|
|
215
|
-
typeStyle = computed(() => this.typeConfig()?.typeStyle?.() ?? '
|
|
211
|
+
typeStyle = computed(() => this.typeConfig()?.typeStyle?.() ?? 'flat', /* @ts-ignore */
|
|
216
212
|
...(ngDevMode ? [{ debugName: "typeStyle" }] : /* istanbul ignore next */ []));
|
|
217
213
|
flyoutLabel = computed(() => this.typeConfig()?.flyoutLabel?.() ?? 'Menu', /* @ts-ignore */
|
|
218
214
|
...(ngDevMode ? [{ debugName: "flyoutLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -222,10 +218,15 @@ class NavigationContainerComponent {
|
|
|
222
218
|
...(ngDevMode ? [{ debugName: "flyoutIconOnly" }] : /* istanbul ignore next */ []));
|
|
223
219
|
flyoutIconPosition = computed(() => this.typeConfig()?.flyoutIconPosition?.() ?? 'start', /* @ts-ignore */
|
|
224
220
|
...(ngDevMode ? [{ debugName: "flyoutIconPosition" }] : /* istanbul ignore next */ []));
|
|
221
|
+
flyoutTriggerVariant = computed(() => this.typeConfig()?.flyoutTriggerVariant?.() ?? 'button', /* @ts-ignore */
|
|
222
|
+
...(ngDevMode ? [{ debugName: "flyoutTriggerVariant" }] : /* istanbul ignore next */ []));
|
|
223
|
+
flyoutTriggerFloating = computed(() => this.typeConfig()?.flyoutTriggerFloating?.() ?? false, /* @ts-ignore */
|
|
224
|
+
...(ngDevMode ? [{ debugName: "flyoutTriggerFloating" }] : /* istanbul ignore next */ []));
|
|
225
|
+
flyoutTriggerClass = computed(() => this.typeConfig()?.flyoutTriggerClass?.() ?? '', /* @ts-ignore */
|
|
226
|
+
...(ngDevMode ? [{ debugName: "flyoutTriggerClass" }] : /* istanbul ignore next */ []));
|
|
225
227
|
controller = injectNavigationController({
|
|
226
228
|
navId: this.navId,
|
|
227
229
|
data: this.data,
|
|
228
|
-
items: this.items,
|
|
229
230
|
orientation: this.orientationPreference,
|
|
230
231
|
type: this.typePreference,
|
|
231
232
|
position: this.positionPreference,
|
|
@@ -288,7 +289,7 @@ class NavigationContainerComponent {
|
|
|
288
289
|
...(ngDevMode ? [{ debugName: "shellClasses" }] : /* istanbul ignore next */ []));
|
|
289
290
|
state = this.resolvedState;
|
|
290
291
|
hostClasses = computed(() => cn('relative block min-h-0 text-foreground transition-[width] duration-300 ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:transition-none', this.resolvedState().orientation === 'horizontal'
|
|
291
|
-
? 'w-full'
|
|
292
|
+
? 'h-full w-full'
|
|
292
293
|
: this.resolvedState().type === 'dockbar'
|
|
293
294
|
? this.dockbarAsideOpen()
|
|
294
295
|
? 'w-76'
|
|
@@ -323,14 +324,18 @@ class NavigationContainerComponent {
|
|
|
323
324
|
this.hoverPreviewExpanded.set(this.sidebarCollapse() ? value : false);
|
|
324
325
|
}
|
|
325
326
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
326
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.2", type: NavigationContainerComponent, isStandalone: true, selector: "Navigation", inputs: { navId: { classPropertyName: "navId", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null },
|
|
327
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.2", type: NavigationContainerComponent, isStandalone: true, selector: "Navigation", inputs: { navId: { classPropertyName: "navId", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, collapseTree: { classPropertyName: "collapseTree", publicName: "collapse-tree", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null }, groupClass: { classPropertyName: "groupClass", publicName: "nav-group-class", 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 }, openedIds: { classPropertyName: "openedIds", publicName: "openedIds", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openedIds: "openedIdsChange", itemSelected: "itemSelected" }, host: { attributes: { "role": "navigation" }, listeners: { "mouseenter": "setHoverPreview(true)", "mouseleave": "setHoverPreview(false)" }, properties: { "class": "hostClasses()", "attr.aria-label": "ariaLabel() || null", "attr.data-navigation-id": "resolvedState().id", "attr.data-orientation": "resolvedState().orientation", "attr.data-type": "resolvedState().type", "attr.data-type-style": "typeStyle()", "attr.data-position": "resolvedState().position", "attr.data-collapse-tree": "collapseTree()", "attr.data-preview-expanded": "previewRailExpanded() ? \"true\" : null" } }, providers: [
|
|
328
|
+
{ provide: NAVIGATION_SHELL, useExisting: forwardRef(() => NavigationContainerComponent) },
|
|
329
|
+
], queries: [{ propertyName: "iconTemplate", first: true, predicate: NavigationIconDirective, descendants: true, isSignal: true }], ngImport: i0, template: ` <ng-content /> `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
327
330
|
}
|
|
328
331
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationContainerComponent, decorators: [{
|
|
329
332
|
type: Component,
|
|
330
333
|
args: [{
|
|
331
334
|
selector: 'Navigation',
|
|
332
335
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
333
|
-
providers: [
|
|
336
|
+
providers: [
|
|
337
|
+
{ provide: NAVIGATION_SHELL, useExisting: forwardRef(() => NavigationContainerComponent) },
|
|
338
|
+
],
|
|
334
339
|
host: {
|
|
335
340
|
'[class]': 'hostClasses()',
|
|
336
341
|
role: 'navigation',
|
|
@@ -347,7 +352,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
347
352
|
},
|
|
348
353
|
template: ` <ng-content /> `,
|
|
349
354
|
}]
|
|
350
|
-
}], propDecorators: { navId: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }],
|
|
355
|
+
}], propDecorators: { navId: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], collapseTree: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapse-tree", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], itemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClass", required: false }] }], groupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav-group-class", required: false }] }], activeIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIds", required: false }] }], activeUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeUrl", required: false }] }], openedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "openedIds", required: false }] }, { type: i0.Output, args: ["openedIdsChange"] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }], iconTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NavigationIconDirective), { isSignal: true }] }] } });
|
|
351
356
|
|
|
352
357
|
class NavigationItemContentComponent {
|
|
353
358
|
nav = inject(NavigationService);
|
|
@@ -1531,7 +1536,7 @@ class NavigationEntryGridComponent {
|
|
|
1531
1536
|
...(ngDevMode ? [{ debugName: "navId" }] : /* istanbul ignore next */ []));
|
|
1532
1537
|
branch = input.required(/* @ts-ignore */
|
|
1533
1538
|
...(ngDevMode ? [{ debugName: "branch" }] : /* istanbul ignore next */ []));
|
|
1534
|
-
typeStyle = input('
|
|
1539
|
+
typeStyle = input('flat', /* @ts-ignore */
|
|
1535
1540
|
...(ngDevMode ? [{ debugName: "typeStyle" }] : /* istanbul ignore next */ []));
|
|
1536
1541
|
itemClass = input('', /* @ts-ignore */
|
|
1537
1542
|
...(ngDevMode ? [{ debugName: "itemClass" }] : /* istanbul ignore next */ []));
|
|
@@ -2042,10 +2047,19 @@ class NavigationFlyoutMenuComponent {
|
|
|
2042
2047
|
/** Penempatan ikon relatif label: `start` (default) atau `end`. */
|
|
2043
2048
|
iconPosition = input('start', /* @ts-ignore */
|
|
2044
2049
|
...(ngDevMode ? [{ debugName: "iconPosition" }] : /* istanbul ignore next */ []));
|
|
2050
|
+
/** Bentuk visual tombol trigger: `button` (pil) | `link` | `plain` (ghost). */
|
|
2051
|
+
variant = input('button', /* @ts-ignore */
|
|
2052
|
+
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
2053
|
+
/** Trigger mengambang (`fixed`) — host menjadi popover lepas, panel menempel ke trigger. */
|
|
2054
|
+
floating = input(false, /* @ts-ignore */
|
|
2055
|
+
...(ngDevMode ? [{ debugName: "floating" }] : /* istanbul ignore next */ []));
|
|
2056
|
+
/** Kelas Tailwind untuk host trigger (posisi pojok floating / styling wrapper in-flow). */
|
|
2057
|
+
triggerClass = input('', /* @ts-ignore */
|
|
2058
|
+
...(ngDevMode ? [{ debugName: "triggerClass" }] : /* istanbul ignore next */ []));
|
|
2045
2059
|
/** `bottom` = bar berada di bawah konten; panel menempel sisi bawah container dan tumbuh ke atas. */
|
|
2046
2060
|
position = input('top', /* @ts-ignore */
|
|
2047
2061
|
...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
2048
|
-
typeStyle = input('
|
|
2062
|
+
typeStyle = input('flat', /* @ts-ignore */
|
|
2049
2063
|
...(ngDevMode ? [{ debugName: "typeStyle" }] : /* istanbul ignore next */ []));
|
|
2050
2064
|
compact = input(false, /* @ts-ignore */
|
|
2051
2065
|
...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
|
|
@@ -2090,6 +2104,12 @@ class NavigationFlyoutMenuComponent {
|
|
|
2090
2104
|
return this.branches().find((branch) => branch.key === key) ?? null;
|
|
2091
2105
|
}, /* @ts-ignore */
|
|
2092
2106
|
...(ngDevMode ? [{ debugName: "activeBranch" }] : /* istanbul ignore next */ []));
|
|
2107
|
+
/**
|
|
2108
|
+
* Floating: sisi popover relatif trigger — `true` = rata kanan (buka ke kiri, untuk trigger di
|
|
2109
|
+
* pojok kanan), `false` = rata kiri (buka ke kanan). Diukur dari posisi trigger saat dibuka.
|
|
2110
|
+
*/
|
|
2111
|
+
floatingAlignEnd = signal(true, /* @ts-ignore */
|
|
2112
|
+
...(ngDevMode ? [{ debugName: "floatingAlignEnd" }] : /* istanbul ignore next */ []));
|
|
2093
2113
|
/**
|
|
2094
2114
|
* Offset panel terhadap host agar panel menimpa penuh container parent dari
|
|
2095
2115
|
* `Navigation` (lebar sama persis; posisi atas di mode top, posisi bawah di
|
|
@@ -2098,14 +2118,40 @@ class NavigationFlyoutMenuComponent {
|
|
|
2098
2118
|
*/
|
|
2099
2119
|
panelPlacement = signal(null, /* @ts-ignore */
|
|
2100
2120
|
...(ngDevMode ? [{ debugName: "panelPlacement" }] : /* istanbul ignore next */ []));
|
|
2101
|
-
panelWrapperClasses = computed(() =>
|
|
2121
|
+
panelWrapperClasses = computed(() => {
|
|
2122
|
+
if (this.floating()) {
|
|
2123
|
+
// Floating: popover menempel ke trigger — atas/bawah ikut nav-position; sisi kiri/kanan
|
|
2124
|
+
// ikut posisi trigger (floatingAlignEnd) agar tidak keluar layar saat trigger di pojok kiri.
|
|
2125
|
+
return cn('absolute z-50 w-[min(22rem,85vw)] max-w-[85vw]', this.floatingAlignEnd() ? 'right-0' : 'left-0', this.isBottom() ? 'bottom-full mb-2' : 'top-full mt-2');
|
|
2126
|
+
}
|
|
2127
|
+
// Default: panel menutupi (overlay) container bar persis — posisi & lebar ikut container.
|
|
2128
|
+
return cn('absolute z-50', !this.panelPlacement() && cn('inset-x-0', this.isBottom() ? 'bottom-0' : 'top-0'));
|
|
2129
|
+
}, /* @ts-ignore */
|
|
2102
2130
|
...(ngDevMode ? [{ debugName: "panelWrapperClasses" }] : /* istanbul ignore next */ []));
|
|
2103
|
-
/**
|
|
2104
|
-
|
|
2131
|
+
/**
|
|
2132
|
+
* Mode bottom membalik urutan visual: grid entri di atas, bar di bawah (dekat bar trigger).
|
|
2133
|
+
* `min-h-0 flex-1` membuat menu mengisi penuh panel card (yang di-clip) sehingga ROW 2
|
|
2134
|
+
* bisa jadi satu-satunya area scroll.
|
|
2135
|
+
*/
|
|
2136
|
+
menuClasses = computed(() => cn('flex min-h-0 flex-1', this.isBottom() ? 'flex-col-reverse' : 'flex-col'), /* @ts-ignore */
|
|
2105
2137
|
...(ngDevMode ? [{ debugName: "menuClasses" }] : /* istanbul ignore next */ []));
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2138
|
+
/**
|
|
2139
|
+
* ROW 1 = bar flyout: satu baris horizontal seperti bar navbar —
|
|
2140
|
+
* Header (kiri) · menu item (tengah, flex-1) · Footer (kanan). `shrink-0` membuatnya DIAM
|
|
2141
|
+
* (tidak ikut scroll) — hanya ROW 2 (grid child) yang punya area scroll sendiri.
|
|
2142
|
+
* Border memisahkan bar dari ROW 2 di sisi yang menjauh dari bar (bawah di mode top).
|
|
2143
|
+
*/
|
|
2144
|
+
barRowClasses = computed(() => cn('flex shrink-0 items-center gap-2 bg-popover px-2 md:px-3', this.isBorderRail()
|
|
2145
|
+
? cn('min-h-12 border-border', this.isBottom() ? 'border-t-[1.5px]' : 'border-b-[1.5px]')
|
|
2146
|
+
: cn('min-h-[3.25rem] border-[hsl(var(--border)/var(--opacity-60))]', this.isBottom() ? 'border-t' : 'border-b')), /* @ts-ignore */
|
|
2147
|
+
...(ngDevMode ? [{ debugName: "barRowClasses" }] : /* istanbul ignore next */ []));
|
|
2148
|
+
/**
|
|
2149
|
+
* ROW 2 = HANYA area ini yang scroll: children dari nav item aktif. `min-h-0 flex-1`
|
|
2150
|
+
* membatasi tingginya ke sisa ruang panel lalu `overflow-y-auto` men-scroll isinya —
|
|
2151
|
+
* bar ROW 1 & kontainer panel sendiri tetap diam.
|
|
2152
|
+
*/
|
|
2153
|
+
scrollRegionClasses = computed(() => cn('min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain'), /* @ts-ignore */
|
|
2154
|
+
...(ngDevMode ? [{ debugName: "scrollRegionClasses" }] : /* istanbul ignore next */ []));
|
|
2109
2155
|
isOpen() {
|
|
2110
2156
|
return this.nav.isDrawerOpen(this.navId());
|
|
2111
2157
|
}
|
|
@@ -2115,6 +2161,17 @@ class NavigationFlyoutMenuComponent {
|
|
|
2115
2161
|
}
|
|
2116
2162
|
}
|
|
2117
2163
|
measurePanelPlacement() {
|
|
2164
|
+
// Floating: panel anchored ke trigger via CSS, bukan overlay container. Pilih sisi popover
|
|
2165
|
+
// (kanan→buka kiri / kiri→buka kanan) dari posisi trigger agar tidak keluar layar.
|
|
2166
|
+
if (this.floating()) {
|
|
2167
|
+
const triggerEl = this.host.nativeElement.querySelector('[data-navigation-flyout-trigger="true"]');
|
|
2168
|
+
const rect = triggerEl?.getBoundingClientRect();
|
|
2169
|
+
if (rect && typeof window !== 'undefined' && window.innerWidth > 0) {
|
|
2170
|
+
this.floatingAlignEnd.set(rect.left + rect.width / 2 > window.innerWidth / 2);
|
|
2171
|
+
}
|
|
2172
|
+
this.panelPlacement.set(null);
|
|
2173
|
+
return;
|
|
2174
|
+
}
|
|
2118
2175
|
const hostEl = this.host.nativeElement;
|
|
2119
2176
|
const navEl = hostEl.closest('[data-navigation-id]');
|
|
2120
2177
|
let container = navEl?.parentElement ?? hostEl.parentElement;
|
|
@@ -2183,8 +2240,30 @@ class NavigationFlyoutMenuComponent {
|
|
|
2183
2240
|
openBranch(item) {
|
|
2184
2241
|
this.nav.openPanel(this.navId(), item);
|
|
2185
2242
|
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Host trigger+panel. Default `relative block w-full` (mengalir di dalam bar/div). Saat
|
|
2245
|
+
* `floating`, jadi `fixed` (mengambang) — default pojok kanan-atas, override via `triggerClass`.
|
|
2246
|
+
*/
|
|
2247
|
+
hostClasses = computed(() => this.floating()
|
|
2248
|
+
? cn('fixed z-50 block w-max', this.triggerClass() || 'right-6 top-6')
|
|
2249
|
+
: cn('relative block w-full', this.triggerClass()), /* @ts-ignore */
|
|
2250
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2251
|
+
/** Bentuk visual trigger: `button` (pil), `link` (tautan), atau `plain` (ghost); + ikon/teks. */
|
|
2186
2252
|
triggerClasses() {
|
|
2187
|
-
|
|
2253
|
+
const iconOnly = this.showIconOnly();
|
|
2254
|
+
const base = 'nav-trigger group/nav inline-flex min-w-0 items-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring';
|
|
2255
|
+
if (this.variant() === 'link') {
|
|
2256
|
+
return cn(base, 'text-sm underline-offset-4 hover:underline',
|
|
2257
|
+
// Icon-only tetap punya target ≥ 36px (WCAG 2.5.8) walau tanpa chrome tautan.
|
|
2258
|
+
iconOnly ? 'h-9 w-9 justify-center gap-0' : 'gap-1.5', this.isOpen() ? 'text-primary underline' : 'text-primary/90 hover:text-primary', this.itemClass());
|
|
2259
|
+
}
|
|
2260
|
+
if (this.variant() === 'plain') {
|
|
2261
|
+
return cn(base, 'gap-2 rounded-md text-sm', iconOnly ? 'h-9 w-9 justify-center' : 'h-9 px-3 py-2', this.isOpen()
|
|
2262
|
+
? 'bg-accent text-accent-foreground'
|
|
2263
|
+
: 'text-foreground/80 hover:bg-accent hover:text-accent-foreground', this.itemClass());
|
|
2264
|
+
}
|
|
2265
|
+
// button (pil, default)
|
|
2266
|
+
return cn(base, 'h-10 gap-2 rounded-full border border-[hsl(var(--border)/var(--opacity-60))] bg-background px-4 py-2 text-sm shadow-sm', iconOnly && 'w-10 justify-center gap-0 px-0', this.isBorderRail()
|
|
2188
2267
|
? this.isOpen()
|
|
2189
2268
|
? 'text-primary'
|
|
2190
2269
|
: 'text-foreground/80 hover:text-primary'
|
|
@@ -2193,23 +2272,28 @@ class NavigationFlyoutMenuComponent {
|
|
|
2193
2272
|
: 'text-foreground/80 hover:bg-accent hover:text-accent-foreground', this.itemClass());
|
|
2194
2273
|
}
|
|
2195
2274
|
panelCardClasses() {
|
|
2275
|
+
if (this.floating()) {
|
|
2276
|
+
// Floating: kartu popover mandiri (rounded penuh + border + shadow), tinggi dibatasi & di-clip;
|
|
2277
|
+
// hanya ROW 2 (children) yang scroll.
|
|
2278
|
+
return cn('relative flex flex-col rounded-xl border border-[hsl(var(--border)/var(--opacity-70))] bg-popover text-popover-foreground shadow-2xl', 'max-h-[min(28rem,70vh)] overflow-hidden');
|
|
2279
|
+
}
|
|
2196
2280
|
// Border-rail: panel menutup tepat content-box frame layout, jadi garis
|
|
2197
2281
|
// sisi bar memakai border frame (rail) itu sendiri — panel cukup menggambar
|
|
2198
2282
|
// border 1.5px senada rail pada sisi yang menjauh dari bar agar sambungan
|
|
2199
2283
|
// tetap lurus (bawah di mode top, atas di mode bottom).
|
|
2200
|
-
return cn('relative
|
|
2284
|
+
return cn('relative flex flex-col bg-popover text-popover-foreground shadow-2xl',
|
|
2285
|
+
// Batasi tinggi panel ke viewport lalu CLIP — bukan scroll. Hanya ROW 2 (children, lihat
|
|
2286
|
+
// scrollRegionClasses) yang scroll; bar ROW 1 & kontainer panel sendiri tetap diam.
|
|
2287
|
+
'max-h-[calc(100dvh-5rem)] overflow-hidden', this.isBorderRail()
|
|
2201
2288
|
? cn('rounded-none border-border', this.isBottom() ? 'border-t-[1.5px]' : 'border-b-[1.5px]')
|
|
2202
2289
|
: 'rounded-xl border border-[hsl(var(--border)/var(--opacity-70))]');
|
|
2203
2290
|
}
|
|
2204
2291
|
rowClasses() {
|
|
2205
|
-
//
|
|
2206
|
-
//
|
|
2207
|
-
//
|
|
2208
|
-
//
|
|
2209
|
-
|
|
2210
|
-
return cn('m-0 flex min-w-0 list-none flex-wrap items-center gap-1 px-2 py-2 pr-12 md:px-3 md:pr-14', this.isBorderRail()
|
|
2211
|
-
? cn('min-h-12 border-border', this.isBottom() ? 'border-t-[1.5px]' : 'border-b-[1.5px]')
|
|
2212
|
-
: cn('min-h-[3.25rem] border-[hsl(var(--border)/var(--opacity-60))]', this.isBottom() ? 'border-t' : 'border-b'));
|
|
2292
|
+
// Menu item = bagian tengah ROW 1: isi ruang antara Footer & Header (flex-1) lalu
|
|
2293
|
+
// di-center seperti menubar navbar. Saat jumlah/lebar item melebihi band, band ini
|
|
2294
|
+
// scroll horizontal (overflow-x-auto) agar tidak ada item ter-clip & takterjangkau
|
|
2295
|
+
// (panel card meng-clip overflow-x). Tinggi & border bar ditangani barRowClasses().
|
|
2296
|
+
return cn('m-0 flex min-w-0 flex-1 list-none items-center justify-center gap-1 overflow-x-auto overscroll-x-contain py-2');
|
|
2213
2297
|
}
|
|
2214
2298
|
/**
|
|
2215
2299
|
* Container `<li>` tab group. Basis `flex -my-2 self-stretch` membuat tab setinggi
|
|
@@ -2258,14 +2342,22 @@ class NavigationFlyoutMenuComponent {
|
|
|
2258
2342
|
}
|
|
2259
2343
|
focusFirstPanelItem() {
|
|
2260
2344
|
const panel = this.host.nativeElement.querySelector('[data-navigation-flyout-panel="true"]');
|
|
2261
|
-
|
|
2345
|
+
if (!panel) {
|
|
2346
|
+
return;
|
|
2347
|
+
}
|
|
2348
|
+
// Fokus awal ke menu item ROW 1 (lalu grid ROW 2) — BUKAN kontrol Header/Footer yang
|
|
2349
|
+
// juga ada di bar (mis. tombol logout). querySelector mengembalikan match pertama dalam
|
|
2350
|
+
// urutan DOM, dan Header/Footer bisa mendahului menu, jadi lingkup ke baris menu dulu.
|
|
2351
|
+
const target = panel.querySelector('[data-navigation-flyout-row="true"] [role="menuitem"], [data-navigation-flyout-row="true"] a[href]') ?? panel.querySelector('[role="menuitem"], a[href]');
|
|
2262
2352
|
target?.focus();
|
|
2263
2353
|
}
|
|
2264
2354
|
focusTrigger() {
|
|
2265
|
-
this.host.nativeElement
|
|
2355
|
+
this.host.nativeElement
|
|
2356
|
+
.querySelector('[data-navigation-flyout-trigger="true"]')
|
|
2357
|
+
?.focus();
|
|
2266
2358
|
}
|
|
2267
2359
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFlyoutMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2268
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationFlyoutMenuComponent, isStandalone: true, selector: "NavigationFlyoutMenu", inputs: { navId: { classPropertyName: "navId", publicName: "navId", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "typeStyle", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null }, groupClass: { classPropertyName: "groupClass", publicName: "groupClass", 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: { listeners: { "keydown.escape": "onEscape($event)", "document:click": "onDocumentClick($event)", "window:resize": "onWindowResize()" },
|
|
2360
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationFlyoutMenuComponent, isStandalone: true, selector: "NavigationFlyoutMenu", inputs: { navId: { classPropertyName: "navId", publicName: "navId", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, floating: { classPropertyName: "floating", publicName: "floating", isSignal: true, isRequired: false, transformFunction: null }, triggerClass: { classPropertyName: "triggerClass", publicName: "triggerClass", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "typeStyle", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null }, groupClass: { classPropertyName: "groupClass", publicName: "groupClass", 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: { listeners: { "keydown.escape": "onEscape($event)", "document:click": "onDocumentClick($event)", "window:resize": "onWindowResize()" }, properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
2269
2361
|
<button
|
|
2270
2362
|
type="button"
|
|
2271
2363
|
data-navigation-flyout-trigger="true"
|
|
@@ -2275,7 +2367,8 @@ class NavigationFlyoutMenuComponent {
|
|
|
2275
2367
|
[attr.aria-controls]="isOpen() ? panelId() : null"
|
|
2276
2368
|
[attr.aria-label]="showIconOnly() ? label() : null"
|
|
2277
2369
|
[attr.title]="showIconOnly() ? label() : null"
|
|
2278
|
-
(click)="toggleFlyout()"
|
|
2370
|
+
(click)="toggleFlyout()"
|
|
2371
|
+
>
|
|
2279
2372
|
@if (showIconOnly()) {
|
|
2280
2373
|
<Icon [name]="triggerIcon() ?? 'menu'" [size]="18" class="text-current" />
|
|
2281
2374
|
} @else {
|
|
@@ -2296,88 +2389,109 @@ class NavigationFlyoutMenuComponent {
|
|
|
2296
2389
|
[id]="panelId()"
|
|
2297
2390
|
data-navigation-flyout-panel="true"
|
|
2298
2391
|
[class]="panelWrapperClasses()"
|
|
2299
|
-
[style.left.px]="panelPlacement()?.left"
|
|
2300
|
-
[style.top.px]="isBottom() ? null : panelPlacement()?.top"
|
|
2301
|
-
[style.bottom.px]="isBottom() ? panelPlacement()?.bottom : null"
|
|
2302
|
-
[style.width.px]="panelPlacement()?.width"
|
|
2392
|
+
[style.left.px]="floating() ? null : panelPlacement()?.left"
|
|
2393
|
+
[style.top.px]="floating() || isBottom() ? null : panelPlacement()?.top"
|
|
2394
|
+
[style.bottom.px]="!floating() && isBottom() ? panelPlacement()?.bottom : null"
|
|
2395
|
+
[style.width.px]="floating() ? null : panelPlacement()?.width"
|
|
2396
|
+
>
|
|
2303
2397
|
<div [class]="panelCardClasses()">
|
|
2304
|
-
<button
|
|
2305
|
-
type="button"
|
|
2306
|
-
data-navigation-flyout-close="true"
|
|
2307
|
-
[class]="closeButtonClasses()"
|
|
2308
|
-
aria-label="Close menu"
|
|
2309
|
-
(click)="closeFlyout(true)">
|
|
2310
|
-
<span aria-hidden="true" class="text-base leading-none">✕</span>
|
|
2311
|
-
</button>
|
|
2312
|
-
|
|
2313
2398
|
<div role="menu" [class]="menuClasses()" [attr.aria-label]="label()">
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2399
|
+
<!-- ROW 1 = bar (sticky, menutup bar trigger), struktur seperti bar navbar:
|
|
2400
|
+
Header (kiri) | menu item (tengah) | Footer (kanan). Hanya ROW 2 (grid child)
|
|
2401
|
+
di bawah bar yang ikut scroll. -->
|
|
2402
|
+
<div data-navigation-flyout-bar="true" [class]="barRowClasses()">
|
|
2403
|
+
<ng-content select="NavigationHeader" />
|
|
2404
|
+
|
|
2405
|
+
<ul
|
|
2406
|
+
role="none"
|
|
2407
|
+
data-navigation-flyout-row="true"
|
|
2408
|
+
[class]="rowClasses()"
|
|
2409
|
+
(keydown)="onRowKeydown($event)"
|
|
2410
|
+
>
|
|
2411
|
+
@for (item of items(); track item.key) {
|
|
2412
|
+
@switch (item.type) {
|
|
2413
|
+
@case ('divider') {
|
|
2414
|
+
<li role="separator" class="mx-1 h-5 w-px bg-border"></li>
|
|
2415
|
+
}
|
|
2416
|
+
@case ('spacer') {
|
|
2417
|
+
<li role="none" aria-hidden="true" class="flex-1"></li>
|
|
2418
|
+
}
|
|
2419
|
+
@default {
|
|
2420
|
+
@if (item.children.length > 0) {
|
|
2421
|
+
<li
|
|
2422
|
+
role="none"
|
|
2423
|
+
[class]="groupContainerClasses(item)"
|
|
2424
|
+
[attr.data-navigation-item-key]="item.key"
|
|
2425
|
+
>
|
|
2426
|
+
<button
|
|
2427
|
+
type="button"
|
|
2428
|
+
role="menuitem"
|
|
2429
|
+
data-navigation-flyout-tab="true"
|
|
2430
|
+
[class]="tabClasses(item)"
|
|
2431
|
+
[attr.aria-expanded]="isBranchOpen(item)"
|
|
2432
|
+
[attr.aria-controls]="item.panelId"
|
|
2433
|
+
[disabled]="item.disabled || null"
|
|
2434
|
+
(click)="openBranch(item)"
|
|
2435
|
+
>
|
|
2436
|
+
<NavigationItemContent
|
|
2437
|
+
[item]="item"
|
|
2438
|
+
[active]="isItemActive(item)"
|
|
2439
|
+
[compact]="false"
|
|
2440
|
+
[orientation]="'horizontal'"
|
|
2441
|
+
[level]="0"
|
|
2442
|
+
[iconTemplate]="iconTemplate()"
|
|
2443
|
+
/>
|
|
2444
|
+
<Icon
|
|
2445
|
+
name="chevron_right"
|
|
2446
|
+
[size]="16"
|
|
2447
|
+
[class]="tabChevronClasses(item)"
|
|
2448
|
+
/>
|
|
2449
|
+
</button>
|
|
2450
|
+
</li>
|
|
2451
|
+
} @else {
|
|
2452
|
+
<li
|
|
2453
|
+
NavigationItem
|
|
2454
|
+
[navId]="navId()"
|
|
2455
|
+
[item]="item"
|
|
2456
|
+
[level]="0"
|
|
2457
|
+
[orientation]="'horizontal'"
|
|
2458
|
+
[compact]="false"
|
|
2459
|
+
[itemClass]="navItemClass()"
|
|
2460
|
+
[activeIds]="activeIds()"
|
|
2461
|
+
[activeUrl]="activeUrl()"
|
|
2462
|
+
[iconTemplate]="iconTemplate()"
|
|
2463
|
+
[collapseTree]="collapseTree()"
|
|
2464
|
+
[openedIds]="openedIds()"
|
|
2465
|
+
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
2466
|
+
(itemSelected)="itemSelected.emit($event)"
|
|
2467
|
+
></li>
|
|
2468
|
+
}
|
|
2361
2469
|
}
|
|
2362
2470
|
}
|
|
2363
2471
|
}
|
|
2472
|
+
</ul>
|
|
2473
|
+
|
|
2474
|
+
<ng-content select="NavigationFooter" />
|
|
2475
|
+
</div>
|
|
2476
|
+
|
|
2477
|
+
<!-- ROW 2 = child dari menu item aktif; HANYA area ini yang men-scroll. -->
|
|
2478
|
+
<div data-navigation-flyout-scroll="true" [class]="scrollRegionClasses()">
|
|
2479
|
+
@if (activeBranch(); as branch) {
|
|
2480
|
+
<NavigationEntryGrid
|
|
2481
|
+
[navId]="navId()"
|
|
2482
|
+
[branch]="branch"
|
|
2483
|
+
[typeStyle]="typeStyle()"
|
|
2484
|
+
[itemClass]="itemClass()"
|
|
2485
|
+
[activeIds]="activeIds()"
|
|
2486
|
+
[activeUrl]="activeUrl()"
|
|
2487
|
+
[iconTemplate]="iconTemplate()"
|
|
2488
|
+
[collapseTree]="collapseTree()"
|
|
2489
|
+
[openedIds]="openedIds()"
|
|
2490
|
+
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
2491
|
+
(itemSelected)="itemSelected.emit($event)"
|
|
2492
|
+
/>
|
|
2364
2493
|
}
|
|
2365
|
-
</
|
|
2366
|
-
|
|
2367
|
-
@if (activeBranch(); as branch) {
|
|
2368
|
-
<NavigationEntryGrid
|
|
2369
|
-
[navId]="navId()"
|
|
2370
|
-
[branch]="branch"
|
|
2371
|
-
[typeStyle]="typeStyle()"
|
|
2372
|
-
[itemClass]="itemClass()"
|
|
2373
|
-
[activeIds]="activeIds()"
|
|
2374
|
-
[activeUrl]="activeUrl()"
|
|
2375
|
-
[iconTemplate]="iconTemplate()"
|
|
2376
|
-
[collapseTree]="collapseTree()"
|
|
2377
|
-
[openedIds]="openedIds()"
|
|
2378
|
-
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
2379
|
-
(itemSelected)="itemSelected.emit($event)" />
|
|
2380
|
-
}
|
|
2494
|
+
</div>
|
|
2381
2495
|
</div>
|
|
2382
2496
|
</div>
|
|
2383
2497
|
</div>
|
|
@@ -2389,9 +2503,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2389
2503
|
args: [{
|
|
2390
2504
|
selector: 'NavigationFlyoutMenu',
|
|
2391
2505
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2392
|
-
imports: [
|
|
2506
|
+
imports: [
|
|
2507
|
+
IconComponent,
|
|
2508
|
+
NavigationEntryGridComponent,
|
|
2509
|
+
NavigationItemComponent,
|
|
2510
|
+
NavigationItemContentComponent,
|
|
2511
|
+
],
|
|
2393
2512
|
host: {
|
|
2394
|
-
class: '
|
|
2513
|
+
'[class]': 'hostClasses()',
|
|
2395
2514
|
'(keydown.escape)': 'onEscape($event)',
|
|
2396
2515
|
'(document:click)': 'onDocumentClick($event)',
|
|
2397
2516
|
'(window:resize)': 'onWindowResize()',
|
|
@@ -2406,7 +2525,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2406
2525
|
[attr.aria-controls]="isOpen() ? panelId() : null"
|
|
2407
2526
|
[attr.aria-label]="showIconOnly() ? label() : null"
|
|
2408
2527
|
[attr.title]="showIconOnly() ? label() : null"
|
|
2409
|
-
(click)="toggleFlyout()"
|
|
2528
|
+
(click)="toggleFlyout()"
|
|
2529
|
+
>
|
|
2410
2530
|
@if (showIconOnly()) {
|
|
2411
2531
|
<Icon [name]="triggerIcon() ?? 'menu'" [size]="18" class="text-current" />
|
|
2412
2532
|
} @else {
|
|
@@ -2427,95 +2547,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2427
2547
|
[id]="panelId()"
|
|
2428
2548
|
data-navigation-flyout-panel="true"
|
|
2429
2549
|
[class]="panelWrapperClasses()"
|
|
2430
|
-
[style.left.px]="panelPlacement()?.left"
|
|
2431
|
-
[style.top.px]="isBottom() ? null : panelPlacement()?.top"
|
|
2432
|
-
[style.bottom.px]="isBottom() ? panelPlacement()?.bottom : null"
|
|
2433
|
-
[style.width.px]="panelPlacement()?.width"
|
|
2550
|
+
[style.left.px]="floating() ? null : panelPlacement()?.left"
|
|
2551
|
+
[style.top.px]="floating() || isBottom() ? null : panelPlacement()?.top"
|
|
2552
|
+
[style.bottom.px]="!floating() && isBottom() ? panelPlacement()?.bottom : null"
|
|
2553
|
+
[style.width.px]="floating() ? null : panelPlacement()?.width"
|
|
2554
|
+
>
|
|
2434
2555
|
<div [class]="panelCardClasses()">
|
|
2435
|
-
<button
|
|
2436
|
-
type="button"
|
|
2437
|
-
data-navigation-flyout-close="true"
|
|
2438
|
-
[class]="closeButtonClasses()"
|
|
2439
|
-
aria-label="Close menu"
|
|
2440
|
-
(click)="closeFlyout(true)">
|
|
2441
|
-
<span aria-hidden="true" class="text-base leading-none">✕</span>
|
|
2442
|
-
</button>
|
|
2443
|
-
|
|
2444
2556
|
<div role="menu" [class]="menuClasses()" [attr.aria-label]="label()">
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2557
|
+
<!-- ROW 1 = bar (sticky, menutup bar trigger), struktur seperti bar navbar:
|
|
2558
|
+
Header (kiri) | menu item (tengah) | Footer (kanan). Hanya ROW 2 (grid child)
|
|
2559
|
+
di bawah bar yang ikut scroll. -->
|
|
2560
|
+
<div data-navigation-flyout-bar="true" [class]="barRowClasses()">
|
|
2561
|
+
<ng-content select="NavigationHeader" />
|
|
2562
|
+
|
|
2563
|
+
<ul
|
|
2564
|
+
role="none"
|
|
2565
|
+
data-navigation-flyout-row="true"
|
|
2566
|
+
[class]="rowClasses()"
|
|
2567
|
+
(keydown)="onRowKeydown($event)"
|
|
2568
|
+
>
|
|
2569
|
+
@for (item of items(); track item.key) {
|
|
2570
|
+
@switch (item.type) {
|
|
2571
|
+
@case ('divider') {
|
|
2572
|
+
<li role="separator" class="mx-1 h-5 w-px bg-border"></li>
|
|
2573
|
+
}
|
|
2574
|
+
@case ('spacer') {
|
|
2575
|
+
<li role="none" aria-hidden="true" class="flex-1"></li>
|
|
2576
|
+
}
|
|
2577
|
+
@default {
|
|
2578
|
+
@if (item.children.length > 0) {
|
|
2579
|
+
<li
|
|
2580
|
+
role="none"
|
|
2581
|
+
[class]="groupContainerClasses(item)"
|
|
2582
|
+
[attr.data-navigation-item-key]="item.key"
|
|
2583
|
+
>
|
|
2584
|
+
<button
|
|
2585
|
+
type="button"
|
|
2586
|
+
role="menuitem"
|
|
2587
|
+
data-navigation-flyout-tab="true"
|
|
2588
|
+
[class]="tabClasses(item)"
|
|
2589
|
+
[attr.aria-expanded]="isBranchOpen(item)"
|
|
2590
|
+
[attr.aria-controls]="item.panelId"
|
|
2591
|
+
[disabled]="item.disabled || null"
|
|
2592
|
+
(click)="openBranch(item)"
|
|
2593
|
+
>
|
|
2594
|
+
<NavigationItemContent
|
|
2595
|
+
[item]="item"
|
|
2596
|
+
[active]="isItemActive(item)"
|
|
2597
|
+
[compact]="false"
|
|
2598
|
+
[orientation]="'horizontal'"
|
|
2599
|
+
[level]="0"
|
|
2600
|
+
[iconTemplate]="iconTemplate()"
|
|
2601
|
+
/>
|
|
2602
|
+
<Icon
|
|
2603
|
+
name="chevron_right"
|
|
2604
|
+
[size]="16"
|
|
2605
|
+
[class]="tabChevronClasses(item)"
|
|
2606
|
+
/>
|
|
2607
|
+
</button>
|
|
2608
|
+
</li>
|
|
2609
|
+
} @else {
|
|
2610
|
+
<li
|
|
2611
|
+
NavigationItem
|
|
2612
|
+
[navId]="navId()"
|
|
2613
|
+
[item]="item"
|
|
2614
|
+
[level]="0"
|
|
2615
|
+
[orientation]="'horizontal'"
|
|
2616
|
+
[compact]="false"
|
|
2617
|
+
[itemClass]="navItemClass()"
|
|
2618
|
+
[activeIds]="activeIds()"
|
|
2619
|
+
[activeUrl]="activeUrl()"
|
|
2620
|
+
[iconTemplate]="iconTemplate()"
|
|
2621
|
+
[collapseTree]="collapseTree()"
|
|
2622
|
+
[openedIds]="openedIds()"
|
|
2623
|
+
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
2624
|
+
(itemSelected)="itemSelected.emit($event)"
|
|
2625
|
+
></li>
|
|
2626
|
+
}
|
|
2492
2627
|
}
|
|
2493
2628
|
}
|
|
2494
2629
|
}
|
|
2630
|
+
</ul>
|
|
2631
|
+
|
|
2632
|
+
<ng-content select="NavigationFooter" />
|
|
2633
|
+
</div>
|
|
2634
|
+
|
|
2635
|
+
<!-- ROW 2 = child dari menu item aktif; HANYA area ini yang men-scroll. -->
|
|
2636
|
+
<div data-navigation-flyout-scroll="true" [class]="scrollRegionClasses()">
|
|
2637
|
+
@if (activeBranch(); as branch) {
|
|
2638
|
+
<NavigationEntryGrid
|
|
2639
|
+
[navId]="navId()"
|
|
2640
|
+
[branch]="branch"
|
|
2641
|
+
[typeStyle]="typeStyle()"
|
|
2642
|
+
[itemClass]="itemClass()"
|
|
2643
|
+
[activeIds]="activeIds()"
|
|
2644
|
+
[activeUrl]="activeUrl()"
|
|
2645
|
+
[iconTemplate]="iconTemplate()"
|
|
2646
|
+
[collapseTree]="collapseTree()"
|
|
2647
|
+
[openedIds]="openedIds()"
|
|
2648
|
+
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
2649
|
+
(itemSelected)="itemSelected.emit($event)"
|
|
2650
|
+
/>
|
|
2495
2651
|
}
|
|
2496
|
-
</
|
|
2497
|
-
|
|
2498
|
-
@if (activeBranch(); as branch) {
|
|
2499
|
-
<NavigationEntryGrid
|
|
2500
|
-
[navId]="navId()"
|
|
2501
|
-
[branch]="branch"
|
|
2502
|
-
[typeStyle]="typeStyle()"
|
|
2503
|
-
[itemClass]="itemClass()"
|
|
2504
|
-
[activeIds]="activeIds()"
|
|
2505
|
-
[activeUrl]="activeUrl()"
|
|
2506
|
-
[iconTemplate]="iconTemplate()"
|
|
2507
|
-
[collapseTree]="collapseTree()"
|
|
2508
|
-
[openedIds]="openedIds()"
|
|
2509
|
-
(openedIdsChange)="openedIdsChange.emit($event)"
|
|
2510
|
-
(itemSelected)="itemSelected.emit($event)" />
|
|
2511
|
-
}
|
|
2652
|
+
</div>
|
|
2512
2653
|
</div>
|
|
2513
2654
|
</div>
|
|
2514
2655
|
</div>
|
|
2515
2656
|
}
|
|
2516
2657
|
`,
|
|
2517
2658
|
}]
|
|
2518
|
-
}], propDecorators: { navId: [{ type: i0.Input, args: [{ isSignal: true, alias: "navId", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], typeStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "typeStyle", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], itemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClass", required: false }] }], groupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupClass", 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"] }] } });
|
|
2659
|
+
}], propDecorators: { navId: [{ type: i0.Input, args: [{ isSignal: true, alias: "navId", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconPosition", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], floating: [{ type: i0.Input, args: [{ isSignal: true, alias: "floating", required: false }] }], triggerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerClass", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], typeStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "typeStyle", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], itemClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemClass", required: false }] }], groupClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupClass", 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"] }] } });
|
|
2519
2660
|
|
|
2520
2661
|
class NavigationHorizontalComponent {
|
|
2521
2662
|
nav = inject(NavigationService);
|
|
@@ -2527,7 +2668,7 @@ class NavigationHorizontalComponent {
|
|
|
2527
2668
|
/** Posisi bar terhadap konten: `bottom` membuka panel ke atas; selain itu ke bawah. */
|
|
2528
2669
|
position = input('top', /* @ts-ignore */
|
|
2529
2670
|
...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
2530
|
-
typeStyle = input('
|
|
2671
|
+
typeStyle = input('flat', /* @ts-ignore */
|
|
2531
2672
|
...(ngDevMode ? [{ debugName: "typeStyle" }] : /* istanbul ignore next */ []));
|
|
2532
2673
|
compact = input(false, /* @ts-ignore */
|
|
2533
2674
|
...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
|
|
@@ -2555,7 +2696,7 @@ class NavigationHorizontalComponent {
|
|
|
2555
2696
|
/** Kelas tambahan untuk NavigationItem leaf di row saat style border-rail aktif. */
|
|
2556
2697
|
navItemClass = computed(() => cn(this.itemClass(), this.isBorderRail() && 'rounded-none hover:bg-transparent hover:text-primary'), /* @ts-ignore */
|
|
2557
2698
|
...(ngDevMode ? [{ debugName: "navItemClass" }] : /* istanbul ignore next */ []));
|
|
2558
|
-
listClasses = computed(() => cn('flex min-w-0
|
|
2699
|
+
listClasses = computed(() => cn('flex h-full min-w-0 items-center justify-center gap-1 list-none p-0'), /* @ts-ignore */
|
|
2559
2700
|
...(ngDevMode ? [{ debugName: "listClasses" }] : /* istanbul ignore next */ []));
|
|
2560
2701
|
isItemActive(item) {
|
|
2561
2702
|
return this.nav.isItemActive(item, this.activeIds(), this.activeUrl());
|
|
@@ -2635,10 +2776,15 @@ class NavigationHorizontalComponent {
|
|
|
2635
2776
|
// Panel mega selebar container parent, menempel rapat tanpa gap pada sisi bar:
|
|
2636
2777
|
// nav-position top membuka ke bawah (sisi atas siku), bottom membuka ke atas
|
|
2637
2778
|
// (sisi bawah siku) sehingga sambungan border selalu menyatu dengan bar.
|
|
2638
|
-
// Border-rail:
|
|
2639
|
-
//
|
|
2640
|
-
|
|
2641
|
-
|
|
2779
|
+
// Border-rail: sisi kiri/kanan panel dibiarkan ditangani rail vertikal dari
|
|
2780
|
+
// layout; panel hanya menggambar border atas & bawah 1.5px senada rail.
|
|
2781
|
+
// Panel dibiarkan pada tepi bawah bar (`top-full`) tanpa offset, sehingga border
|
|
2782
|
+
// atasnya sejajar dengan border-bottom bar (mis. yang dipasang consumer).
|
|
2783
|
+
return cn('absolute z-50 bg-popover text-popover-foreground shadow-lg',
|
|
2784
|
+
// Batasi tinggi ke viewport (dikurangi area bar) lalu scroll vertikal supaya
|
|
2785
|
+
// menu dengan item banyak tetap bisa diakses tanpa keluar layar.
|
|
2786
|
+
'max-h-[calc(100dvh-5rem)] overflow-x-hidden overflow-y-auto overscroll-contain', this.isBottom() ? 'bottom-full' : 'top-full', !this.panelPlacement() && 'inset-x-0', this.isBorderRail()
|
|
2787
|
+
? 'rounded-none border-y-[1.5px] border-border'
|
|
2642
2788
|
: cn('rounded-xl border border-[hsl(var(--border)/var(--opacity-70))]', this.isBottom() ? 'rounded-b-none' : 'rounded-t-none'));
|
|
2643
2789
|
}
|
|
2644
2790
|
onKeydown(event) {
|
|
@@ -2701,7 +2847,7 @@ class NavigationHorizontalComponent {
|
|
|
2701
2847
|
item?.focus();
|
|
2702
2848
|
}
|
|
2703
2849
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationHorizontalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2704
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationHorizontalComponent, isStandalone: true, selector: "NavigationHorizontal", inputs: { navId: { classPropertyName: "navId", publicName: "navId", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "typeStyle", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null }, groupClass: { classPropertyName: "groupClass", publicName: "groupClass", 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: { listeners: { "window:resize": "onWindowResize()", "document:click": "onDocumentClick($event)" }, classAttribute: "relative block w-full" }, ngImport: i0, template: `
|
|
2850
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationHorizontalComponent, isStandalone: true, selector: "NavigationHorizontal", inputs: { navId: { classPropertyName: "navId", publicName: "navId", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "typeStyle", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null }, itemClass: { classPropertyName: "itemClass", publicName: "itemClass", isSignal: true, isRequired: false, transformFunction: null }, groupClass: { classPropertyName: "groupClass", publicName: "groupClass", 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: { listeners: { "window:resize": "onWindowResize()", "document:click": "onDocumentClick($event)" }, classAttribute: "relative block h-full w-full" }, ngImport: i0, template: `
|
|
2705
2851
|
<ul [class]="listClasses()" role="menubar" (keydown)="onKeydown($event)">
|
|
2706
2852
|
@for (item of items(); track item.key) {
|
|
2707
2853
|
@switch (item.type) {
|
|
@@ -2799,7 +2945,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2799
2945
|
NavigationItemContentComponent,
|
|
2800
2946
|
],
|
|
2801
2947
|
host: {
|
|
2802
|
-
class: 'relative block w-full',
|
|
2948
|
+
class: 'relative block h-full w-full',
|
|
2803
2949
|
'(window:resize)': 'onWindowResize()',
|
|
2804
2950
|
'(document:click)': 'onDocumentClick($event)',
|
|
2805
2951
|
},
|
|
@@ -2900,7 +3046,7 @@ class NavigationContentComponent {
|
|
|
2900
3046
|
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
2901
3047
|
hostClasses = computed(() => cn('min-h-0 flex-1', this.container.displayState().orientation === 'horizontal'
|
|
2902
3048
|
? 'flex h-full min-w-0 items-stretch justify-center overflow-visible'
|
|
2903
|
-
: 'block overflow-y-auto overflow-x-hidden', this.class()), /* @ts-ignore */
|
|
3049
|
+
: 'block overflow-y-auto overflow-x-hidden py-2', this.class()), /* @ts-ignore */
|
|
2904
3050
|
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2905
3051
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2906
3052
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationContentComponent, isStandalone: true, selector: "NavigationContent", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
@@ -2914,6 +3060,9 @@ class NavigationContentComponent {
|
|
|
2914
3060
|
[icon]="container.flyoutIcon()"
|
|
2915
3061
|
[iconOnly]="container.flyoutIconOnly()"
|
|
2916
3062
|
[iconPosition]="container.flyoutIconPosition()"
|
|
3063
|
+
[variant]="container.flyoutTriggerVariant()"
|
|
3064
|
+
[floating]="container.flyoutTriggerFloating()"
|
|
3065
|
+
[triggerClass]="container.flyoutTriggerClass()"
|
|
2917
3066
|
[position]="navState.position"
|
|
2918
3067
|
[typeStyle]="container.typeStyle()"
|
|
2919
3068
|
[compact]="container.compact()"
|
|
@@ -2925,7 +3074,11 @@ class NavigationContentComponent {
|
|
|
2925
3074
|
[collapseTree]="container.collapseTree()"
|
|
2926
3075
|
[openedIds]="container.openedIds()"
|
|
2927
3076
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
2928
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3077
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3078
|
+
>
|
|
3079
|
+
<ng-content select="NavigationHeader" ngProjectAs="NavigationHeader" />
|
|
3080
|
+
<ng-content select="NavigationFooter" ngProjectAs="NavigationFooter" />
|
|
3081
|
+
</NavigationFlyoutMenu>
|
|
2929
3082
|
} @else if (navState.orientation === 'horizontal') {
|
|
2930
3083
|
<NavigationHorizontal
|
|
2931
3084
|
[navId]="navState.id"
|
|
@@ -2941,7 +3094,8 @@ class NavigationContentComponent {
|
|
|
2941
3094
|
[collapseTree]="container.collapseTree()"
|
|
2942
3095
|
[openedIds]="container.openedIds()"
|
|
2943
3096
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
2944
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3097
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3098
|
+
/>
|
|
2945
3099
|
} @else if (navState.type === 'dockbar') {
|
|
2946
3100
|
<NavigationDockbarMenu
|
|
2947
3101
|
[navId]="navState.id"
|
|
@@ -2955,7 +3109,8 @@ class NavigationContentComponent {
|
|
|
2955
3109
|
[collapseTree]="container.collapseTree()"
|
|
2956
3110
|
[openedIds]="container.openedIds()"
|
|
2957
3111
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
2958
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3112
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3113
|
+
/>
|
|
2959
3114
|
} @else {
|
|
2960
3115
|
<NavigationList
|
|
2961
3116
|
[navId]="navState.id"
|
|
@@ -2969,9 +3124,10 @@ class NavigationContentComponent {
|
|
|
2969
3124
|
[collapseTree]="container.collapseTree()"
|
|
2970
3125
|
[openedIds]="container.openedIds()"
|
|
2971
3126
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
2972
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3127
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3128
|
+
/>
|
|
2973
3129
|
}
|
|
2974
|
-
`, isInline: true, dependencies: [{ kind: "component", type: NavigationDockbarMenuComponent, selector: "NavigationDockbarMenu", inputs: ["navId", "items", "mode", "position", "itemClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }, { kind: "component", type: NavigationFlyoutMenuComponent, selector: "NavigationFlyoutMenu", inputs: ["navId", "items", "label", "icon", "iconOnly", "iconPosition", "position", "typeStyle", "compact", "itemClass", "groupClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }, { kind: "component", type: NavigationHorizontalComponent, selector: "NavigationHorizontal", inputs: ["navId", "items", "position", "typeStyle", "compact", "itemClass", "groupClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }, { kind: "component", type: NavigationListComponent, selector: "NavigationList", inputs: ["navId", "items", "collapsed", "compact", "position", "itemClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3130
|
+
`, isInline: true, dependencies: [{ kind: "component", type: NavigationDockbarMenuComponent, selector: "NavigationDockbarMenu", inputs: ["navId", "items", "mode", "position", "itemClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }, { kind: "component", type: NavigationFlyoutMenuComponent, selector: "NavigationFlyoutMenu", inputs: ["navId", "items", "label", "icon", "iconOnly", "iconPosition", "variant", "floating", "triggerClass", "position", "typeStyle", "compact", "itemClass", "groupClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }, { kind: "component", type: NavigationHorizontalComponent, selector: "NavigationHorizontal", inputs: ["navId", "items", "position", "typeStyle", "compact", "itemClass", "groupClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }, { kind: "component", type: NavigationListComponent, selector: "NavigationList", inputs: ["navId", "items", "collapsed", "compact", "position", "itemClass", "activeIds", "activeUrl", "iconTemplate", "collapseTree", "openedIds"], outputs: ["openedIdsChange", "itemSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2975
3131
|
}
|
|
2976
3132
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationContentComponent, decorators: [{
|
|
2977
3133
|
type: Component,
|
|
@@ -2998,6 +3154,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2998
3154
|
[icon]="container.flyoutIcon()"
|
|
2999
3155
|
[iconOnly]="container.flyoutIconOnly()"
|
|
3000
3156
|
[iconPosition]="container.flyoutIconPosition()"
|
|
3157
|
+
[variant]="container.flyoutTriggerVariant()"
|
|
3158
|
+
[floating]="container.flyoutTriggerFloating()"
|
|
3159
|
+
[triggerClass]="container.flyoutTriggerClass()"
|
|
3001
3160
|
[position]="navState.position"
|
|
3002
3161
|
[typeStyle]="container.typeStyle()"
|
|
3003
3162
|
[compact]="container.compact()"
|
|
@@ -3009,7 +3168,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3009
3168
|
[collapseTree]="container.collapseTree()"
|
|
3010
3169
|
[openedIds]="container.openedIds()"
|
|
3011
3170
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
3012
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3171
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3172
|
+
>
|
|
3173
|
+
<ng-content select="NavigationHeader" ngProjectAs="NavigationHeader" />
|
|
3174
|
+
<ng-content select="NavigationFooter" ngProjectAs="NavigationFooter" />
|
|
3175
|
+
</NavigationFlyoutMenu>
|
|
3013
3176
|
} @else if (navState.orientation === 'horizontal') {
|
|
3014
3177
|
<NavigationHorizontal
|
|
3015
3178
|
[navId]="navState.id"
|
|
@@ -3025,7 +3188,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3025
3188
|
[collapseTree]="container.collapseTree()"
|
|
3026
3189
|
[openedIds]="container.openedIds()"
|
|
3027
3190
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
3028
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3191
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3192
|
+
/>
|
|
3029
3193
|
} @else if (navState.type === 'dockbar') {
|
|
3030
3194
|
<NavigationDockbarMenu
|
|
3031
3195
|
[navId]="navState.id"
|
|
@@ -3039,7 +3203,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3039
3203
|
[collapseTree]="container.collapseTree()"
|
|
3040
3204
|
[openedIds]="container.openedIds()"
|
|
3041
3205
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
3042
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3206
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3207
|
+
/>
|
|
3043
3208
|
} @else {
|
|
3044
3209
|
<NavigationList
|
|
3045
3210
|
[navId]="navState.id"
|
|
@@ -3053,7 +3218,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3053
3218
|
[collapseTree]="container.collapseTree()"
|
|
3054
3219
|
[openedIds]="container.openedIds()"
|
|
3055
3220
|
(openedIdsChange)="container.openedIds.set($event)"
|
|
3056
|
-
(itemSelected)="container.itemSelected.emit($event)"
|
|
3221
|
+
(itemSelected)="container.itemSelected.emit($event)"
|
|
3222
|
+
/>
|
|
3057
3223
|
}
|
|
3058
3224
|
`,
|
|
3059
3225
|
}]
|
|
@@ -3070,7 +3236,7 @@ class NavigationFooterComponent {
|
|
|
3070
3236
|
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3071
3237
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3072
3238
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: NavigationFooterComponent, isStandalone: true, selector: "NavigationFooter", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
3073
|
-
<div class="flex h-full items-center">
|
|
3239
|
+
<div class="flex h-full min-w-0 items-center gap-3">
|
|
3074
3240
|
<ng-content />
|
|
3075
3241
|
</div>
|
|
3076
3242
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -3084,7 +3250,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3084
3250
|
'[class]': 'hostClasses()',
|
|
3085
3251
|
},
|
|
3086
3252
|
template: `
|
|
3087
|
-
<div class="flex h-full items-center">
|
|
3253
|
+
<div class="flex h-full min-w-0 items-center gap-3">
|
|
3088
3254
|
<ng-content />
|
|
3089
3255
|
</div>
|
|
3090
3256
|
`,
|
|
@@ -3109,11 +3275,26 @@ class NavigationHeaderComponent {
|
|
|
3109
3275
|
return this.toggle() || (this.shell.collapseEnabled() && !this.displayCollapsed());
|
|
3110
3276
|
}, /* @ts-ignore */
|
|
3111
3277
|
...(ngDevMode ? [{ debugName: "showToggle" }] : /* istanbul ignore next */ []));
|
|
3112
|
-
toggleAriaLabel = computed(() =>
|
|
3278
|
+
toggleAriaLabel = computed(() => this.collapsed() ? 'Expand navigation' : 'Collapse navigation', /* @ts-ignore */
|
|
3113
3279
|
...(ngDevMode ? [{ debugName: "toggleAriaLabel" }] : /* istanbul ignore next */ []));
|
|
3114
|
-
toggleIconName = computed(() =>
|
|
3280
|
+
toggleIconName = computed(() => this.collapsed() ? 'left_panel_open' : 'left_panel_close', /* @ts-ignore */
|
|
3115
3281
|
...(ngDevMode ? [{ debugName: "toggleIconName" }] : /* istanbul ignore next */ []));
|
|
3116
|
-
|
|
3282
|
+
/**
|
|
3283
|
+
* Baris isi header. Saat collapsed/dockbar (vertical) isi (inisial/ikon) dipusatkan di tengah
|
|
3284
|
+
* rail agar simetris dengan ikon nav-item di bawahnya (yang juga center di rail); selain itu kiri
|
|
3285
|
+
* dengan padding `px-3`.
|
|
3286
|
+
*/
|
|
3287
|
+
rowClasses = computed(() => cn('flex h-full items-center', !this.isHorizontal() && this.displayCollapsed() ? 'justify-center' : 'gap-3 px-3'), /* @ts-ignore */
|
|
3288
|
+
...(ngDevMode ? [{ debugName: "rowClasses" }] : /* istanbul ignore next */ []));
|
|
3289
|
+
contentClasses = computed(() => {
|
|
3290
|
+
if (this.isHorizontal()) {
|
|
3291
|
+
return 'flex min-w-0 items-center gap-3';
|
|
3292
|
+
}
|
|
3293
|
+
// Collapsed/dockbar: inisial center (tanpa `flex-1` yang membuatnya rata kiri).
|
|
3294
|
+
return this.displayCollapsed()
|
|
3295
|
+
? 'flex min-w-0 items-center justify-center'
|
|
3296
|
+
: 'flex min-w-0 flex-1 items-center gap-3';
|
|
3297
|
+
}, /* @ts-ignore */
|
|
3117
3298
|
...(ngDevMode ? [{ debugName: "contentClasses" }] : /* istanbul ignore next */ []));
|
|
3118
3299
|
hostClasses = computed(() => cn(this.isHorizontal()
|
|
3119
3300
|
? 'relative z-10 block h-full w-auto shrink-0'
|
|
@@ -3124,7 +3305,7 @@ class NavigationHeaderComponent {
|
|
|
3124
3305
|
}
|
|
3125
3306
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3126
3307
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationHeaderComponent, isStandalone: true, selector: "NavigationHeader", inputs: { toggle: { classPropertyName: "toggle", publicName: "toggle", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.data-collapsed": "displayCollapsed()" } }, ngImport: i0, template: `
|
|
3127
|
-
<div class="
|
|
3308
|
+
<div [class]="rowClasses()">
|
|
3128
3309
|
<div [class]="contentClasses()">
|
|
3129
3310
|
<ng-content />
|
|
3130
3311
|
</div>
|
|
@@ -3136,7 +3317,8 @@ class NavigationHeaderComponent {
|
|
|
3136
3317
|
[attr.aria-label]="toggleAriaLabel()"
|
|
3137
3318
|
[attr.title]="toggleAriaLabel()"
|
|
3138
3319
|
data-navigation-header-toggle="true"
|
|
3139
|
-
(click)="toggleCollapsed()"
|
|
3320
|
+
(click)="toggleCollapsed()"
|
|
3321
|
+
>
|
|
3140
3322
|
<Icon data-navigation-header-toggle-icon="true" [name]="toggleIconName()" [size]="18" />
|
|
3141
3323
|
</button>
|
|
3142
3324
|
}
|
|
@@ -3154,7 +3336,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3154
3336
|
'[attr.data-collapsed]': 'displayCollapsed()',
|
|
3155
3337
|
},
|
|
3156
3338
|
template: `
|
|
3157
|
-
<div class="
|
|
3339
|
+
<div [class]="rowClasses()">
|
|
3158
3340
|
<div [class]="contentClasses()">
|
|
3159
3341
|
<ng-content />
|
|
3160
3342
|
</div>
|
|
@@ -3166,7 +3348,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3166
3348
|
[attr.aria-label]="toggleAriaLabel()"
|
|
3167
3349
|
[attr.title]="toggleAriaLabel()"
|
|
3168
3350
|
data-navigation-header-toggle="true"
|
|
3169
|
-
(click)="toggleCollapsed()"
|
|
3351
|
+
(click)="toggleCollapsed()"
|
|
3352
|
+
>
|
|
3170
3353
|
<Icon data-navigation-header-toggle-icon="true" [name]="toggleIconName()" [size]="18" />
|
|
3171
3354
|
</button>
|
|
3172
3355
|
}
|
|
@@ -3340,7 +3523,7 @@ class NavigationNavbarComponent {
|
|
|
3340
3523
|
destroyRef = inject(DestroyRef);
|
|
3341
3524
|
/** Posisi bar terhadap konten layout: `top` (default) atau `bottom` — panel grid membuka ke arah sebaliknya. */
|
|
3342
3525
|
position = input(null, { ...(ngDevMode ? { debugName: "position" } : /* istanbul ignore next */ {}), alias: 'nav-position' });
|
|
3343
|
-
typeStyle = input('
|
|
3526
|
+
typeStyle = input('flat', { ...(ngDevMode ? { debugName: "typeStyle" } : /* istanbul ignore next */ {}), alias: 'nav-appearance' });
|
|
3344
3527
|
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3345
3528
|
headerSlot = contentChild(NavigationHeaderComponent, /* @ts-ignore */
|
|
3346
3529
|
...(ngDevMode ? [{ debugName: "headerSlot" }] : /* istanbul ignore next */ []));
|
|
@@ -3361,7 +3544,7 @@ class NavigationNavbarComponent {
|
|
|
3361
3544
|
this.destroyRef.onDestroy(() => this.container.unregisterType(config));
|
|
3362
3545
|
}
|
|
3363
3546
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationNavbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3364
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationNavbarComponent, isStandalone: true, selector: "NavigationNavbar", inputs: { position: { classPropertyName: "position", publicName: "nav-position", isSignal: true, isRequired: false, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "nav-
|
|
3547
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationNavbarComponent, isStandalone: true, selector: "NavigationNavbar", inputs: { position: { classPropertyName: "position", publicName: "nav-position", isSignal: true, isRequired: false, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "nav-appearance", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, queries: [{ propertyName: "headerSlot", first: true, predicate: NavigationHeaderComponent, descendants: true, isSignal: true }, { propertyName: "contentSlot", first: true, predicate: NavigationContentComponent, descendants: true, isSignal: true }, { propertyName: "footerSlot", first: true, predicate: NavigationFooterComponent, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3365
3548
|
@if (headerSlot()) {
|
|
3366
3549
|
<ng-content select="NavigationHeader" />
|
|
3367
3550
|
}
|
|
@@ -3402,7 +3585,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3402
3585
|
}
|
|
3403
3586
|
`,
|
|
3404
3587
|
}]
|
|
3405
|
-
}], ctorParameters: () => [], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav-position", required: false }] }], typeStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav-
|
|
3588
|
+
}], ctorParameters: () => [], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav-position", required: false }] }], typeStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav-appearance", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], headerSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NavigationHeaderComponent), { isSignal: true }] }], contentSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NavigationContentComponent), { isSignal: true }] }], footerSlot: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NavigationFooterComponent), { isSignal: true }] }] } });
|
|
3406
3589
|
|
|
3407
3590
|
/**
|
|
3408
3591
|
* Type flyout horizontal (trigger + panel menu) untuk `<Navigation>`.
|
|
@@ -3421,16 +3604,25 @@ class NavigationFlyoutComponent {
|
|
|
3421
3604
|
iconOnly = input(false, { ...(ngDevMode ? { debugName: "iconOnly" } : /* istanbul ignore next */ {}), alias: 'icon-only', transform: booleanAttribute });
|
|
3422
3605
|
/** Penempatan ikon relatif terhadap label: `start` (default) atau `end`. */
|
|
3423
3606
|
iconPosition = input('start', { ...(ngDevMode ? { debugName: "iconPosition" } : /* istanbul ignore next */ {}), alias: 'icon-position' });
|
|
3607
|
+
/** Bentuk visual tombol trigger: `button` (pil, default) | `link` | `plain` (ghost). */
|
|
3608
|
+
triggerVariant = input('button', { ...(ngDevMode ? { debugName: "triggerVariant" } : /* istanbul ignore next */ {}), alias: 'trigger-variant' });
|
|
3609
|
+
/**
|
|
3610
|
+
* Trigger mengambang (`fixed`) alih-alih mengalir di dalam bar/div. Default pojok kanan-atas;
|
|
3611
|
+
* pakai `trigger-class` untuk pindah pojok (mis. `bottom-6 right-6 top-auto`).
|
|
3612
|
+
*
|
|
3613
|
+
* Catatan: `position: fixed` ber-anchor ke viewport HANYA bila tak ada ancestor pembentuk
|
|
3614
|
+
* containing block. Di dalam `<Layout>` (frame-nya memakai `backdrop-blur`), trigger ber-anchor
|
|
3615
|
+
* ke kotak konten frame (bukan viewport sebenarnya) dan bisa ter-clip oleh frame `overflow-hidden`.
|
|
3616
|
+
* Untuk floating sebenar-viewport, tempatkan `<Navigation>` flyout di luar frame `<Layout>`.
|
|
3617
|
+
*/
|
|
3618
|
+
triggerFloating = input(false, { ...(ngDevMode ? { debugName: "triggerFloating" } : /* istanbul ignore next */ {}), alias: 'trigger-floating',
|
|
3619
|
+
transform: booleanAttribute });
|
|
3620
|
+
/** Kelas Tailwind untuk host trigger (posisi pojok floating / styling wrapper saat in-flow). */
|
|
3621
|
+
triggerClass = input('', { ...(ngDevMode ? { debugName: "triggerClass" } : /* istanbul ignore next */ {}), alias: 'trigger-class' });
|
|
3424
3622
|
/** Posisi bar terhadap konten layout: `top` (default) atau `bottom` — panel membuka ke arah sebaliknya. */
|
|
3425
3623
|
position = input(null, { ...(ngDevMode ? { debugName: "position" } : /* istanbul ignore next */ {}), alias: 'nav-position' });
|
|
3426
|
-
typeStyle = input('
|
|
3624
|
+
typeStyle = input('flat', { ...(ngDevMode ? { debugName: "typeStyle" } : /* istanbul ignore next */ {}), alias: 'nav-appearance' });
|
|
3427
3625
|
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3428
|
-
headerSlot = contentChild(NavigationHeaderComponent, /* @ts-ignore */
|
|
3429
|
-
...(ngDevMode ? [{ debugName: "headerSlot" }] : /* istanbul ignore next */ []));
|
|
3430
|
-
contentSlot = contentChild(NavigationContentComponent, /* @ts-ignore */
|
|
3431
|
-
...(ngDevMode ? [{ debugName: "contentSlot" }] : /* istanbul ignore next */ []));
|
|
3432
|
-
footerSlot = contentChild(NavigationFooterComponent, /* @ts-ignore */
|
|
3433
|
-
...(ngDevMode ? [{ debugName: "footerSlot" }] : /* istanbul ignore next */ []));
|
|
3434
3626
|
hostClasses = computed(() => cn(this.container.shellClasses(), this.class()), /* @ts-ignore */
|
|
3435
3627
|
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3436
3628
|
constructor() {
|
|
@@ -3442,26 +3634,24 @@ class NavigationFlyoutComponent {
|
|
|
3442
3634
|
flyoutIcon: this.icon,
|
|
3443
3635
|
flyoutIconOnly: this.iconOnly,
|
|
3444
3636
|
flyoutIconPosition: this.iconPosition,
|
|
3637
|
+
flyoutTriggerVariant: this.triggerVariant,
|
|
3638
|
+
flyoutTriggerFloating: this.triggerFloating,
|
|
3639
|
+
flyoutTriggerClass: this.triggerClass,
|
|
3445
3640
|
typeStyle: this.typeStyle,
|
|
3446
3641
|
};
|
|
3447
3642
|
this.container.registerType(config);
|
|
3448
3643
|
this.destroyRef.onDestroy(() => this.container.unregisterType(config));
|
|
3449
3644
|
}
|
|
3450
3645
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFlyoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3451
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
<ng-content select="
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
}
|
|
3461
|
-
|
|
3462
|
-
@if (footerSlot()) {
|
|
3463
|
-
<ng-content select="NavigationFooter" />
|
|
3464
|
-
}
|
|
3646
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: NavigationFlyoutComponent, isStandalone: true, selector: "NavigationFlyout", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "icon-only", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "icon-position", isSignal: true, isRequired: false, transformFunction: null }, triggerVariant: { classPropertyName: "triggerVariant", publicName: "trigger-variant", isSignal: true, isRequired: false, transformFunction: null }, triggerFloating: { classPropertyName: "triggerFloating", publicName: "trigger-floating", isSignal: true, isRequired: false, transformFunction: null }, triggerClass: { classPropertyName: "triggerClass", publicName: "trigger-class", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "nav-position", isSignal: true, isRequired: false, transformFunction: null }, typeStyle: { classPropertyName: "typeStyle", publicName: "nav-appearance", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
3647
|
+
<!-- Bar hanya berisi trigger (dari NavigationContent → FlyoutMenu); NavigationHeader &
|
|
3648
|
+
NavigationFooter di-re-project ke DALAM panel flyout saat dibuka. Urutan dibaca dari sisi
|
|
3649
|
+
bar ke arah luar: header (menempel bar, sticky) → menu → footer (ujung jauh). Mode top:
|
|
3650
|
+
brand atas, logout bawah; mode bottom: cerminannya (brand bawah dekat bar, logout atas). -->
|
|
3651
|
+
<NavigationContent>
|
|
3652
|
+
<ng-content select="NavigationHeader" ngProjectAs="NavigationHeader" />
|
|
3653
|
+
<ng-content select="NavigationFooter" ngProjectAs="NavigationFooter" />
|
|
3654
|
+
</NavigationContent>
|
|
3465
3655
|
`, isInline: true, dependencies: [{ kind: "component", type: NavigationContentComponent, selector: "NavigationContent", inputs: ["class"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3466
3656
|
}
|
|
3467
3657
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFlyoutComponent, decorators: [{
|
|
@@ -3474,22 +3664,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3474
3664
|
'[class]': 'hostClasses()',
|
|
3475
3665
|
},
|
|
3476
3666
|
template: `
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
<ng-content select="
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
}
|
|
3486
|
-
|
|
3487
|
-
@if (footerSlot()) {
|
|
3488
|
-
<ng-content select="NavigationFooter" />
|
|
3489
|
-
}
|
|
3667
|
+
<!-- Bar hanya berisi trigger (dari NavigationContent → FlyoutMenu); NavigationHeader &
|
|
3668
|
+
NavigationFooter di-re-project ke DALAM panel flyout saat dibuka. Urutan dibaca dari sisi
|
|
3669
|
+
bar ke arah luar: header (menempel bar, sticky) → menu → footer (ujung jauh). Mode top:
|
|
3670
|
+
brand atas, logout bawah; mode bottom: cerminannya (brand bawah dekat bar, logout atas). -->
|
|
3671
|
+
<NavigationContent>
|
|
3672
|
+
<ng-content select="NavigationHeader" ngProjectAs="NavigationHeader" />
|
|
3673
|
+
<ng-content select="NavigationFooter" ngProjectAs="NavigationFooter" />
|
|
3674
|
+
</NavigationContent>
|
|
3490
3675
|
`,
|
|
3491
3676
|
}]
|
|
3492
|
-
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon-only", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon-position", required: false }] }],
|
|
3677
|
+
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon-only", required: false }] }], iconPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon-position", required: false }] }], triggerVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger-variant", required: false }] }], triggerFloating: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger-floating", required: false }] }], triggerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger-class", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav-position", required: false }] }], typeStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "nav-appearance", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3493
3678
|
|
|
3494
3679
|
/**
|
|
3495
3680
|
* Tampilan compact aktif saat sidebar collapsible sedang collapsed, atau saat
|
|
@@ -3560,8 +3745,270 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3560
3745
|
}]
|
|
3561
3746
|
}], ctorParameters: () => [] });
|
|
3562
3747
|
|
|
3748
|
+
/**
|
|
3749
|
+
* Slot aksi di sisi kanan `NavigationFooter`. Selalu didorong ke kanan (`ml-auto`),
|
|
3750
|
+
* rata tengah vertikal, dengan jarak antar-child otomatis (`gap`). Isi bebas dengan
|
|
3751
|
+
* ikon, button, atau teks — mis. tombol logout.
|
|
3752
|
+
*
|
|
3753
|
+
* Otomatis disembunyikan saat sidebar vertical sedang collapsed (rail icon-only)
|
|
3754
|
+
* agar tidak overflow; konsisten dengan `NavigationFooterTitle`.
|
|
3755
|
+
*/
|
|
3756
|
+
class NavigationFooterActionComponent {
|
|
3757
|
+
shell = inject(NAVIGATION_SHELL, { optional: true });
|
|
3758
|
+
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3759
|
+
collapsed = computed(() => {
|
|
3760
|
+
const state = this.shell?.displayState();
|
|
3761
|
+
return state ? state.orientation === 'vertical' && state.collapsed : false;
|
|
3762
|
+
}, /* @ts-ignore */
|
|
3763
|
+
...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
3764
|
+
hostClasses = computed(() => cn(this.collapsed() ? 'hidden' : 'ml-auto flex shrink-0 items-center gap-1', this.class()), /* @ts-ignore */
|
|
3765
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3766
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFooterActionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3767
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: NavigationFooterActionComponent, isStandalone: true, selector: "NavigationFooterAction", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3768
|
+
}
|
|
3769
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFooterActionComponent, decorators: [{
|
|
3770
|
+
type: Component,
|
|
3771
|
+
args: [{
|
|
3772
|
+
selector: 'NavigationFooterAction',
|
|
3773
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3774
|
+
host: {
|
|
3775
|
+
'[class]': 'hostClasses()',
|
|
3776
|
+
},
|
|
3777
|
+
template: `<ng-content />`,
|
|
3778
|
+
}]
|
|
3779
|
+
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3780
|
+
|
|
3781
|
+
/**
|
|
3782
|
+
* Turunkan inisial ringkas dari sebuah nama untuk avatar fallback.
|
|
3783
|
+
*
|
|
3784
|
+
* "Ojie Permana" → "OP"
|
|
3785
|
+
* "Ojiepermana" → "OJ"
|
|
3786
|
+
* "" → ""
|
|
3787
|
+
*
|
|
3788
|
+
* Mengambil huruf depan kata pertama dan kata terakhir; bila hanya satu kata,
|
|
3789
|
+
* memakai dua huruf pertamanya.
|
|
3790
|
+
*/
|
|
3791
|
+
function deriveNavigationInitials(name) {
|
|
3792
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
3793
|
+
if (parts.length === 0) {
|
|
3794
|
+
return '';
|
|
3795
|
+
}
|
|
3796
|
+
const first = parts[0] ?? '';
|
|
3797
|
+
if (parts.length === 1) {
|
|
3798
|
+
return first.slice(0, 2).toUpperCase();
|
|
3799
|
+
}
|
|
3800
|
+
const last = parts[parts.length - 1] ?? '';
|
|
3801
|
+
return (first.charAt(0) + last.charAt(0)).toUpperCase();
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3804
|
+
/**
|
|
3805
|
+
* Blok avatar/inisial untuk slot `NavigationFooter` (profil user). Sama seperti
|
|
3806
|
+
* `NavigationHeaderInitial` tetapi default-nya bulat (rounded-full) sesuai
|
|
3807
|
+
* konvensi avatar user. Consumer cukup memberi `name`; inisial diturunkan
|
|
3808
|
+
* otomatis. Beri `src` untuk foto, `icon` untuk material symbol, atau `initials`
|
|
3809
|
+
* untuk override.
|
|
3810
|
+
*
|
|
3811
|
+
* Tetap tampil saat sidebar collapsed; pasangannya `NavigationFooterTitle` yang
|
|
3812
|
+
* menyembunyikan diri.
|
|
3813
|
+
*/
|
|
3814
|
+
class NavigationFooterInitialComponent {
|
|
3815
|
+
name = input('', /* @ts-ignore */
|
|
3816
|
+
...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
3817
|
+
src = input(null, /* @ts-ignore */
|
|
3818
|
+
...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
3819
|
+
initials = input(null, /* @ts-ignore */
|
|
3820
|
+
...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
|
|
3821
|
+
icon = input(null, /* @ts-ignore */
|
|
3822
|
+
...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
3823
|
+
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3824
|
+
resolvedInitials = computed(() => this.initials()?.slice(0, 2).toUpperCase() || deriveNavigationInitials(this.name()), /* @ts-ignore */
|
|
3825
|
+
...(ngDevMode ? [{ debugName: "resolvedInitials" }] : /* istanbul ignore next */ []));
|
|
3826
|
+
hostClasses = computed(() => cn('inline-flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full bg-primary/10 text-primary', this.class()), /* @ts-ignore */
|
|
3827
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3828
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFooterInitialComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3829
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationFooterInitialComponent, isStandalone: true, selector: "NavigationFooterInitial", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.role": "name() ? 'img' : null", "attr.aria-label": "name() || null" } }, ngImport: i0, template: `
|
|
3830
|
+
@if (src(); as source) {
|
|
3831
|
+
<img [src]="source" alt="" class="h-full w-full rounded-[inherit] object-cover" />
|
|
3832
|
+
} @else if (icon(); as glyph) {
|
|
3833
|
+
<Icon [name]="glyph" [size]="18" />
|
|
3834
|
+
} @else {
|
|
3835
|
+
<span class="text-xs font-semibold leading-none">{{ resolvedInitials() }}</span>
|
|
3836
|
+
}
|
|
3837
|
+
`, isInline: true, dependencies: [{ kind: "component", type: IconComponent, selector: "Icon", inputs: ["name", "class", "size", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3838
|
+
}
|
|
3839
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFooterInitialComponent, decorators: [{
|
|
3840
|
+
type: Component,
|
|
3841
|
+
args: [{
|
|
3842
|
+
selector: 'NavigationFooterInitial',
|
|
3843
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3844
|
+
imports: [IconComponent],
|
|
3845
|
+
host: {
|
|
3846
|
+
'[class]': 'hostClasses()',
|
|
3847
|
+
'[attr.role]': "name() ? 'img' : null",
|
|
3848
|
+
'[attr.aria-label]': 'name() || null',
|
|
3849
|
+
},
|
|
3850
|
+
template: `
|
|
3851
|
+
@if (src(); as source) {
|
|
3852
|
+
<img [src]="source" alt="" class="h-full w-full rounded-[inherit] object-cover" />
|
|
3853
|
+
} @else if (icon(); as glyph) {
|
|
3854
|
+
<Icon [name]="glyph" [size]="18" />
|
|
3855
|
+
} @else {
|
|
3856
|
+
<span class="text-xs font-semibold leading-none">{{ resolvedInitials() }}</span>
|
|
3857
|
+
}
|
|
3858
|
+
`,
|
|
3859
|
+
}]
|
|
3860
|
+
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3861
|
+
|
|
3862
|
+
/**
|
|
3863
|
+
* Judul + subjudul untuk slot `NavigationFooter` (mis. nama + email user).
|
|
3864
|
+
* Otomatis disembunyikan saat sidebar vertical sedang collapsed (rail icon-only)
|
|
3865
|
+
* dengan membaca `NAVIGATION_SHELL`.
|
|
3866
|
+
*/
|
|
3867
|
+
class NavigationFooterTitleComponent {
|
|
3868
|
+
shell = inject(NAVIGATION_SHELL, { optional: true });
|
|
3869
|
+
title = input('', /* @ts-ignore */
|
|
3870
|
+
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
3871
|
+
subtitle = input(null, /* @ts-ignore */
|
|
3872
|
+
...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
3873
|
+
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3874
|
+
collapsed = computed(() => {
|
|
3875
|
+
const state = this.shell?.displayState();
|
|
3876
|
+
return state ? state.orientation === 'vertical' && state.collapsed : false;
|
|
3877
|
+
}, /* @ts-ignore */
|
|
3878
|
+
...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
3879
|
+
hostClasses = computed(() => cn(this.collapsed() ? 'hidden' : 'flex min-w-0 flex-col justify-center', this.class()), /* @ts-ignore */
|
|
3880
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3881
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFooterTitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3882
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationFooterTitleComponent, isStandalone: true, selector: "NavigationFooterTitle", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.data-collapsed": "collapsed()" } }, ngImport: i0, template: `
|
|
3883
|
+
<span class="block truncate text-sm font-semibold leading-tight text-foreground">{{ title() }}</span>
|
|
3884
|
+
@if (subtitle(); as sub) {
|
|
3885
|
+
<span class="block truncate text-xs leading-tight text-muted-foreground">{{ sub }}</span>
|
|
3886
|
+
}
|
|
3887
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3888
|
+
}
|
|
3889
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationFooterTitleComponent, decorators: [{
|
|
3890
|
+
type: Component,
|
|
3891
|
+
args: [{
|
|
3892
|
+
selector: 'NavigationFooterTitle',
|
|
3893
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3894
|
+
host: {
|
|
3895
|
+
'[class]': 'hostClasses()',
|
|
3896
|
+
'[attr.data-collapsed]': 'collapsed()',
|
|
3897
|
+
},
|
|
3898
|
+
template: `
|
|
3899
|
+
<span class="block truncate text-sm font-semibold leading-tight text-foreground">{{ title() }}</span>
|
|
3900
|
+
@if (subtitle(); as sub) {
|
|
3901
|
+
<span class="block truncate text-xs leading-tight text-muted-foreground">{{ sub }}</span>
|
|
3902
|
+
}
|
|
3903
|
+
`,
|
|
3904
|
+
}]
|
|
3905
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3906
|
+
|
|
3907
|
+
/**
|
|
3908
|
+
* Blok avatar/inisial untuk slot `NavigationHeader` (brand/logo). Consumer cukup
|
|
3909
|
+
* memberi `name`; inisial diturunkan otomatis ("Ojie Permana" → "OP"). Beri `src`
|
|
3910
|
+
* untuk gambar, `icon` (material symbol) sebagai ganti inisial, atau `initials`
|
|
3911
|
+
* untuk override manual.
|
|
3912
|
+
*
|
|
3913
|
+
* Selalu tampil baik saat sidebar expanded maupun collapsed karena ukurannya muat
|
|
3914
|
+
* di rail icon-only — pasangannya, `NavigationHeaderTitle`, yang menyembunyikan
|
|
3915
|
+
* diri saat collapsed.
|
|
3916
|
+
*/
|
|
3917
|
+
class NavigationHeaderInitialComponent {
|
|
3918
|
+
name = input('', /* @ts-ignore */
|
|
3919
|
+
...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
3920
|
+
src = input(null, /* @ts-ignore */
|
|
3921
|
+
...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
3922
|
+
initials = input(null, /* @ts-ignore */
|
|
3923
|
+
...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
|
|
3924
|
+
icon = input(null, /* @ts-ignore */
|
|
3925
|
+
...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
3926
|
+
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3927
|
+
resolvedInitials = computed(() => this.initials()?.slice(0, 2).toUpperCase() || deriveNavigationInitials(this.name()), /* @ts-ignore */
|
|
3928
|
+
...(ngDevMode ? [{ debugName: "resolvedInitials" }] : /* istanbul ignore next */ []));
|
|
3929
|
+
hostClasses = computed(() => cn('inline-flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-md bg-primary/10 text-primary', this.class()), /* @ts-ignore */
|
|
3930
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3931
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationHeaderInitialComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3932
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationHeaderInitialComponent, isStandalone: true, selector: "NavigationHeaderInitial", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.role": "name() ? 'img' : null", "attr.aria-label": "name() || null" } }, ngImport: i0, template: `
|
|
3933
|
+
@if (src(); as source) {
|
|
3934
|
+
<img [src]="source" alt="" class="h-full w-full rounded-[inherit] object-cover" />
|
|
3935
|
+
} @else if (icon(); as glyph) {
|
|
3936
|
+
<Icon [name]="glyph" [size]="18" />
|
|
3937
|
+
} @else {
|
|
3938
|
+
<span class="text-xs font-semibold leading-none">{{ resolvedInitials() }}</span>
|
|
3939
|
+
}
|
|
3940
|
+
`, isInline: true, dependencies: [{ kind: "component", type: IconComponent, selector: "Icon", inputs: ["name", "class", "size", "fill", "weight", "grade", "opticalSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3941
|
+
}
|
|
3942
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationHeaderInitialComponent, decorators: [{
|
|
3943
|
+
type: Component,
|
|
3944
|
+
args: [{
|
|
3945
|
+
selector: 'NavigationHeaderInitial',
|
|
3946
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3947
|
+
imports: [IconComponent],
|
|
3948
|
+
host: {
|
|
3949
|
+
'[class]': 'hostClasses()',
|
|
3950
|
+
'[attr.role]': "name() ? 'img' : null",
|
|
3951
|
+
'[attr.aria-label]': 'name() || null',
|
|
3952
|
+
},
|
|
3953
|
+
template: `
|
|
3954
|
+
@if (src(); as source) {
|
|
3955
|
+
<img [src]="source" alt="" class="h-full w-full rounded-[inherit] object-cover" />
|
|
3956
|
+
} @else if (icon(); as glyph) {
|
|
3957
|
+
<Icon [name]="glyph" [size]="18" />
|
|
3958
|
+
} @else {
|
|
3959
|
+
<span class="text-xs font-semibold leading-none">{{ resolvedInitials() }}</span>
|
|
3960
|
+
}
|
|
3961
|
+
`,
|
|
3962
|
+
}]
|
|
3963
|
+
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3964
|
+
|
|
3965
|
+
/**
|
|
3966
|
+
* Judul + subjudul untuk slot `NavigationHeader`. Otomatis disembunyikan saat
|
|
3967
|
+
* sidebar vertical sedang collapsed (rail icon-only) dengan membaca
|
|
3968
|
+
* `NAVIGATION_SHELL` — consumer tidak perlu mengelola state collapse sendiri.
|
|
3969
|
+
*/
|
|
3970
|
+
class NavigationHeaderTitleComponent {
|
|
3971
|
+
shell = inject(NAVIGATION_SHELL, { optional: true });
|
|
3972
|
+
title = input('', /* @ts-ignore */
|
|
3973
|
+
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
3974
|
+
subtitle = input(null, /* @ts-ignore */
|
|
3975
|
+
...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
3976
|
+
class = input('', { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3977
|
+
collapsed = computed(() => {
|
|
3978
|
+
const state = this.shell?.displayState();
|
|
3979
|
+
return state ? state.orientation === 'vertical' && state.collapsed : false;
|
|
3980
|
+
}, /* @ts-ignore */
|
|
3981
|
+
...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
3982
|
+
hostClasses = computed(() => cn(this.collapsed() ? 'hidden' : 'flex min-w-0 flex-col justify-center', this.class()), /* @ts-ignore */
|
|
3983
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3984
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationHeaderTitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3985
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: NavigationHeaderTitleComponent, isStandalone: true, selector: "NavigationHeaderTitle", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.data-collapsed": "collapsed()" } }, ngImport: i0, template: `
|
|
3986
|
+
<span class="block truncate text-sm font-semibold leading-tight text-foreground">{{ title() }}</span>
|
|
3987
|
+
@if (subtitle(); as sub) {
|
|
3988
|
+
<span class="block truncate text-xs leading-tight text-muted-foreground">{{ sub }}</span>
|
|
3989
|
+
}
|
|
3990
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3991
|
+
}
|
|
3992
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: NavigationHeaderTitleComponent, decorators: [{
|
|
3993
|
+
type: Component,
|
|
3994
|
+
args: [{
|
|
3995
|
+
selector: 'NavigationHeaderTitle',
|
|
3996
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3997
|
+
host: {
|
|
3998
|
+
'[class]': 'hostClasses()',
|
|
3999
|
+
'[attr.data-collapsed]': 'collapsed()',
|
|
4000
|
+
},
|
|
4001
|
+
template: `
|
|
4002
|
+
<span class="block truncate text-sm font-semibold leading-tight text-foreground">{{ title() }}</span>
|
|
4003
|
+
@if (subtitle(); as sub) {
|
|
4004
|
+
<span class="block truncate text-xs leading-tight text-muted-foreground">{{ sub }}</span>
|
|
4005
|
+
}
|
|
4006
|
+
`,
|
|
4007
|
+
}]
|
|
4008
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
4009
|
+
|
|
3563
4010
|
/**
|
|
3564
4011
|
* Generated bundle index. Do not edit.
|
|
3565
4012
|
*/
|
|
3566
4013
|
|
|
3567
|
-
export { NavigationCollapseExpandedDirective, NavigationCollapseRootDirective, NavigationContainerComponent, NavigationContentComponent, NavigationDockbarComponent, NavigationFlyoutComponent, NavigationFooterComponent, NavigationHeaderComponent, NavigationIconDirective, NavigationNavbarComponent, NavigationSidebarComponent, normalizeUiNavItems };
|
|
4014
|
+
export { NavigationCollapseExpandedDirective, NavigationCollapseRootDirective, NavigationContainerComponent, NavigationContentComponent, NavigationDockbarComponent, NavigationFlyoutComponent, NavigationFooterActionComponent, NavigationFooterComponent, NavigationFooterInitialComponent, NavigationFooterTitleComponent, NavigationHeaderComponent, NavigationHeaderInitialComponent, NavigationHeaderTitleComponent, NavigationIconDirective, NavigationNavbarComponent, NavigationSidebarComponent, deriveNavigationInitials, normalizeUiNavItems };
|