yukit-web 0.0.8 → 0.0.10
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/.npm/_cacache/content-v2/sha512/18/79/a746b85a1e5f78160e21b8778eed881794235757188ad74ecaee7594e73d09ad3f3329fac07cab4b44a44b2c4acf3120eac007e148ab60864dcf52f6cf2e +1 -0
- package/.npm/_cacache/index-v5/64/dc/73c7a26f2e6eb0c711133d96c247da5ecf0eba708cd37c450a7b3c7cb488 +1 -1
- package/.npm/_logs/{2026-08-27T14_38_45_040Z-debug-0.log → 2026-08-31T11_23_18_129Z-debug-0.log} +10 -10
- package/.npm/_logs/{2026-08-27T14_38_45_607Z-debug-0.log → 2026-08-31T11_23_18_708Z-debug-0.log} +2 -2
- package/fesm2022/yukit-web.mjs +222 -240
- package/fesm2022/yukit-web.mjs.map +1 -1
- package/package.json +1 -1
- package/types/yukit-web.d.ts +66 -131
- package/.npm/_cacache/content-v2/sha512/0d/0d/9afe7385c2515aaf1728dce41fa0c3d4593176eb0a2df03a967eda797ee2f398ff4f1dd0c25c50b676962a78b5c1320c25154d62debcae3769db14b41dbd +0 -1
package/fesm2022/yukit-web.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { forwardRef, signal, Directive, input, inject, TemplateRef, ElementRef, booleanAttribute, output, computed, contentChildren, ChangeDetectionStrategy, Component, model, contentChild, viewChild, Injector, afterNextRender, effect, numberAttribute, linkedSignal, Injectable,
|
|
4
|
+
import { forwardRef, signal, Directive, input, inject, TemplateRef, ElementRef, booleanAttribute, output, computed, contentChildren, ChangeDetectionStrategy, Component, model, contentChild, viewChild, Injector, afterNextRender, effect, numberAttribute, linkedSignal, Injectable, runInInjectionContext } from '@angular/core';
|
|
5
5
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
6
|
import { NgTemplateOutlet } from '@angular/common';
|
|
7
7
|
import { HlmButton, provideBrnButtonConfig } from 'yukit-web/helm/button';
|
|
@@ -48,7 +48,7 @@ import * as i1$c from 'yukit-web/helm/table';
|
|
|
48
48
|
import { HlmTableContainer, HlmTable, HlmTHead, HlmTBody, HlmTFoot, HlmTr, HlmTh, HlmTd, HlmCaption } from 'yukit-web/helm/table';
|
|
49
49
|
import { injectTable, FlexRenderDirective } from '@tanstack/angular-table';
|
|
50
50
|
import { rowSortingFeature, rowSelectionFeature, rowPaginationFeature, columnVisibilityFeature, columnFilteringFeature, sortFns, createPaginatedRowModel, createSortedRowModel, createFilteredRowModel, createCoreRowModel } from '@tanstack/table-core';
|
|
51
|
-
import { skip, switchMap, timer, of
|
|
51
|
+
import { skip, switchMap, timer, of } from 'rxjs';
|
|
52
52
|
import * as i1$d from 'yukit-web/helm/avatar';
|
|
53
53
|
import { HlmAvatarImports } from 'yukit-web/helm/avatar';
|
|
54
54
|
import * as i1$e from 'yukit-web/helm/item';
|
|
@@ -56,7 +56,7 @@ import { HlmItem, HlmItemHeader, HlmItemMedia, HlmItemContent, HlmItemTitle, Hlm
|
|
|
56
56
|
import * as i1$f from '@spartan-ng/brain/sheet';
|
|
57
57
|
import { BrnSheetTrigger, BrnSheetClose } from '@spartan-ng/brain/sheet';
|
|
58
58
|
import * as i1$g from 'yukit-web/helm/sheet';
|
|
59
|
-
import { HlmSheetImports } from 'yukit-web/helm/sheet';
|
|
59
|
+
import { HlmSheet, HlmSheetImports } from 'yukit-web/helm/sheet';
|
|
60
60
|
import * as i1$i from 'yukit-web/helm/popover';
|
|
61
61
|
import { HlmPopoverImports } from 'yukit-web/helm/popover';
|
|
62
62
|
import * as i1$h from '@spartan-ng/brain/popover';
|
|
@@ -81,14 +81,12 @@ import * as i1$o from 'yukit-web/helm/tabs';
|
|
|
81
81
|
import { HlmTabsImports } from 'yukit-web/helm/tabs';
|
|
82
82
|
import * as i1$p from 'yukit-web/helm/attachment';
|
|
83
83
|
import { HlmAttachment, HlmAttachmentGroup, HlmAttachmentMedia, HlmAttachmentContent, HlmAttachmentTitle, HlmAttachmentDescription, HlmAttachmentActions, HlmAttachmentAction, HlmAttachmentTrigger } from 'yukit-web/helm/attachment';
|
|
84
|
-
import { map, distinctUntilChanged
|
|
84
|
+
import { map, distinctUntilChanged } from 'rxjs/operators';
|
|
85
85
|
import * as i1$q from 'yukit-web/helm/sidebar';
|
|
86
86
|
import { HlmSidebarService, HlmSidebarWrapper, HlmSidebarHeader, HlmSidebarContent, HlmSidebarFooter, HlmSidebarGroup, HlmSidebarGroupLabel, HlmSidebarGroupContent, HlmSidebarMenu, HlmSidebarMenuItem, HlmSidebarMenuButton, HlmSidebarMenuBadge, HlmSidebarMenuSub, HlmSidebarMenuSubItem, HlmSidebarMenuSubButton, HlmSidebarSeparator, HlmSidebarRail, HlmSidebarInset, injectHlmSidebarConfig, HlmSidebar, HlmSidebarTrigger } from 'yukit-web/helm/sidebar';
|
|
87
87
|
export { HlmSidebarService as YuwSidebarService, provideHlmSidebarConfig as provideYuwSidebarConfig } from 'yukit-web/helm/sidebar';
|
|
88
88
|
import { Router, isActive, RouterLink, RouterLinkActive } from '@angular/router';
|
|
89
|
-
import
|
|
90
|
-
import { HlmHoverCardPortal, HlmHoverCardContent } from 'yukit-web/helm/hover-card';
|
|
91
|
-
import { BrnHoverCardContentService } from '@spartan-ng/brain/hover-card';
|
|
89
|
+
import { OverlayContainer } from '@angular/cdk/overlay';
|
|
92
90
|
|
|
93
91
|
/**
|
|
94
92
|
* Merges class lists the shadcn/Spartan way: `clsx` resolves conditionals/arrays, `twMerge`
|
|
@@ -3216,6 +3214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
3216
3214
|
}]
|
|
3217
3215
|
}] });
|
|
3218
3216
|
|
|
3217
|
+
const YUW_SHEET_OVERLAY_BASE_CLASS = 'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 isolate bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs';
|
|
3219
3218
|
/**
|
|
3220
3219
|
* Slide-in sheet overlay panel component for side drawers, dialogs, and detail views.
|
|
3221
3220
|
*
|
|
@@ -3234,7 +3233,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
3234
3233
|
* renders and screen readers read this label; when absent there is no close button. User-facing
|
|
3235
3234
|
* text the consuming app is responsible for translating.
|
|
3236
3235
|
* - `panelClass`: Extra classes merged onto the sheet panel (e.g. `sm:max-w-lg` to widen it).
|
|
3237
|
-
* They win over the library defaults via `twMerge`.
|
|
3236
|
+
* They win over the library defaults via `twMerge`. Note `twMerge` resolves per variant group, so a
|
|
3237
|
+
* plain utility does not displace a variant-prefixed default — to override `data-[side=left]:w-3/4`
|
|
3238
|
+
* the class has to be `data-[side=left]:w-64`, not `w-64`.
|
|
3239
|
+
* - `overlayClass`: Extra classes for the backdrop, for a sheet that should not dim the whole
|
|
3240
|
+
* viewport. Applied through `setOverlayClass` rather than a template binding: the backdrop lives in
|
|
3241
|
+
* the overlay too, and the helm's own class always wins the `class` input it exposes.
|
|
3242
|
+
* - `scrollStrategy`: What happens to page scroll while open. Defaults to the brain's blocking
|
|
3243
|
+
* strategy; pass `'reposition'` for a panel that should leave the page scrollable.
|
|
3244
|
+
* - `ariaModal`: Whether the sheet claims the rest of the page is hidden. Leave `true` for a real
|
|
3245
|
+
* modal; set `false` when content outside stays visible and usable, so the claim stays honest.
|
|
3246
|
+
* - `closeOnOutsidePointerEvents`: Whether a pointer press outside the panel closes it. Default is
|
|
3247
|
+
* `false`, matching the brain.
|
|
3238
3248
|
* - `triggerVariant`: Button style variant for the trigger button.
|
|
3239
3249
|
* - `triggerSize`: Button size for the trigger button.
|
|
3240
3250
|
*
|
|
@@ -3253,6 +3263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
3253
3263
|
*/
|
|
3254
3264
|
class YuwSheetComponent {
|
|
3255
3265
|
constructor() {
|
|
3266
|
+
this.sheet = viewChild.required(HlmSheet);
|
|
3256
3267
|
this.open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
3257
3268
|
this.showTrigger = input(true, { ...(ngDevMode ? { debugName: "showTrigger" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3258
3269
|
this.side = input('right', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
|
|
@@ -3261,23 +3272,33 @@ class YuwSheetComponent {
|
|
|
3261
3272
|
this.ariaLabel = input(undefined, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
3262
3273
|
this.closeLabel = input(undefined, ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
|
|
3263
3274
|
this.panelClass = input(undefined, ...(ngDevMode ? [{ debugName: "panelClass" }] : /* istanbul ignore next */ []));
|
|
3275
|
+
this.overlayClass = input(undefined, ...(ngDevMode ? [{ debugName: "overlayClass" }] : /* istanbul ignore next */ []));
|
|
3276
|
+
this.scrollStrategy = input(null, ...(ngDevMode ? [{ debugName: "scrollStrategy" }] : /* istanbul ignore next */ []));
|
|
3277
|
+
this.ariaModal = input(true, { ...(ngDevMode ? { debugName: "ariaModal" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3278
|
+
this.closeOnOutsidePointerEvents = input(false, { ...(ngDevMode ? { debugName: "closeOnOutsidePointerEvents" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3264
3279
|
this.triggerVariant = input('outline', ...(ngDevMode ? [{ debugName: "triggerVariant" }] : /* istanbul ignore next */ []));
|
|
3265
3280
|
this.triggerSize = input('default', ...(ngDevMode ? [{ debugName: "triggerSize" }] : /* istanbul ignore next */ []));
|
|
3266
3281
|
this.hasFooter = contentChild(YuwSheetFooterDirective, ...(ngDevMode ? [{ debugName: "hasFooter" }] : /* istanbul ignore next */ []));
|
|
3267
3282
|
this._sheetState = computed(() => (this.open() ? 'open' : 'closed'), ...(ngDevMode ? [{ debugName: "_sheetState" }] : /* istanbul ignore next */ []));
|
|
3283
|
+
effect(() => {
|
|
3284
|
+
const overlayClass = this.overlayClass();
|
|
3285
|
+
if (overlayClass === undefined)
|
|
3286
|
+
return;
|
|
3287
|
+
this.sheet().setOverlayClass(`${YUW_SHEET_OVERLAY_BASE_CLASS} ${overlayClass}`);
|
|
3288
|
+
});
|
|
3268
3289
|
}
|
|
3269
3290
|
onStateChanged(state) {
|
|
3270
3291
|
this.open.set(state === 'open');
|
|
3271
3292
|
}
|
|
3272
3293
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3273
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: YuwSheetComponent, isStandalone: true, selector: "yuw-sheet", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, showTrigger: { classPropertyName: "showTrigger", publicName: "showTrigger", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, triggerVariant: { classPropertyName: "triggerVariant", publicName: "triggerVariant", isSignal: true, isRequired: false, transformFunction: null }, triggerSize: { classPropertyName: "triggerSize", publicName: "triggerSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideX })], queries: [{ propertyName: "hasFooter", first: true, predicate: YuwSheetFooterDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<hlm-sheet
|
|
3294
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: YuwSheetComponent, isStandalone: true, selector: "yuw-sheet", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, showTrigger: { classPropertyName: "showTrigger", publicName: "showTrigger", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, overlayClass: { classPropertyName: "overlayClass", publicName: "overlayClass", isSignal: true, isRequired: false, transformFunction: null }, scrollStrategy: { classPropertyName: "scrollStrategy", publicName: "scrollStrategy", isSignal: true, isRequired: false, transformFunction: null }, ariaModal: { classPropertyName: "ariaModal", publicName: "ariaModal", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsidePointerEvents: { classPropertyName: "closeOnOutsidePointerEvents", publicName: "closeOnOutsidePointerEvents", isSignal: true, isRequired: false, transformFunction: null }, triggerVariant: { classPropertyName: "triggerVariant", publicName: "triggerVariant", isSignal: true, isRequired: false, transformFunction: null }, triggerSize: { classPropertyName: "triggerSize", publicName: "triggerSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideX })], queries: [{ propertyName: "hasFooter", first: true, predicate: YuwSheetFooterDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "sheet", first: true, predicate: HlmSheet, descendants: true, isSignal: true }], ngImport: i0, template: "<hlm-sheet\n [side]=\"side()\"\n [state]=\"_sheetState()\"\n [aria-label]=\"ariaLabel()\"\n [aria-modal]=\"ariaModal()\"\n [scrollStrategy]=\"scrollStrategy()\"\n [closeOnOutsidePointerEvents]=\"closeOnOutsidePointerEvents()\"\n (stateChanged)=\"onStateChanged($event)\"\n>\n @if (showTrigger()) {\n <yuw-button yuwSheetTriggerButton [variant]=\"triggerVariant()\" [size]=\"triggerSize()\">\n <ng-content select=\"[yuwSheetTrigger]\" />\n </yuw-button>\n }\n\n <hlm-sheet-content *hlmSheetPortal [showCloseButton]=\"false\" [class]=\"panelClass()\">\n @if (title() || description()) {\n <div hlmSheetHeader>\n @if (title()) {\n <h2 hlmSheetTitle>{{ title() }}</h2>\n }\n @if (description()) {\n <p hlmSheetDescription>{{ description() }}</p>\n }\n </div>\n }\n\n <div class=\"flex-1 overflow-y-auto px-4\">\n <ng-content />\n </div>\n\n @if (hasFooter()) {\n <div hlmSheetFooter>\n <ng-content select=\"[yuwSheetFooter]\" />\n </div>\n }\n\n @if (closeLabel()) {\n <div class=\"absolute inset-e-3 top-3\">\n <yuw-button yuwSheetClose variant=\"ghost\" size=\"icon-sm\">\n <ng-icon yuwButtonIcon name=\"lucideX\" />\n <span class=\"sr-only\">{{ closeLabel() }}</span>\n </yuw-button>\n </div>\n }\n </hlm-sheet-content>\n</hlm-sheet>\n", dependencies: [{ kind: "component", type: i1$g.HlmSheet, selector: "hlm-sheet", exportAs: ["hlmSheet"] }, { kind: "component", type: i1$g.HlmSheetContent, selector: "hlm-sheet-content", inputs: ["showCloseButton"] }, { kind: "directive", type: i1$g.HlmSheetDescription, selector: "[hlmSheetDescription]" }, { kind: "directive", type: i1$g.HlmSheetFooter, selector: "[hlmSheetFooter],hlm-sheet-footer" }, { kind: "directive", type: i1$g.HlmSheetHeader, selector: "[hlmSheetHeader],hlm-sheet-header" }, { kind: "directive", type: i1$g.HlmSheetPortal, selector: "[hlmSheetPortal]" }, { kind: "directive", type: i1$g.HlmSheetTitle, selector: "[hlmSheetTitle]" }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["variant", "size", "color", "disabled", "type", "href", "target", "transparent", "yuwDropdownMenuTrigger", "ariaLabel", "buttons", "orientation", "groupAriaLabel", "animationDisabled", "class"], outputs: ["clicked", "buttonClicked"] }, { kind: "directive", type: YuwSheetTriggerDirective, selector: "yuw-button[yuwSheetTriggerButton]" }, { kind: "directive", type: YuwSheetCloseDirective, selector: "yuw-button[yuwSheetClose]" }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
3274
3295
|
}
|
|
3275
3296
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSheetComponent, decorators: [{
|
|
3276
3297
|
type: Component,
|
|
3277
3298
|
args: [{ selector: 'yuw-sheet', imports: [...HlmSheetImports, YuwButtonComponent, YuwSheetTriggerDirective, YuwSheetCloseDirective, NgIcon], providers: [provideIcons({ lucideX })], host: {
|
|
3278
3299
|
class: 'contents',
|
|
3279
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<hlm-sheet
|
|
3280
|
-
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], showTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTrigger", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], triggerVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerVariant", required: false }] }], triggerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerSize", required: false }] }], hasFooter: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwSheetFooterDirective), { isSignal: true }] }] } });
|
|
3300
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<hlm-sheet\n [side]=\"side()\"\n [state]=\"_sheetState()\"\n [aria-label]=\"ariaLabel()\"\n [aria-modal]=\"ariaModal()\"\n [scrollStrategy]=\"scrollStrategy()\"\n [closeOnOutsidePointerEvents]=\"closeOnOutsidePointerEvents()\"\n (stateChanged)=\"onStateChanged($event)\"\n>\n @if (showTrigger()) {\n <yuw-button yuwSheetTriggerButton [variant]=\"triggerVariant()\" [size]=\"triggerSize()\">\n <ng-content select=\"[yuwSheetTrigger]\" />\n </yuw-button>\n }\n\n <hlm-sheet-content *hlmSheetPortal [showCloseButton]=\"false\" [class]=\"panelClass()\">\n @if (title() || description()) {\n <div hlmSheetHeader>\n @if (title()) {\n <h2 hlmSheetTitle>{{ title() }}</h2>\n }\n @if (description()) {\n <p hlmSheetDescription>{{ description() }}</p>\n }\n </div>\n }\n\n <div class=\"flex-1 overflow-y-auto px-4\">\n <ng-content />\n </div>\n\n @if (hasFooter()) {\n <div hlmSheetFooter>\n <ng-content select=\"[yuwSheetFooter]\" />\n </div>\n }\n\n @if (closeLabel()) {\n <div class=\"absolute inset-e-3 top-3\">\n <yuw-button yuwSheetClose variant=\"ghost\" size=\"icon-sm\">\n <ng-icon yuwButtonIcon name=\"lucideX\" />\n <span class=\"sr-only\">{{ closeLabel() }}</span>\n </yuw-button>\n </div>\n }\n </hlm-sheet-content>\n</hlm-sheet>\n" }]
|
|
3301
|
+
}], ctorParameters: () => [], propDecorators: { sheet: [{ type: i0.ViewChild, args: [i0.forwardRef(() => HlmSheet), { isSignal: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], showTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTrigger", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], overlayClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlayClass", required: false }] }], scrollStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollStrategy", required: false }] }], ariaModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaModal", required: false }] }], closeOnOutsidePointerEvents: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsidePointerEvents", required: false }] }], triggerVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerVariant", required: false }] }], triggerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerSize", required: false }] }], hasFooter: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwSheetFooterDirective), { isSignal: true }] }] } });
|
|
3281
3302
|
const YuwSheetImports = [YuwSheetComponent, YuwSheetFooterDirective];
|
|
3282
3303
|
|
|
3283
3304
|
/**
|
|
@@ -4095,13 +4116,33 @@ const yuwSidebarMenuChevronClass = [
|
|
|
4095
4116
|
'group-aria-expanded/menu-button:rotate-90',
|
|
4096
4117
|
'group-data-[yuw-rail=on]:hidden!',
|
|
4097
4118
|
].join(' ');
|
|
4098
|
-
const
|
|
4099
|
-
|
|
4100
|
-
'
|
|
4101
|
-
'
|
|
4119
|
+
const YUW_SIDEBAR_RAIL_WIDTH_VAR = '--yuw-sidebar-rail-width';
|
|
4120
|
+
const yuwSidebarSubmenuSheetClass = [
|
|
4121
|
+
'data-[side=left]:inset-y-0',
|
|
4122
|
+
'data-[side=left]:left-[var(--yuw-sidebar-rail-width)]',
|
|
4123
|
+
'data-[side=left]:h-full',
|
|
4124
|
+
'data-[side=left]:w-64',
|
|
4125
|
+
'data-[side=left]:sm:max-w-none',
|
|
4126
|
+
'data-[side=left]:border-r-0',
|
|
4127
|
+
'rounded-s-none',
|
|
4128
|
+
'rounded-e-xl',
|
|
4129
|
+
'bg-sidebar',
|
|
4130
|
+
'text-sidebar-foreground',
|
|
4131
|
+
'gap-0',
|
|
4132
|
+
'p-0',
|
|
4133
|
+
'duration-200',
|
|
4134
|
+
'data-[side=left]:data-open:slide-in-from-left-4',
|
|
4135
|
+
'data-[side=left]:data-closed:slide-out-to-left-4',
|
|
4136
|
+
'data-open:fade-in-0',
|
|
4137
|
+
'data-closed:fade-out-0',
|
|
4138
|
+
'motion-reduce:animate-none',
|
|
4139
|
+
].join(' ');
|
|
4140
|
+
const yuwSidebarSubmenuOverlayClass = 'left-[var(--yuw-sidebar-rail-width)]!';
|
|
4141
|
+
const yuwSidebarSubmenuSheetBodyClass = [
|
|
4102
4142
|
'flex',
|
|
4103
4143
|
'flex-col',
|
|
4104
4144
|
'gap-0.5',
|
|
4145
|
+
'py-2',
|
|
4105
4146
|
'[&_[data-sidebar=menu-sub]]:mx-0',
|
|
4106
4147
|
'[&_[data-sidebar=menu-sub]]:translate-x-0',
|
|
4107
4148
|
'[&_[data-sidebar=menu-sub]]:border-0',
|
|
@@ -4111,10 +4152,9 @@ const yuwSidebarFlyoutClass = [
|
|
|
4111
4152
|
'[&_[data-sidebar=menu-sub-button]]:translate-x-0',
|
|
4112
4153
|
'[&_[data-sidebar=menu-sub-button]]:h-8',
|
|
4113
4154
|
].join(' ');
|
|
4114
|
-
const
|
|
4155
|
+
const yuwSidebarSubmenuSheetLabelClass = [
|
|
4115
4156
|
'text-muted-foreground',
|
|
4116
|
-
'
|
|
4117
|
-
'pt-1',
|
|
4157
|
+
'pt-4',
|
|
4118
4158
|
'pb-1.5',
|
|
4119
4159
|
'text-xs',
|
|
4120
4160
|
'font-medium',
|
|
@@ -4175,6 +4215,14 @@ const yuwSidebarMenuSubButtonClass = ['[&>span]:truncate', '[&>span]:min-w-0'].j
|
|
|
4175
4215
|
* - Expanding, the rail look has to go immediately. The labels need the whole animation to fade and
|
|
4176
4216
|
* ellipsis into place, so waiting would replace one jump with another at the far end.
|
|
4177
4217
|
*
|
|
4218
|
+
* `railPending` is the mirror of it, for anything whose *presence* has to span the whole collapse
|
|
4219
|
+
* rather than arrive at the end of it: `true` the instant the panel starts narrowing, `false` only
|
|
4220
|
+
* once the expand has finished widening. The pair brackets the animation from both sides — every
|
|
4221
|
+
* frame in which the panel is at, or moving towards, rail width has `railPending` set, while only the
|
|
4222
|
+
* frames where it has actually arrived have `railSettled` set. Something that must not be visible
|
|
4223
|
+
* during the motion keys off this one; something that must not be restyled during the motion keys off
|
|
4224
|
+
* `railSettled`.
|
|
4225
|
+
*
|
|
4178
4226
|
* The delay runs through `timer` rather than a `setTimeout` inside an `effect`, and that is not a
|
|
4179
4227
|
* stylistic choice: this app is zoneless, so a signal written from a bare timer callback notifies
|
|
4180
4228
|
* nobody. Components reading `railSettled` in a template binding are `OnPush`, so they would keep
|
|
@@ -4183,13 +4231,15 @@ const yuwSidebarMenuSubButtonClass = ['[&>span]:truncate', '[&>span]:min-w-0'].j
|
|
|
4183
4231
|
*
|
|
4184
4232
|
* Provided at the root so `<yuw-sidebar>` and the nav share one instance — the component stamps the
|
|
4185
4233
|
* attribute the class layers select on, and the nav reads the same signal to decide between accordion
|
|
4186
|
-
* and
|
|
4234
|
+
* and submenu sheet, so the two must agree on the exact frame.
|
|
4187
4235
|
*/
|
|
4188
4236
|
class YuwSidebarRailService {
|
|
4189
4237
|
constructor() {
|
|
4190
4238
|
this.sidebar = inject(HlmSidebarService);
|
|
4191
4239
|
this.collapsed = computed(() => (this.sidebar.isMobile() ? !this.sidebar.openMobile() : !this.sidebar.open()), ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
4192
|
-
this.
|
|
4240
|
+
this.collapsed$ = toObservable(this.collapsed);
|
|
4241
|
+
this.railSettled = toSignal(this.collapsed$.pipe(switchMap((collapsed) => (collapsed ? timer(YUW_SIDEBAR_TRANSITION_MS).pipe(map(() => true)) : of(false)))), { initialValue: false });
|
|
4242
|
+
this.railPending = toSignal(this.collapsed$.pipe(switchMap((collapsed) => (collapsed ? of(true) : timer(YUW_SIDEBAR_TRANSITION_MS).pipe(map(() => false))))), { initialValue: false });
|
|
4193
4243
|
}
|
|
4194
4244
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarRailService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4195
4245
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarRailService, providedIn: 'root' }); }
|
|
@@ -4417,13 +4467,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4417
4467
|
* (`'default'`, `'sm'`, `'lg'`) and `isActive`.
|
|
4418
4468
|
*
|
|
4419
4469
|
* `tooltip` labels the item while the sidebar is collapsed to icons, where the label itself is
|
|
4420
|
-
* hidden; the composed primitive shows it only in that state
|
|
4421
|
-
*
|
|
4470
|
+
* hidden; the composed primitive shows it only in that state. Every entry gets one, including those
|
|
4471
|
+
* with children — their submenu opens on click, so it never competes with the hover.
|
|
4422
4472
|
*
|
|
4423
4473
|
* Reaching that input takes composing `BrnTooltip` here under the same `tooltip` alias the helm uses,
|
|
4424
4474
|
* rather than forwarding it. `HlmSidebarMenuButton` publishes the alias on its own `hostDirectives`
|
|
4425
4475
|
* entry, which does not make it an input of the helm directive — a forward cannot be re-forwarded, the
|
|
4426
|
-
* same limit `
|
|
4476
|
+
* same limit `context-menu.directives.ts` documents. Angular resolves both entries to the one
|
|
4427
4477
|
* `BrnTooltip` instance on the element, so the helm keeps driving `mutableTooltipDisabled` (which is
|
|
4428
4478
|
* what confines the tooltip to the collapsed state) while this binding supplies its content.
|
|
4429
4479
|
*
|
|
@@ -4450,7 +4500,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4450
4500
|
* shrink-to-fit for the whole width animation — long enough for the label to stop ellipsing and
|
|
4451
4501
|
* the trailing chevron to sit against it.
|
|
4452
4502
|
* - `[&>span]:hidden` drops the label while collapsed, leaving the icon alone — the tooltip carries
|
|
4453
|
-
* the name in that state
|
|
4503
|
+
* the name in that state. Matched by element rather
|
|
4454
4504
|
* than by `:last-child` (which is what the helm's own `truncate` uses): an expandable entry ends
|
|
4455
4505
|
* with a trailing chevron, so the label is no longer the last child and a positional selector
|
|
4456
4506
|
* would skip exactly those entries. `span` is unambiguous here — the label is the only one a menu
|
|
@@ -4545,179 +4595,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4545
4595
|
hostDirectives: [{ directive: HlmSidebarMenuSubButton, inputs: ['size', 'isActive', 'closeMobileSidebarOnClick'] }],
|
|
4546
4596
|
}]
|
|
4547
4597
|
}], ctorParameters: () => [] });
|
|
4548
|
-
/**
|
|
4549
|
-
* Host of a collapsed-state flyout: the element that scopes the overlay for one entry. Apply
|
|
4550
|
-
* alongside `[yuwSidebarMenuItem]` on the `<li>` holding the entry and its panel.
|
|
4551
|
-
*
|
|
4552
|
-
* Provides `BrnHoverCardContentService` itself instead of composing `HlmHoverCard`. The service has
|
|
4553
|
-
* to be scoped per `<li>` — it holds the single overlay and its content, so a shared one would have
|
|
4554
|
-
* every entry in the sidebar fighting over the same panel — and providing it here is all that is
|
|
4555
|
-
* needed for that. What `HlmHoverCard` adds on top is a `contentChild` pairing that assigns the
|
|
4556
|
-
* trigger's content in `ngAfterContentInit`, and that pairing is actively harmful here: it writes
|
|
4557
|
-
* into the same writable signal the trigger's own input feeds, so its one-time value outlives and
|
|
4558
|
-
* overrides the binding that is supposed to turn the flyout off while the sidebar is expanded.
|
|
4559
|
-
*/
|
|
4560
|
-
class YuwSidebarFlyoutHostDirective {
|
|
4561
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutHostDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4562
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: YuwSidebarFlyoutHostDirective, isStandalone: true, selector: "[yuwSidebarFlyoutHost]", providers: [BrnHoverCardContentService], ngImport: i0 }); }
|
|
4563
|
-
}
|
|
4564
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutHostDirective, decorators: [{
|
|
4565
|
-
type: Directive,
|
|
4566
|
-
args: [{
|
|
4567
|
-
selector: '[yuwSidebarFlyoutHost]',
|
|
4568
|
-
providers: [BrnHoverCardContentService],
|
|
4569
|
-
}]
|
|
4570
|
-
}] });
|
|
4571
|
-
/**
|
|
4572
|
-
* The entry whose hover opens a flyout. Apply to the same element as `[yuwSidebarMenuButton]`, bound
|
|
4573
|
-
* to the panel's `<ng-template>` reference — or to `undefined` to switch the flyout off entirely,
|
|
4574
|
-
* which is how an expanded sidebar keeps its submenus inline.
|
|
4575
|
-
*
|
|
4576
|
-
* Drives `BrnHoverCardContentService` directly instead of composing `BrnHoverCardTrigger`. The brain
|
|
4577
|
-
* trigger has no way to be turned off once it has run: it feeds the panel to the service through an
|
|
4578
|
-
* effect that ignores falsy values, and the service's `show()` consults only its stored content, so
|
|
4579
|
-
* a trigger that was ever enabled keeps opening its overlay forever. Rebinding to `undefined` cannot
|
|
4580
|
-
* undo it, and neither can `hide()`, which detaches the overlay but leaves the content in place.
|
|
4581
|
-
* Owning the wiring here is what makes an unbound panel mean "inert".
|
|
4582
|
-
*
|
|
4583
|
-
* The `effect` is the whole lifecycle: it runs when a panel arrives, and its `onCleanup` closes the
|
|
4584
|
-
* overlay and drops the subscription when the panel goes away or the entry is destroyed. Nothing
|
|
4585
|
-
* else tracks teardown, which is why there is no `DestroyRef` or `takeUntilDestroyed` here — a second
|
|
4586
|
-
* mechanism would only be able to disagree with this one.
|
|
4587
|
-
*
|
|
4588
|
-
* Delays are read inside `switchMap` rather than captured when the effect runs, so retuning them
|
|
4589
|
-
* does not tear down and rebuild the subscription.
|
|
4590
|
-
*
|
|
4591
|
-
* `distinctUntilChanged` before the timer is load-bearing, and not as an optimisation: the five
|
|
4592
|
-
* merged sources overlap, so crossing from the entry to the panel emits a `mouseleave` and the
|
|
4593
|
-
* panel's own hover almost together, and `mouseenter` and `focusin` both fire on the same pointer
|
|
4594
|
-
* arriving. Each duplicate would restart `switchMap` and cancel the timer already in flight, so a
|
|
4595
|
-
* repeat during the show delay could keep the panel from ever opening.
|
|
4596
|
-
*
|
|
4597
|
-
* It cannot dedupe the crossing itself, though — that genuinely alternates `false` then `true`, so
|
|
4598
|
-
* both values are distinct and both survive. `toggle` is therefore guarded against the state it is
|
|
4599
|
-
* already in, because `show()` is not idempotent: it calls `detach()` then `attach()`, tearing the
|
|
4600
|
-
* panel down and rebuilding it. Re-showing an open panel replays its enter animation, which is the
|
|
4601
|
-
* flicker you get when the pointer moves from the rail into the flyout.
|
|
4602
|
-
*
|
|
4603
|
-
* Note there is no click handling. `BrnHoverCardTrigger` maps a click to `false`, which is right for
|
|
4604
|
-
* a hover card — clicking the trigger dismisses it — and wrong for a nav rail, where the entry's own
|
|
4605
|
-
* click has nothing to collapse while collapsed and closing the panel would take away the links the
|
|
4606
|
-
* pointer is travelling to. Activating a child closes the flyout anyway, since the pointer leaves
|
|
4607
|
-
* the panel as the page changes.
|
|
4608
|
-
*
|
|
4609
|
-
* `align` is `'right'` for a sidebar flyout rather than the hover card's own `'bottom'`. It is set as
|
|
4610
|
-
* an input rather than through `provideBrnHoverCardDefaultOptions` because that provider types its
|
|
4611
|
-
* `align` as `'top' | 'bottom'`, even though the position map handles all four sides.
|
|
4612
|
-
*/
|
|
4613
|
-
class YuwSidebarFlyoutTriggerDirective {
|
|
4614
|
-
constructor() {
|
|
4615
|
-
this.element = inject(ElementRef);
|
|
4616
|
-
this.viewContainerRef = inject(ViewContainerRef);
|
|
4617
|
-
this.service = inject(BrnHoverCardContentService);
|
|
4618
|
-
this.panel = input(undefined, { ...(ngDevMode ? { debugName: "panel" } : /* istanbul ignore next */ {}), alias: 'yuwSidebarFlyoutTrigger' });
|
|
4619
|
-
this.align = input('right', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
|
|
4620
|
-
this.sideOffset = input(0, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
4621
|
-
this.showDelay = input(120, { ...(ngDevMode ? { debugName: "showDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
4622
|
-
this.hideDelay = input(300, { ...(ngDevMode ? { debugName: "hideDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
4623
|
-
this.pointerOver = merge(fromEvent(this.element.nativeElement, 'mouseenter').pipe(map(() => true)), fromEvent(this.element.nativeElement, 'mouseleave').pipe(map(() => false)), fromEvent(this.element.nativeElement, 'focusin').pipe(map(() => true)), fromEvent(this.element.nativeElement, 'focusout').pipe(map(() => false)), this.service.hovered$);
|
|
4624
|
-
effect((onCleanup) => {
|
|
4625
|
-
const panel = this.panel();
|
|
4626
|
-
if (!panel)
|
|
4627
|
-
return;
|
|
4628
|
-
this.service.setConfig({
|
|
4629
|
-
attachTo: this.element,
|
|
4630
|
-
align: this.align(),
|
|
4631
|
-
sideOffset: this.sideOffset(),
|
|
4632
|
-
});
|
|
4633
|
-
this.service.setContent(panel, this.viewContainerRef);
|
|
4634
|
-
const subscription = this.pointerOver
|
|
4635
|
-
.pipe(distinctUntilChanged(), switchMap$1((visible) => timer(visible ? this.showDelay() : this.hideDelay()).pipe(map(() => visible))))
|
|
4636
|
-
.subscribe((visible) => this.toggle(visible));
|
|
4637
|
-
onCleanup(() => {
|
|
4638
|
-
subscription.unsubscribe();
|
|
4639
|
-
this.toggle(false);
|
|
4640
|
-
});
|
|
4641
|
-
});
|
|
4642
|
-
}
|
|
4643
|
-
toggle(open) {
|
|
4644
|
-
if (open === (this.service.state() === 'open'))
|
|
4645
|
-
return;
|
|
4646
|
-
this.service.setState(open ? 'open' : 'closed');
|
|
4647
|
-
if (open) {
|
|
4648
|
-
this.service.show();
|
|
4649
|
-
return;
|
|
4650
|
-
}
|
|
4651
|
-
this.service.hide();
|
|
4652
|
-
}
|
|
4653
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4654
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.8", type: YuwSidebarFlyoutTriggerDirective, isStandalone: true, selector: "[yuwSidebarFlyoutTrigger]", inputs: { panel: { classPropertyName: "panel", publicName: "yuwSidebarFlyoutTrigger", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "showDelay", isSignal: true, isRequired: false, transformFunction: null }, hideDelay: { classPropertyName: "hideDelay", publicName: "hideDelay", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
|
|
4655
|
-
}
|
|
4656
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutTriggerDirective, decorators: [{
|
|
4657
|
-
type: Directive,
|
|
4658
|
-
args: [{
|
|
4659
|
-
selector: '[yuwSidebarFlyoutTrigger]',
|
|
4660
|
-
}]
|
|
4661
|
-
}], ctorParameters: () => [], propDecorators: { panel: [{ type: i0.Input, args: [{ isSignal: true, alias: "yuwSidebarFlyoutTrigger", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }], showDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDelay", required: false }] }], hideDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideDelay", required: false }] }] } });
|
|
4662
|
-
/**
|
|
4663
|
-
* Marks the `<ng-template>` holding a flyout's markup, and is what `[yuwSidebarFlyoutTrigger]` is
|
|
4664
|
-
* bound to. Exported as `yuwSidebarFlyoutPanel` so the template can name it.
|
|
4665
|
-
*
|
|
4666
|
-
* Structural — the composed primitive injects the `TemplateRef`, which is what lets the panel be
|
|
4667
|
-
* portalled into a CDK overlay instead of rendering inside the rail.
|
|
4668
|
-
*
|
|
4669
|
-
* The trigger is bound to the template's own `#ref` (a `TemplateRef`, which its input accepts), so
|
|
4670
|
-
* this directive is never referenced by name — but it cannot be dropped: it is the sole provider of
|
|
4671
|
-
* the exposed state and side tokens that `[yuwSidebarFlyout]` injects from its host, and without it
|
|
4672
|
-
* the panel throws NG0201 the moment the overlay instantiates it.
|
|
4673
|
-
*/
|
|
4674
|
-
class YuwSidebarFlyoutPanelDirective {
|
|
4675
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutPanelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4676
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: YuwSidebarFlyoutPanelDirective, isStandalone: true, selector: "ng-template[yuwSidebarFlyoutPanel]", hostDirectives: [{ directive: i2$1.HlmHoverCardPortal }], ngImport: i0 }); }
|
|
4677
|
-
}
|
|
4678
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutPanelDirective, decorators: [{
|
|
4679
|
-
type: Directive,
|
|
4680
|
-
args: [{
|
|
4681
|
-
selector: 'ng-template[yuwSidebarFlyoutPanel]',
|
|
4682
|
-
hostDirectives: [HlmHoverCardPortal],
|
|
4683
|
-
}]
|
|
4684
|
-
}] });
|
|
4685
|
-
/**
|
|
4686
|
-
* The flyout's visible surface. Apply to the single root element inside a `[yuwSidebarFlyoutPanel]`
|
|
4687
|
-
* template.
|
|
4688
|
-
*
|
|
4689
|
-
* Separate from the panel marker because the two sit on different nodes: the marker is the
|
|
4690
|
-
* `<ng-template>`, this is the element the overlay renders. Carries the popover surface of the
|
|
4691
|
-
* composed helm content plus `yuwSidebarFlyoutClass`.
|
|
4692
|
-
*
|
|
4693
|
-
* That class layer exists because the panel lives in the overlay, outside the sidebar's DOM subtree,
|
|
4694
|
-
* and so is no longer a descendant of the `group/sidebar-wrapper` element. Every
|
|
4695
|
-
* `group-data-[collapsible=…]` selector therefore resolves against nothing and stays inert —
|
|
4696
|
-
* including the `hidden` that `HlmSidebarMenuSub` and `HlmSidebarMenuSubButton` apply to themselves
|
|
4697
|
-
* in exactly this state, which is why the submenu markup renders visible in here with no override.
|
|
4698
|
-
* What the layer undoes instead is the indentation and vertical rule those primitives carry for the
|
|
4699
|
-
* inline case, which make no sense in a panel.
|
|
4700
|
-
*
|
|
4701
|
-
* The gap between rail and panel is that layer's `ms-2`, not the trigger's `sideOffset`, which is
|
|
4702
|
-
* deliberately `0`. An offset moves the overlay away from the trigger and leaves dead space between
|
|
4703
|
-
* them: crossing it slowly means the pointer is over neither element, and the hover card closes
|
|
4704
|
-
* mid-journey. A margin keeps the same visual gap inside the overlay's own box, so the pointer never
|
|
4705
|
-
* leaves the hover target on its way in.
|
|
4706
|
-
*/
|
|
4707
|
-
class YuwSidebarFlyoutDirective {
|
|
4708
|
-
constructor() {
|
|
4709
|
-
classes(() => yuwSidebarFlyoutClass);
|
|
4710
|
-
}
|
|
4711
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4712
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: YuwSidebarFlyoutDirective, isStandalone: true, selector: "[yuwSidebarFlyout]", hostDirectives: [{ directive: i2$1.HlmHoverCardContent }], ngImport: i0 }); }
|
|
4713
|
-
}
|
|
4714
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutDirective, decorators: [{
|
|
4715
|
-
type: Directive,
|
|
4716
|
-
args: [{
|
|
4717
|
-
selector: '[yuwSidebarFlyout]',
|
|
4718
|
-
hostDirectives: [HlmHoverCardContent],
|
|
4719
|
-
}]
|
|
4720
|
-
}], ctorParameters: () => [] });
|
|
4721
4598
|
/** Divider between sidebar sections. */
|
|
4722
4599
|
class YuwSidebarSeparatorDirective {
|
|
4723
4600
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSeparatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
@@ -4765,11 +4642,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4765
4642
|
}]
|
|
4766
4643
|
}] });
|
|
4767
4644
|
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4645
|
+
/**
|
|
4646
|
+
* Holds which rail entry's submenu the collapsed sidebar is showing. Provided on `<yuw-sidebar>`, so
|
|
4647
|
+
* two sidebars on a page don't drive each other.
|
|
4648
|
+
*
|
|
4649
|
+
* `renderedItem` lags `activeItem` by one close: the sheet renders from it so its markup outlives the
|
|
4650
|
+
* close and the panel can animate out. Swapping entries never writes `null`, which would detach the
|
|
4651
|
+
* overlay and replay the open animation. Matching is by `id` — the nav rebuilds these objects.
|
|
4652
|
+
*/
|
|
4653
|
+
class YuwSidebarSubmenuService {
|
|
4654
|
+
constructor() {
|
|
4655
|
+
this.item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
|
|
4656
|
+
this.lastItem = signal(null, ...(ngDevMode ? [{ debugName: "lastItem" }] : /* istanbul ignore next */ []));
|
|
4657
|
+
this.activeItem = this.item.asReadonly();
|
|
4658
|
+
this.renderedItem = this.lastItem.asReadonly();
|
|
4659
|
+
this.open = computed(() => this.item() !== null, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
4660
|
+
}
|
|
4661
|
+
toggle(item) {
|
|
4662
|
+
const next = this.item()?.id === item.id ? null : item;
|
|
4663
|
+
this.item.set(next);
|
|
4664
|
+
if (next)
|
|
4665
|
+
this.lastItem.set(next);
|
|
4666
|
+
}
|
|
4667
|
+
close() {
|
|
4668
|
+
this.item.set(null);
|
|
4669
|
+
}
|
|
4670
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4671
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuService }); }
|
|
4672
|
+
}
|
|
4673
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuService, decorators: [{
|
|
4674
|
+
type: Injectable
|
|
4675
|
+
}] });
|
|
4676
|
+
|
|
4773
4677
|
/**
|
|
4774
4678
|
* Renders one {@link YuwSidebarContentDto} as the group/menu/item tree.
|
|
4775
4679
|
*
|
|
@@ -4783,19 +4687,27 @@ const CARET_RIGHT_BORDER_CLASSES = `
|
|
|
4783
4687
|
* `group-data-[collapsible=icon]:` selectors — which resolve against the sidebar root — working
|
|
4784
4688
|
* identically for object-rendered and hand-written markup.
|
|
4785
4689
|
*
|
|
4786
|
-
* An entry with `children`
|
|
4787
|
-
* accordion: the entry carries `aria-expanded` and the submenu is nested beneath it.
|
|
4788
|
-
* icons, where there is no room for either the label or the nesting,
|
|
4789
|
-
*
|
|
4790
|
-
*
|
|
4791
|
-
*
|
|
4792
|
-
*
|
|
4793
|
-
*
|
|
4794
|
-
*
|
|
4795
|
-
*
|
|
4796
|
-
*
|
|
4797
|
-
*
|
|
4798
|
-
*
|
|
4690
|
+
* An entry with `children` shows its submenu two ways, one per sidebar state. Expanded, it is an
|
|
4691
|
+
* accordion rendered here: the entry carries `aria-expanded` and the submenu is nested beneath it.
|
|
4692
|
+
* Collapsed to icons, where there is no room for either the label or the nesting, it moves into the
|
|
4693
|
+
* sheet beside the rail — which this component does not own. `<yuw-sidebar>` renders one sheet and
|
|
4694
|
+
* this component only reports, through `YuwSidebarSubmenuService`, which entry the user picked. It
|
|
4695
|
+
* cannot own the panel itself: `<yuw-sidebar>` instantiates this component twice, once for `content`
|
|
4696
|
+
* and once for `footer`, so a sheet in here would be two sheets fighting over one screen position.
|
|
4697
|
+
*
|
|
4698
|
+
* Such an entry also opts out of the helm's close-the-mobile-sheet-on-click behaviour, which every
|
|
4699
|
+
* other entry keeps. On mobile the sidebar *is* a sheet, and that behaviour assumes a click means
|
|
4700
|
+
* "I have navigated, take this away" — true of a leaf, false of an accordion header, whose click only
|
|
4701
|
+
* unfolds a submenu inside the very panel it would be dismissing. Its children still close it, since
|
|
4702
|
+
* activating one of those really is the navigation the panel was opened for.
|
|
4703
|
+
*
|
|
4704
|
+
* A click on such an entry toggles the accordion while the panel is open, and opens the sheet on that
|
|
4705
|
+
* entry once collapsed — the same gesture either way, differing only in where the submenu appears.
|
|
4706
|
+
* Clicking the entry the sheet is already showing closes it; clicking a different one swaps the
|
|
4707
|
+
* sheet's contents. When the entry also has a `route` or an `href` it navigates *and* toggles, which
|
|
4708
|
+
* is why an active one keeps its pointer events instead of being locked like a childless active
|
|
4709
|
+
* entry; when it has neither, toggling is all it does and it stays out of `itemClicked`, since
|
|
4710
|
+
* opening a submenu is not an action for the consumer to handle.
|
|
4799
4711
|
*
|
|
4800
4712
|
* The chevron marking an expandable entry rotates off that same `aria-expanded`, read from the
|
|
4801
4713
|
* button through the `group/menu-button` the helm already declares on every menu button. Its
|
|
@@ -4808,11 +4720,11 @@ const CARET_RIGHT_BORDER_CLASSES = `
|
|
|
4808
4720
|
* Which of the two forms is live comes from `isRail`, and all three of its conditions are
|
|
4809
4721
|
* load-bearing. `collapsible` must be `'icon'`, the only mode that leaves a narrow rail behind:
|
|
4810
4722
|
* `'offcanvas'` moves the whole panel off-screen and `'none'` never collapses, yet the service
|
|
4811
|
-
* reports `state() === 'collapsed'` for both — reading the state alone
|
|
4812
|
-
* sitting there at full width. It must not be mobile, where the panel is a full-width sheet
|
|
4813
|
-
* the accordion. And the collapse must have finished animating, which is what `railSettled`
|
|
4814
|
-
* for:
|
|
4815
|
-
*
|
|
4723
|
+
* reports `state() === 'collapsed'` for both — reading the state alone opens the sheet beside a
|
|
4724
|
+
* sidebar sitting there at full width. It must not be mobile, where the panel is a full-width sheet
|
|
4725
|
+
* showing the accordion. And the collapse must have finished animating, which is what `railSettled`
|
|
4726
|
+
* waits for: switching to the sheet while the panel is still wide would leave it overlapping the very
|
|
4727
|
+
* sidebar it is supposed to sit beside. That same settled signal drives the rail's own styling, so
|
|
4816
4728
|
* the geometry and the submenu form always change on the same frame.
|
|
4817
4729
|
*
|
|
4818
4730
|
* The accordion opens and closes over a grid-rows transition rather than by appearing outright, which
|
|
@@ -4847,8 +4759,8 @@ const CARET_RIGHT_BORDER_CLASSES = `
|
|
|
4847
4759
|
* `routerLinkActiveOptions` a stable object identity: a literal in the template
|
|
4848
4760
|
* (`[routerLinkActiveOptions]="{exact: item.exact ?? false}"`) allocates a new object on every
|
|
4849
4761
|
* change-detection pass, and `RouterLinkActive` treats that as a changed input and re-runs its
|
|
4850
|
-
* subscription.
|
|
4851
|
-
*
|
|
4762
|
+
* subscription. Every entry resolves a tooltip, entries with children included: the submenu opens on
|
|
4763
|
+
* click, so hover is free to do what it does for every other rail icon and name the thing.
|
|
4852
4764
|
*/
|
|
4853
4765
|
class YuwSidebarNavComponent {
|
|
4854
4766
|
constructor() {
|
|
@@ -4856,15 +4768,14 @@ class YuwSidebarNavComponent {
|
|
|
4856
4768
|
this.injector = inject(Injector);
|
|
4857
4769
|
this.sidebarService = inject(HlmSidebarService);
|
|
4858
4770
|
this.rail = inject(YuwSidebarRailService);
|
|
4771
|
+
this.submenu = inject(YuwSidebarSubmenuService);
|
|
4859
4772
|
this.content = input.required(...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
|
|
4860
4773
|
this.collapsible = input('offcanvas', ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
|
|
4861
4774
|
this.itemClicked = output();
|
|
4862
4775
|
this.activeRoutes = new Map();
|
|
4863
4776
|
this.chevronClass = yuwSidebarMenuChevronClass;
|
|
4864
|
-
this.flyoutLabelClass = yuwSidebarFlyoutLabelClass;
|
|
4865
4777
|
this.badgeClass = yuwSidebarMenuBadgeClass;
|
|
4866
4778
|
this.groupLabelTextClass = yuwSidebarGroupLabelTextClass;
|
|
4867
|
-
this.caretRightBorderClasses = CARET_RIGHT_BORDER_CLASSES;
|
|
4868
4779
|
this.isRail = computed(() => this.collapsible() === 'icon' && !this.sidebarService.isMobile() && this.rail.railSettled(), ...(ngDevMode ? [{ debugName: "isRail" }] : /* istanbul ignore next */ []));
|
|
4869
4780
|
this.expandedIds = linkedSignal({ ...(ngDevMode ? { debugName: "expandedIds" } : /* istanbul ignore next */ {}), source: () => ({ content: this.content(), rail: this.isRail() }),
|
|
4870
4781
|
computation: ({ content, rail }, previous) => rail || previous
|
|
@@ -4886,7 +4797,7 @@ class YuwSidebarNavComponent {
|
|
|
4886
4797
|
...item,
|
|
4887
4798
|
children,
|
|
4888
4799
|
hasChildren,
|
|
4889
|
-
tooltipText:
|
|
4800
|
+
tooltipText: item.tooltip ?? item.label,
|
|
4890
4801
|
activeOptions: { exact: item.exact ?? false },
|
|
4891
4802
|
expanded,
|
|
4892
4803
|
submenuClass: `${yuwSidebarSubmenuWrapperClass} ${expanded ? yuwSidebarSubmenuOpenClass : yuwSidebarSubmenuClosedClass}`,
|
|
@@ -4913,20 +4824,22 @@ class YuwSidebarNavComponent {
|
|
|
4913
4824
|
onItemClick(id, event) {
|
|
4914
4825
|
this.itemClicked.emit({ id, event });
|
|
4915
4826
|
}
|
|
4916
|
-
onParentClick(
|
|
4917
|
-
if (this.isRail())
|
|
4827
|
+
onParentClick(item, expanded) {
|
|
4828
|
+
if (this.isRail()) {
|
|
4829
|
+
this.submenu.toggle(item);
|
|
4918
4830
|
return;
|
|
4831
|
+
}
|
|
4919
4832
|
this.expandedIds.update((ids) => {
|
|
4920
4833
|
const next = new Set(ids);
|
|
4921
4834
|
if (expanded)
|
|
4922
|
-
next.delete(id);
|
|
4835
|
+
next.delete(item.id);
|
|
4923
4836
|
else
|
|
4924
|
-
next.add(id);
|
|
4837
|
+
next.add(item.id);
|
|
4925
4838
|
return next;
|
|
4926
4839
|
});
|
|
4927
4840
|
}
|
|
4928
4841
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4929
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: YuwSidebarNavComponent, isStandalone: true, selector: "yuw-sidebar-nav", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideChevronRight })], ngImport: i0, template: "<ng-template #submenu let-item>\n <ul yuwSidebarMenuSub>\n @for (child of item.children; track child.id) {\n <li yuwSidebarMenuSubItem>\n @if (child.route) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [routerLink]=\"child.route\"\n routerLinkActive\n #childLink=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"child.activeOptions\"\n [isActive]=\"childLink.isActive\"\n [attr.aria-current]=\"childLink.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"childLink.isActive || child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else if (child.href) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [href]=\"child.href\"\n [attr.target]=\"child.target\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else {\n <button\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n type=\"button\"\n [disabled]=\"child.disabled ?? false\"\n (click)=\"onItemClick(child.id, $event)\"\n >\n <span>{{ child.label }}</span>\n </button>\n }\n </li>\n }\n </ul>\n</ng-template>\n\n@for (group of _groups(); track group.id) {\n <div yuwSidebarGroup>\n @if (group.label) {\n <div yuwSidebarGroupLabel>\n <span [class]=\"groupLabelTextClass\">{{ group.label }}</span>\n </div>\n }\n\n <div yuwSidebarGroupContent>\n <ul yuwSidebarMenu class=\"gap-1\">\n @for (item of group.items; track item.id) {\n <li yuwSidebarMenuItem
|
|
4842
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: YuwSidebarNavComponent, isStandalone: true, selector: "yuw-sidebar-nav", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideChevronRight })], ngImport: i0, template: "<ng-template #submenu let-item>\n <ul yuwSidebarMenuSub>\n @for (child of item.children; track child.id) {\n <li yuwSidebarMenuSubItem>\n @if (child.route) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [routerLink]=\"child.route\"\n routerLinkActive\n #childLink=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"child.activeOptions\"\n [isActive]=\"childLink.isActive\"\n [attr.aria-current]=\"childLink.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"childLink.isActive || child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else if (child.href) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [href]=\"child.href\"\n [attr.target]=\"child.target\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else {\n <button\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n type=\"button\"\n [disabled]=\"child.disabled ?? false\"\n (click)=\"onItemClick(child.id, $event)\"\n >\n <span>{{ child.label }}</span>\n </button>\n }\n </li>\n }\n </ul>\n</ng-template>\n\n@for (group of _groups(); track group.id) {\n <div yuwSidebarGroup>\n @if (group.label) {\n <div yuwSidebarGroupLabel>\n <span [class]=\"groupLabelTextClass\">{{ group.label }}</span>\n </div>\n }\n\n <div yuwSidebarGroupContent>\n <ul yuwSidebarMenu class=\"gap-1\">\n @for (item of group.items; track item.id) {\n <li yuwSidebarMenuItem>\n @if (item.route) {\n <a\n yuwSidebarMenuButton\n [closeMobileSidebarOnClick]=\"!item.hasChildren\"\n [routerLink]=\"item.route\"\n routerLinkActive\n #link=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"item.activeOptions\"\n [isActive]=\"link.isActive\"\n [tooltip]=\"item.tooltipText\"\n [attr.aria-current]=\"link.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [class.pointer-events-none]=\"(link.isActive && !item.hasChildren) || item.disabled\"\n (click)=\"onParentClick(item, item.expanded)\"\n >\n @if (item.icon) {\n <ng-icon [name]=\"item.icon\" />\n }\n <span>{{ item.label }}</span>\n @if (item.hasChildren) {\n <ng-icon name=\"lucideChevronRight\" [class]=\"chevronClass\" />\n }\n </a>\n } @else if (item.href) {\n <a\n yuwSidebarMenuButton\n [closeMobileSidebarOnClick]=\"!item.hasChildren\"\n [href]=\"item.href\"\n [attr.target]=\"item.target\"\n [tooltip]=\"item.tooltipText\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [class.pointer-events-none]=\"item.disabled\"\n (click)=\"onParentClick(item, item.expanded)\"\n >\n @if (item.icon) {\n <ng-icon [name]=\"item.icon\" />\n }\n <span>{{ item.label }}</span>\n @if (item.hasChildren) {\n <ng-icon name=\"lucideChevronRight\" [class]=\"chevronClass\" />\n }\n </a>\n } @else {\n <button\n yuwSidebarMenuButton\n [closeMobileSidebarOnClick]=\"!item.hasChildren\"\n type=\"button\"\n [tooltip]=\"item.tooltipText\"\n [disabled]=\"item.disabled ?? false\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n (click)=\"item.hasChildren ? onParentClick(item, item.expanded) : onItemClick(item.id, $event)\"\n >\n @if (item.icon) {\n <ng-icon [name]=\"item.icon\" />\n }\n <span>{{ item.label }}</span>\n @if (item.hasChildren) {\n <ng-icon name=\"lucideChevronRight\" [class]=\"chevronClass\" />\n }\n </button>\n }\n\n @if (item.badge) {\n <span yuwSidebarMenuBadge [class]=\"badgeClass\">{{ item.badge }}</span>\n }\n\n @if (item.hasChildren && !isRail()) {\n <div\n [class]=\"item.submenuClass\"\n [attr.inert]=\"item.expanded ? null : ''\"\n [attr.aria-hidden]=\"!item.expanded\"\n >\n <div>\n <ng-container [ngTemplateOutlet]=\"submenu\" [ngTemplateOutletContext]=\"{ $implicit: item }\" />\n </div>\n </div>\n }\n </li>\n }\n </ul>\n </div>\n </div>\n\n @if (group.separatorAfter) {\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n }\n}\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: YuwSidebarGroupDirective, selector: "[yuwSidebarGroup], yuw-sidebar-group" }, { kind: "directive", type: YuwSidebarGroupLabelDirective, selector: "div[yuwSidebarGroupLabel], button[yuwSidebarGroupLabel]" }, { kind: "directive", type: YuwSidebarGroupContentDirective, selector: "div[yuwSidebarGroupContent]" }, { kind: "directive", type: YuwSidebarMenuDirective, selector: "ul[yuwSidebarMenu]" }, { kind: "directive", type: YuwSidebarMenuItemDirective, selector: "li[yuwSidebarMenuItem]" }, { kind: "directive", type: YuwSidebarMenuButtonDirective, selector: "button[yuwSidebarMenuButton], a[yuwSidebarMenuButton]" }, { kind: "directive", type: YuwSidebarMenuBadgeDirective, selector: "[yuwSidebarMenuBadge], yuw-sidebar-menu-badge" }, { kind: "directive", type: YuwSidebarMenuSubDirective, selector: "ul[yuwSidebarMenuSub]" }, { kind: "directive", type: YuwSidebarMenuSubItemDirective, selector: "li[yuwSidebarMenuSubItem]" }, { kind: "directive", type: YuwSidebarMenuSubButtonDirective, selector: "a[yuwSidebarMenuSubButton], button[yuwSidebarMenuSubButton]" }, { kind: "directive", type: YuwSidebarSeparatorDirective, selector: "[yuwSidebarSeparator], yuw-sidebar-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4930
4843
|
}
|
|
4931
4844
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarNavComponent, decorators: [{
|
|
4932
4845
|
type: Component,
|
|
@@ -4947,15 +4860,78 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4947
4860
|
YuwSidebarMenuSubItemDirective,
|
|
4948
4861
|
YuwSidebarMenuSubButtonDirective,
|
|
4949
4862
|
YuwSidebarSeparatorDirective,
|
|
4950
|
-
YuwSidebarFlyoutHostDirective,
|
|
4951
|
-
YuwSidebarFlyoutPanelDirective,
|
|
4952
|
-
YuwSidebarFlyoutTriggerDirective,
|
|
4953
|
-
YuwSidebarFlyoutDirective,
|
|
4954
4863
|
], providers: [provideIcons({ lucideChevronRight })], host: {
|
|
4955
4864
|
class: 'contents',
|
|
4956
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #submenu let-item>\n <ul yuwSidebarMenuSub>\n @for (child of item.children; track child.id) {\n <li yuwSidebarMenuSubItem>\n @if (child.route) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [routerLink]=\"child.route\"\n routerLinkActive\n #childLink=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"child.activeOptions\"\n [isActive]=\"childLink.isActive\"\n [attr.aria-current]=\"childLink.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"childLink.isActive || child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else if (child.href) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [href]=\"child.href\"\n [attr.target]=\"child.target\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else {\n <button\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n type=\"button\"\n [disabled]=\"child.disabled ?? false\"\n (click)=\"onItemClick(child.id, $event)\"\n >\n <span>{{ child.label }}</span>\n </button>\n }\n </li>\n }\n </ul>\n</ng-template>\n\n@for (group of _groups(); track group.id) {\n <div yuwSidebarGroup>\n @if (group.label) {\n <div yuwSidebarGroupLabel>\n <span [class]=\"groupLabelTextClass\">{{ group.label }}</span>\n </div>\n }\n\n <div yuwSidebarGroupContent>\n <ul yuwSidebarMenu class=\"gap-1\">\n @for (item of group.items; track item.id) {\n <li yuwSidebarMenuItem
|
|
4865
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #submenu let-item>\n <ul yuwSidebarMenuSub>\n @for (child of item.children; track child.id) {\n <li yuwSidebarMenuSubItem>\n @if (child.route) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [routerLink]=\"child.route\"\n routerLinkActive\n #childLink=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"child.activeOptions\"\n [isActive]=\"childLink.isActive\"\n [attr.aria-current]=\"childLink.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"childLink.isActive || child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else if (child.href) {\n <a\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n [href]=\"child.href\"\n [attr.target]=\"child.target\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"child.disabled\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else {\n <button\n yuwSidebarMenuSubButton\n closeMobileSidebarOnClick\n type=\"button\"\n [disabled]=\"child.disabled ?? false\"\n (click)=\"onItemClick(child.id, $event)\"\n >\n <span>{{ child.label }}</span>\n </button>\n }\n </li>\n }\n </ul>\n</ng-template>\n\n@for (group of _groups(); track group.id) {\n <div yuwSidebarGroup>\n @if (group.label) {\n <div yuwSidebarGroupLabel>\n <span [class]=\"groupLabelTextClass\">{{ group.label }}</span>\n </div>\n }\n\n <div yuwSidebarGroupContent>\n <ul yuwSidebarMenu class=\"gap-1\">\n @for (item of group.items; track item.id) {\n <li yuwSidebarMenuItem>\n @if (item.route) {\n <a\n yuwSidebarMenuButton\n [closeMobileSidebarOnClick]=\"!item.hasChildren\"\n [routerLink]=\"item.route\"\n routerLinkActive\n #link=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"item.activeOptions\"\n [isActive]=\"link.isActive\"\n [tooltip]=\"item.tooltipText\"\n [attr.aria-current]=\"link.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [class.pointer-events-none]=\"(link.isActive && !item.hasChildren) || item.disabled\"\n (click)=\"onParentClick(item, item.expanded)\"\n >\n @if (item.icon) {\n <ng-icon [name]=\"item.icon\" />\n }\n <span>{{ item.label }}</span>\n @if (item.hasChildren) {\n <ng-icon name=\"lucideChevronRight\" [class]=\"chevronClass\" />\n }\n </a>\n } @else if (item.href) {\n <a\n yuwSidebarMenuButton\n [closeMobileSidebarOnClick]=\"!item.hasChildren\"\n [href]=\"item.href\"\n [attr.target]=\"item.target\"\n [tooltip]=\"item.tooltipText\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [class.pointer-events-none]=\"item.disabled\"\n (click)=\"onParentClick(item, item.expanded)\"\n >\n @if (item.icon) {\n <ng-icon [name]=\"item.icon\" />\n }\n <span>{{ item.label }}</span>\n @if (item.hasChildren) {\n <ng-icon name=\"lucideChevronRight\" [class]=\"chevronClass\" />\n }\n </a>\n } @else {\n <button\n yuwSidebarMenuButton\n [closeMobileSidebarOnClick]=\"!item.hasChildren\"\n type=\"button\"\n [tooltip]=\"item.tooltipText\"\n [disabled]=\"item.disabled ?? false\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n (click)=\"item.hasChildren ? onParentClick(item, item.expanded) : onItemClick(item.id, $event)\"\n >\n @if (item.icon) {\n <ng-icon [name]=\"item.icon\" />\n }\n <span>{{ item.label }}</span>\n @if (item.hasChildren) {\n <ng-icon name=\"lucideChevronRight\" [class]=\"chevronClass\" />\n }\n </button>\n }\n\n @if (item.badge) {\n <span yuwSidebarMenuBadge [class]=\"badgeClass\">{{ item.badge }}</span>\n }\n\n @if (item.hasChildren && !isRail()) {\n <div\n [class]=\"item.submenuClass\"\n [attr.inert]=\"item.expanded ? null : ''\"\n [attr.aria-hidden]=\"!item.expanded\"\n >\n <div>\n <ng-container [ngTemplateOutlet]=\"submenu\" [ngTemplateOutletContext]=\"{ $implicit: item }\" />\n </div>\n </div>\n }\n </li>\n }\n </ul>\n </div>\n </div>\n\n @if (group.separatorAfter) {\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n }\n}\n" }]
|
|
4957
4866
|
}], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
|
|
4958
4867
|
|
|
4868
|
+
/**
|
|
4869
|
+
* The one submenu panel of a collapsed sidebar, showing whatever `YuwSidebarSubmenuService` holds.
|
|
4870
|
+
* Lives here rather than in `YuwSidebarNavComponent`, which `<yuw-sidebar>` instantiates twice.
|
|
4871
|
+
*
|
|
4872
|
+
* The rail width is re-declared as `--yuw-sidebar-rail-width` on the CDK overlay *container*: the
|
|
4873
|
+
* overlay is portalled out of the wrapper that owns `--sidebar-width-icon`, and the panel and
|
|
4874
|
+
* backdrop are siblings there that both need it. It is read off the live wrapper because
|
|
4875
|
+
* `[sidebarWidthIcon]` overrides the config without writing back to it.
|
|
4876
|
+
*
|
|
4877
|
+
* Not `aria-modal`, and scroll is left alone: the rail stays live behind the dim.
|
|
4878
|
+
*/
|
|
4879
|
+
class YuwSidebarSubmenuSheetComponent {
|
|
4880
|
+
constructor() {
|
|
4881
|
+
this.config = injectHlmSidebarConfig();
|
|
4882
|
+
this.rail = inject(YuwSidebarRailService);
|
|
4883
|
+
this.host = inject(ElementRef);
|
|
4884
|
+
this.overlayContainer = inject(OverlayContainer);
|
|
4885
|
+
this._submenu = inject(YuwSidebarSubmenuService);
|
|
4886
|
+
this.itemClicked = output();
|
|
4887
|
+
this.panelClass = yuwSidebarSubmenuSheetClass;
|
|
4888
|
+
this.overlayClass = yuwSidebarSubmenuOverlayClass;
|
|
4889
|
+
this.bodyClass = yuwSidebarSubmenuSheetBodyClass;
|
|
4890
|
+
this.labelClass = yuwSidebarSubmenuSheetLabelClass;
|
|
4891
|
+
this._item = this._submenu.renderedItem;
|
|
4892
|
+
this._activeOptions = computed(() => Object.fromEntries((this._item()?.children ?? []).map((child) => [child.id, { exact: child.exact ?? false }])), ...(ngDevMode ? [{ debugName: "_activeOptions" }] : /* istanbul ignore next */ []));
|
|
4893
|
+
effect(() => {
|
|
4894
|
+
if (this.rail.railSettled())
|
|
4895
|
+
return;
|
|
4896
|
+
this._submenu.close();
|
|
4897
|
+
});
|
|
4898
|
+
effect(() => {
|
|
4899
|
+
if (!this._submenu.open())
|
|
4900
|
+
return;
|
|
4901
|
+
this.overlayContainer.getContainerElement().style.setProperty(YUW_SIDEBAR_RAIL_WIDTH_VAR, this.railWidth());
|
|
4902
|
+
});
|
|
4903
|
+
}
|
|
4904
|
+
railWidth() {
|
|
4905
|
+
const wrapper = this.host.nativeElement.closest('[data-slot=sidebar-wrapper]');
|
|
4906
|
+
const resolved = wrapper ? getComputedStyle(wrapper).getPropertyValue('--sidebar-width-icon').trim() : '';
|
|
4907
|
+
return resolved || this.config.sidebarWidthIcon;
|
|
4908
|
+
}
|
|
4909
|
+
onOpenChange(open) {
|
|
4910
|
+
if (open)
|
|
4911
|
+
return;
|
|
4912
|
+
this._submenu.close();
|
|
4913
|
+
}
|
|
4914
|
+
onChildClick(id, event) {
|
|
4915
|
+
this._submenu.close();
|
|
4916
|
+
this.itemClicked.emit({ id, event });
|
|
4917
|
+
}
|
|
4918
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4919
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: YuwSidebarSubmenuSheetComponent, isStandalone: true, selector: "yuw-sidebar-submenu-sheet", outputs: { itemClicked: "itemClicked" }, host: { classAttribute: "contents" }, ngImport: i0, template: "@if (_item(); as item) {\n <yuw-sheet\n side=\"left\"\n [open]=\"_submenu.open()\"\n (openChange)=\"onOpenChange($event)\"\n [showTrigger]=\"false\"\n [ariaLabel]=\"item.label\"\n [panelClass]=\"panelClass\"\n [overlayClass]=\"overlayClass\"\n [ariaModal]=\"false\"\n scrollStrategy=\"reposition\"\n >\n <div [class]=\"bodyClass\">\n <span [class]=\"labelClass\">{{ item.label }}</span>\n\n <ul yuwSidebarMenuSub>\n @for (child of item.children; track child.id) {\n <li yuwSidebarMenuSubItem>\n @if (child.route) {\n <a\n yuwSidebarMenuSubButton\n [routerLink]=\"child.route\"\n routerLinkActive\n #childLink=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"_activeOptions()[child.id]\"\n [isActive]=\"childLink.isActive\"\n [attr.aria-current]=\"childLink.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"childLink.isActive || child.disabled\"\n (click)=\"_submenu.close()\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else if (child.href) {\n <a\n yuwSidebarMenuSubButton\n [href]=\"child.href\"\n [attr.target]=\"child.target\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"child.disabled\"\n (click)=\"_submenu.close()\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else {\n <button\n yuwSidebarMenuSubButton\n type=\"button\"\n [disabled]=\"child.disabled ?? false\"\n (click)=\"onChildClick(child.id, $event)\"\n >\n <span>{{ child.label }}</span>\n </button>\n }\n </li>\n }\n </ul>\n </div>\n </yuw-sheet>\n}\n", dependencies: [{ kind: "component", type: YuwSheetComponent, selector: "yuw-sheet", inputs: ["open", "showTrigger", "side", "title", "description", "ariaLabel", "closeLabel", "panelClass", "overlayClass", "scrollStrategy", "ariaModal", "closeOnOutsidePointerEvents", "triggerVariant", "triggerSize"], outputs: ["openChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: YuwSidebarMenuSubDirective, selector: "ul[yuwSidebarMenuSub]" }, { kind: "directive", type: YuwSidebarMenuSubItemDirective, selector: "li[yuwSidebarMenuSubItem]" }, { kind: "directive", type: YuwSidebarMenuSubButtonDirective, selector: "a[yuwSidebarMenuSubButton], button[yuwSidebarMenuSubButton]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4920
|
+
}
|
|
4921
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuSheetComponent, decorators: [{
|
|
4922
|
+
type: Component,
|
|
4923
|
+
args: [{ selector: 'yuw-sidebar-submenu-sheet', imports: [
|
|
4924
|
+
YuwSheetComponent,
|
|
4925
|
+
RouterLink,
|
|
4926
|
+
RouterLinkActive,
|
|
4927
|
+
YuwSidebarMenuSubDirective,
|
|
4928
|
+
YuwSidebarMenuSubItemDirective,
|
|
4929
|
+
YuwSidebarMenuSubButtonDirective,
|
|
4930
|
+
], host: {
|
|
4931
|
+
class: 'contents',
|
|
4932
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (_item(); as item) {\n <yuw-sheet\n side=\"left\"\n [open]=\"_submenu.open()\"\n (openChange)=\"onOpenChange($event)\"\n [showTrigger]=\"false\"\n [ariaLabel]=\"item.label\"\n [panelClass]=\"panelClass\"\n [overlayClass]=\"overlayClass\"\n [ariaModal]=\"false\"\n scrollStrategy=\"reposition\"\n >\n <div [class]=\"bodyClass\">\n <span [class]=\"labelClass\">{{ item.label }}</span>\n\n <ul yuwSidebarMenuSub>\n @for (child of item.children; track child.id) {\n <li yuwSidebarMenuSubItem>\n @if (child.route) {\n <a\n yuwSidebarMenuSubButton\n [routerLink]=\"child.route\"\n routerLinkActive\n #childLink=\"routerLinkActive\"\n [routerLinkActiveOptions]=\"_activeOptions()[child.id]\"\n [isActive]=\"childLink.isActive\"\n [attr.aria-current]=\"childLink.isActive ? 'page' : null\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"childLink.isActive || child.disabled\"\n (click)=\"_submenu.close()\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else if (child.href) {\n <a\n yuwSidebarMenuSubButton\n [href]=\"child.href\"\n [attr.target]=\"child.target\"\n [attr.aria-disabled]=\"child.disabled ? 'true' : null\"\n [class.pointer-events-none]=\"child.disabled\"\n (click)=\"_submenu.close()\"\n >\n <span>{{ child.label }}</span>\n </a>\n } @else {\n <button\n yuwSidebarMenuSubButton\n type=\"button\"\n [disabled]=\"child.disabled ?? false\"\n (click)=\"onChildClick(child.id, $event)\"\n >\n <span>{{ child.label }}</span>\n </button>\n }\n </li>\n }\n </ul>\n </div>\n </yuw-sheet>\n}\n" }]
|
|
4933
|
+
}], ctorParameters: () => [], propDecorators: { itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
|
|
4934
|
+
|
|
4959
4935
|
/**
|
|
4960
4936
|
* Collapsible navigation sidebar. Renders as a fixed panel on desktop and as a slide-in sheet on
|
|
4961
4937
|
* mobile, and reads its colors from the `--sidebar-*` theme tokens.
|
|
@@ -4975,8 +4951,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4975
4951
|
* `[routerLink]` anchor whose active state, `aria-current` and pointer-lock resolve automatically
|
|
4976
4952
|
* from `routerLinkActive`; one with an `href` becomes a plain anchor; one with neither becomes a
|
|
4977
4953
|
* button that reports through `itemClicked`. An item with `children` gets a submenu that follows
|
|
4978
|
-
* the sidebar's own state: an accordion while the panel is open, and a
|
|
4979
|
-
* once it is collapsed to icons, so nested entries stay reachable
|
|
4954
|
+
* the sidebar's own state: an accordion while the panel is open, and a sheet sliding out beside the
|
|
4955
|
+
* rail once it is collapsed to icons, so nested entries stay reachable there. Its `expanded`
|
|
4980
4956
|
* field seeds the accordion; the item holding the active route opens on its own.
|
|
4981
4957
|
* - `footer`: The same, rendered into the footer region.
|
|
4982
4958
|
*
|
|
@@ -4998,6 +4974,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
4998
4974
|
* content area's flex sizing — mark it `[yuwSidebarContentExtra]` or `[yuwSidebarFooterExtra]`; the
|
|
4999
4975
|
* default slot keeps everything else, so existing projection-only usage is unaffected.
|
|
5000
4976
|
*
|
|
4977
|
+
* With `collapsible="icon"` the component also renders a single submenu sheet, shared by every entry
|
|
4978
|
+
* that has `children` in either region. It is one panel rather than one per entry because a sheet is a
|
|
4979
|
+
* modal overlay: several would compete for the same screen position, and only one submenu is ever on
|
|
4980
|
+
* screen anyway.
|
|
4981
|
+
*
|
|
5001
4982
|
* `header` has no object form: it is a free-form branding area with no repeating structure to model.
|
|
5002
4983
|
*
|
|
5003
4984
|
* Deliberately not exposed from the helm sidebar (add a wrapper only when a real consumer needs
|
|
@@ -5057,19 +5038,20 @@ class YuwSidebarComponent {
|
|
|
5057
5038
|
this.railSettledChange = outputFromObservable(toObservable(this._rail.railSettled).pipe(distinctUntilChanged()));
|
|
5058
5039
|
}
|
|
5059
5040
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5060
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: YuwSidebarComponent, isStandalone: true, selector: "yuw-sidebar", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, sidebarWidthMobile: { classPropertyName: "sidebarWidthMobile", publicName: "sidebarWidthMobile", isSignal: true, isRequired: false, transformFunction: null }, sidebarContainerClass: { classPropertyName: "sidebarContainerClass", publicName: "sidebarContainerClass", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, footer: { classPropertyName: "footer", publicName: "footer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked", collapsedChange: "collapsedChange", railSettledChange: "railSettledChange" }, host: { classAttribute: "contents" }, ngImport: i0, template: "<hlm-sidebar\n [attr.data-yuw-rail]=\"_isRail() ? 'on' : null\"\n [side]=\"side()\"\n [variant]=\"variant()\"\n [collapsible]=\"collapsible()\"\n [sidebarWidthMobile]=\"sidebarWidthMobile()\"\n [sidebarContainerClass]=\"_containerClass()\"\n>\n <ng-content select=\"[yuwSidebarHeader], yuw-sidebar-header\" />\n\n @if (content(); as nav) {\n <div yuwSidebarContent>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarContentExtra]\" />\n </div>\n }\n\n <ng-content />\n\n @if (footer(); as nav) {\n <div yuwSidebarFooter>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarFooterExtra]\" />\n </div>\n }\n</hlm-sidebar>\n", dependencies: [{ kind: "component", type: HlmSidebar, selector: "hlm-sidebar", inputs: ["sidebarWidthMobile", "side", "variant", "collapsible", "sidebarContainerClass"] }, { kind: "component", type: YuwSidebarNavComponent, selector: "yuw-sidebar-nav", inputs: ["content", "collapsible"], outputs: ["itemClicked"] }, { kind: "directive", type: YuwSidebarContentDirective, selector: "[yuwSidebarContent], yuw-sidebar-content" }, { kind: "directive", type: YuwSidebarFooterDirective, selector: "[yuwSidebarFooter], yuw-sidebar-footer" }, { kind: "directive", type: YuwSidebarSeparatorDirective, selector: "[yuwSidebarSeparator], yuw-sidebar-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5041
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: YuwSidebarComponent, isStandalone: true, selector: "yuw-sidebar", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, sidebarWidthMobile: { classPropertyName: "sidebarWidthMobile", publicName: "sidebarWidthMobile", isSignal: true, isRequired: false, transformFunction: null }, sidebarContainerClass: { classPropertyName: "sidebarContainerClass", publicName: "sidebarContainerClass", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, footer: { classPropertyName: "footer", publicName: "footer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked", collapsedChange: "collapsedChange", railSettledChange: "railSettledChange" }, host: { classAttribute: "contents" }, providers: [YuwSidebarSubmenuService], ngImport: i0, template: "<hlm-sidebar\n [attr.data-yuw-rail]=\"_isRail() ? 'on' : null\"\n [side]=\"side()\"\n [variant]=\"variant()\"\n [collapsible]=\"collapsible()\"\n [sidebarWidthMobile]=\"sidebarWidthMobile()\"\n [sidebarContainerClass]=\"_containerClass()\"\n>\n <ng-content select=\"[yuwSidebarHeader], yuw-sidebar-header\" />\n\n @if (content(); as nav) {\n <div yuwSidebarContent>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarContentExtra]\" />\n </div>\n }\n\n <ng-content />\n\n @if (footer(); as nav) {\n <div yuwSidebarFooter>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarFooterExtra]\" />\n </div>\n }\n</hlm-sidebar>\n\n@if (collapsible() === 'icon') {\n <yuw-sidebar-submenu-sheet (itemClicked)=\"itemClicked.emit($event)\" />\n}\n", dependencies: [{ kind: "component", type: HlmSidebar, selector: "hlm-sidebar", inputs: ["sidebarWidthMobile", "side", "variant", "collapsible", "sidebarContainerClass"] }, { kind: "component", type: YuwSidebarNavComponent, selector: "yuw-sidebar-nav", inputs: ["content", "collapsible"], outputs: ["itemClicked"] }, { kind: "component", type: YuwSidebarSubmenuSheetComponent, selector: "yuw-sidebar-submenu-sheet", outputs: ["itemClicked"] }, { kind: "directive", type: YuwSidebarContentDirective, selector: "[yuwSidebarContent], yuw-sidebar-content" }, { kind: "directive", type: YuwSidebarFooterDirective, selector: "[yuwSidebarFooter], yuw-sidebar-footer" }, { kind: "directive", type: YuwSidebarSeparatorDirective, selector: "[yuwSidebarSeparator], yuw-sidebar-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5061
5042
|
}
|
|
5062
5043
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarComponent, decorators: [{
|
|
5063
5044
|
type: Component,
|
|
5064
5045
|
args: [{ selector: 'yuw-sidebar', imports: [
|
|
5065
5046
|
HlmSidebar,
|
|
5066
5047
|
YuwSidebarNavComponent,
|
|
5048
|
+
YuwSidebarSubmenuSheetComponent,
|
|
5067
5049
|
YuwSidebarContentDirective,
|
|
5068
5050
|
YuwSidebarFooterDirective,
|
|
5069
5051
|
YuwSidebarSeparatorDirective,
|
|
5070
5052
|
], host: {
|
|
5071
5053
|
class: 'contents',
|
|
5072
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<hlm-sidebar\n [attr.data-yuw-rail]=\"_isRail() ? 'on' : null\"\n [side]=\"side()\"\n [variant]=\"variant()\"\n [collapsible]=\"collapsible()\"\n [sidebarWidthMobile]=\"sidebarWidthMobile()\"\n [sidebarContainerClass]=\"_containerClass()\"\n>\n <ng-content select=\"[yuwSidebarHeader], yuw-sidebar-header\" />\n\n @if (content(); as nav) {\n <div yuwSidebarContent>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarContentExtra]\" />\n </div>\n }\n\n <ng-content />\n\n @if (footer(); as nav) {\n <div yuwSidebarFooter>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarFooterExtra]\" />\n </div>\n }\n</hlm-sidebar>\n" }]
|
|
5054
|
+
}, providers: [YuwSidebarSubmenuService], changeDetection: ChangeDetectionStrategy.OnPush, template: "<hlm-sidebar\n [attr.data-yuw-rail]=\"_isRail() ? 'on' : null\"\n [side]=\"side()\"\n [variant]=\"variant()\"\n [collapsible]=\"collapsible()\"\n [sidebarWidthMobile]=\"sidebarWidthMobile()\"\n [sidebarContainerClass]=\"_containerClass()\"\n>\n <ng-content select=\"[yuwSidebarHeader], yuw-sidebar-header\" />\n\n @if (content(); as nav) {\n <div yuwSidebarContent>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarContentExtra]\" />\n </div>\n }\n\n <ng-content />\n\n @if (footer(); as nav) {\n <div yuwSidebarFooter>\n <div yuwSidebarSeparator class=\"mx-auto w-4/5!\"></div>\n <yuw-sidebar-nav [content]=\"nav\" [collapsible]=\"collapsible()\" (itemClicked)=\"itemClicked.emit($event)\" />\n <ng-content select=\"[yuwSidebarFooterExtra]\" />\n </div>\n }\n</hlm-sidebar>\n\n@if (collapsible() === 'icon') {\n <yuw-sidebar-submenu-sheet (itemClicked)=\"itemClicked.emit($event)\" />\n}\n" }]
|
|
5073
5055
|
}], propDecorators: { side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], sidebarWidthMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarWidthMobile", required: false }] }], sidebarContainerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarContainerClass", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], footer: [{ type: i0.Input, args: [{ isSignal: true, alias: "footer", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }], collapsedChange: [{ type: i0.Output, args: ["collapsedChange"] }], railSettledChange: [{ type: i0.Output, args: ["railSettledChange"] }] } });
|
|
5074
5056
|
|
|
5075
5057
|
/**
|
|
@@ -5107,5 +5089,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
5107
5089
|
* Generated bundle index. Do not edit.
|
|
5108
5090
|
*/
|
|
5109
5091
|
|
|
5110
|
-
export { DATATABLE_ALIGN_CLASS, YUW_DATATABLE_FEATURES, YUW_PASSWORD_REVEAL_STATES, YuwAccordion, YuwAccordionContentComponent, YuwAccordionImports, YuwAccordionItem, YuwAccordionTriggerComponent, YuwAlertActionDirective, YuwAlertComponent, YuwAlertDescriptionDirective, YuwAlertDialogComponent, YuwAlertDialogMediaDirective, YuwAlertDialogTriggerDirective, YuwAlertImports, YuwAlertTitleDirective, YuwAttachmentActionDirective, YuwAttachmentActionsDirective, YuwAttachmentContentDirective, YuwAttachmentDescriptionDirective, YuwAttachmentDirective, YuwAttachmentGroupDirective, YuwAttachmentMediaDirective, YuwAttachmentTitleDirective, YuwAttachmentTriggerDirective, YuwAvatarComponent, YuwBadgeComponent, YuwBreadcrumbComponent, YuwButtonComponent, YuwButtonGroupTextDirective, YuwCaptionDirective, YuwCardActionDirective, YuwCardContentDirective, YuwCardDescriptionDirective, YuwCardDirective, YuwCardFooterDirective, YuwCardHeaderDirective, YuwCardImports, YuwCardTitleDirective, YuwCheckboxComponent, YuwComboboxComponent, YuwComboboxItemDirective, YuwContextMenuCheckboxDirective, YuwContextMenuCheckboxIndicatorComponent, YuwContextMenuDirective, YuwContextMenuGroupDirective, YuwContextMenuImports, YuwContextMenuItemDirective, YuwContextMenuLabelDirective, YuwContextMenuRadioDirective, YuwContextMenuRadioIndicatorComponent, YuwContextMenuSeparatorDirective, YuwContextMenuShortcutDirective, YuwContextMenuSubDirective, YuwContextMenuSubIndicatorComponent, YuwContextMenuSubTriggerDirective, YuwContextMenuTriggerDirective, YuwDatatableComponent, YuwDatatableRowSelect, YuwDatepickerComponent, YuwDialogCloseDirective, YuwDialogComponent, YuwDialogFooterDirective, YuwDialogImports, YuwDialogTriggerDirective, YuwEmptyContentDirective, YuwEmptyDescriptionDirective, YuwEmptyDirective, YuwEmptyHeaderDirective, YuwEmptyImports, YuwEmptyMediaDirective, YuwEmptyTitleDirective, YuwInputAddonImports, YuwInputComponent, YuwInputOtpComponent, YuwItemActionsDirective, YuwItemContentDirective, YuwItemDescriptionDirective, YuwItemDirective, YuwItemFooterDirective, YuwItemGroupDirective, YuwItemHeaderDirective, YuwItemImports, YuwItemMediaDirective, YuwItemSeparatorDirective, YuwItemTitleDirective, YuwLabel, YuwLeftAddonDirective, YuwPaginationComponent, YuwPasswordInputComponent, YuwPopoverComponent, YuwPopoverTriggerDirective, YuwRadioGroupComponent, YuwRightAddonDirective, YuwSearchInputComponent, YuwSheetCloseDirective, YuwSheetComponent, YuwSheetFooterDirective, YuwSheetImports, YuwSheetTriggerDirective, YuwSidebarComponent, YuwSidebarContentDirective, YuwSidebarContentExtraDirective,
|
|
5092
|
+
export { DATATABLE_ALIGN_CLASS, YUW_DATATABLE_FEATURES, YUW_PASSWORD_REVEAL_STATES, YuwAccordion, YuwAccordionContentComponent, YuwAccordionImports, YuwAccordionItem, YuwAccordionTriggerComponent, YuwAlertActionDirective, YuwAlertComponent, YuwAlertDescriptionDirective, YuwAlertDialogComponent, YuwAlertDialogMediaDirective, YuwAlertDialogTriggerDirective, YuwAlertImports, YuwAlertTitleDirective, YuwAttachmentActionDirective, YuwAttachmentActionsDirective, YuwAttachmentContentDirective, YuwAttachmentDescriptionDirective, YuwAttachmentDirective, YuwAttachmentGroupDirective, YuwAttachmentMediaDirective, YuwAttachmentTitleDirective, YuwAttachmentTriggerDirective, YuwAvatarComponent, YuwBadgeComponent, YuwBreadcrumbComponent, YuwButtonComponent, YuwButtonGroupTextDirective, YuwCaptionDirective, YuwCardActionDirective, YuwCardContentDirective, YuwCardDescriptionDirective, YuwCardDirective, YuwCardFooterDirective, YuwCardHeaderDirective, YuwCardImports, YuwCardTitleDirective, YuwCheckboxComponent, YuwComboboxComponent, YuwComboboxItemDirective, YuwContextMenuCheckboxDirective, YuwContextMenuCheckboxIndicatorComponent, YuwContextMenuDirective, YuwContextMenuGroupDirective, YuwContextMenuImports, YuwContextMenuItemDirective, YuwContextMenuLabelDirective, YuwContextMenuRadioDirective, YuwContextMenuRadioIndicatorComponent, YuwContextMenuSeparatorDirective, YuwContextMenuShortcutDirective, YuwContextMenuSubDirective, YuwContextMenuSubIndicatorComponent, YuwContextMenuSubTriggerDirective, YuwContextMenuTriggerDirective, YuwDatatableComponent, YuwDatatableRowSelect, YuwDatepickerComponent, YuwDialogCloseDirective, YuwDialogComponent, YuwDialogFooterDirective, YuwDialogImports, YuwDialogTriggerDirective, YuwEmptyContentDirective, YuwEmptyDescriptionDirective, YuwEmptyDirective, YuwEmptyHeaderDirective, YuwEmptyImports, YuwEmptyMediaDirective, YuwEmptyTitleDirective, YuwInputAddonImports, YuwInputComponent, YuwInputOtpComponent, YuwItemActionsDirective, YuwItemContentDirective, YuwItemDescriptionDirective, YuwItemDirective, YuwItemFooterDirective, YuwItemGroupDirective, YuwItemHeaderDirective, YuwItemImports, YuwItemMediaDirective, YuwItemSeparatorDirective, YuwItemTitleDirective, YuwLabel, YuwLeftAddonDirective, YuwPaginationComponent, YuwPasswordInputComponent, YuwPopoverComponent, YuwPopoverTriggerDirective, YuwRadioGroupComponent, YuwRightAddonDirective, YuwSearchInputComponent, YuwSheetCloseDirective, YuwSheetComponent, YuwSheetFooterDirective, YuwSheetImports, YuwSheetTriggerDirective, YuwSidebarComponent, YuwSidebarContentDirective, YuwSidebarContentExtraDirective, YuwSidebarFooterDirective, YuwSidebarFooterExtraDirective, YuwSidebarGroupContentDirective, YuwSidebarGroupDirective, YuwSidebarGroupLabelDirective, YuwSidebarHeaderDirective, YuwSidebarInsetDirective, YuwSidebarMenuBadgeDirective, YuwSidebarMenuButtonDirective, YuwSidebarMenuDirective, YuwSidebarMenuItemDirective, YuwSidebarMenuSubButtonDirective, YuwSidebarMenuSubDirective, YuwSidebarMenuSubItemDirective, YuwSidebarRailDirective, YuwSidebarRailService, YuwSidebarSeparatorDirective, YuwSidebarSubmenuService, YuwSidebarTriggerComponent, YuwSidebarWrapperDirective, YuwSkeletonDirective, YuwSpinnerComponent, YuwSwitchComponent, YuwTBodyDirective, YuwTFootDirective, YuwTHeadDirective, YuwTabPanelDirective, YuwTableContainerDirective, YuwTableDirective, YuwTableImports, YuwTabsComponent, YuwTdDirective, YuwTextareaComponent, YuwThDirective, YuwToasterComponent, YuwTooltipDirective, YuwTrDirective, YuwValueAccessorBase, buildInputOtpGroups, cn, datatableCellVariants, datatableContainerVariants, datatableHeadVariants, datatableHeaderCellVariants, datatableRowVariants, getPaginationRange, provideValueAccessor, totalInputOtpLength };
|
|
5111
5093
|
//# sourceMappingURL=yukit-web.mjs.map
|