yukit-web 0.0.9 → 0.0.11

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.
@@ -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, ViewContainerRef, runInInjectionContext } 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, 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, merge, fromEvent } from 'rxjs';
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, switchMap as switchMap$1 } from 'rxjs/operators';
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 * as i2$1 from 'yukit-web/helm/hover-card';
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 [side]=\"side()\" [state]=\"_sheetState()\" [aria-label]=\"ariaLabel()\" (stateChanged)=\"onStateChanged($event)\">\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 }); }
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 [side]=\"side()\" [state]=\"_sheetState()\" [aria-label]=\"ariaLabel()\" (stateChanged)=\"onStateChanged($event)\">\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" }]
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 yuwSidebarFlyoutClass = [
4099
- 'w-56',
4100
- 'ms-2',
4101
- 'p-1',
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 yuwSidebarFlyoutLabelClass = [
4155
+ const yuwSidebarSubmenuSheetLabelClass = [
4115
4156
  'text-muted-foreground',
4116
- 'px-2',
4117
- 'pt-1',
4157
+ 'pt-4',
4118
4158
  'pb-1.5',
4119
4159
  'text-xs',
4120
4160
  'font-medium',
@@ -4191,7 +4231,7 @@ const yuwSidebarMenuSubButtonClass = ['[&>span]:truncate', '[&>span]:min-w-0'].j
4191
4231
  *
4192
4232
  * Provided at the root so `<yuw-sidebar>` and the nav share one instance — the component stamps the
4193
4233
  * attribute the class layers select on, and the nav reads the same signal to decide between accordion
4194
- * and flyout, so the two must agree on the exact frame.
4234
+ * and submenu sheet, so the two must agree on the exact frame.
4195
4235
  */
4196
4236
  class YuwSidebarRailService {
4197
4237
  constructor() {
@@ -4427,13 +4467,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
4427
4467
  * (`'default'`, `'sm'`, `'lg'`) and `isActive`.
4428
4468
  *
4429
4469
  * `tooltip` labels the item while the sidebar is collapsed to icons, where the label itself is
4430
- * hidden; the composed primitive shows it only in that state, and only for entries with no flyout of
4431
- * their ownan entry with children opens its submenu on the same hover instead.
4470
+ * hidden; the composed primitive shows it only in that state. Every entry gets one, including those
4471
+ * with childrentheir submenu opens on click, so it never competes with the hover.
4432
4472
  *
4433
4473
  * Reaching that input takes composing `BrnTooltip` here under the same `tooltip` alias the helm uses,
4434
4474
  * rather than forwarding it. `HlmSidebarMenuButton` publishes the alias on its own `hostDirectives`
4435
4475
  * entry, which does not make it an input of the helm directive — a forward cannot be re-forwarded, the
4436
- * same limit `[yuwSidebarFlyoutTrigger]` runs into. Angular resolves both entries to the one
4476
+ * same limit `context-menu.directives.ts` documents. Angular resolves both entries to the one
4437
4477
  * `BrnTooltip` instance on the element, so the helm keeps driving `mutableTooltipDisabled` (which is
4438
4478
  * what confines the tooltip to the collapsed state) while this binding supplies its content.
4439
4479
  *
@@ -4460,7 +4500,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
4460
4500
  * shrink-to-fit for the whole width animation — long enough for the label to stop ellipsing and
4461
4501
  * the trailing chevron to sit against it.
4462
4502
  * - `[&>span]:hidden` drops the label while collapsed, leaving the icon alone — the tooltip carries
4463
- * the name in that state, or the flyout does for an entry with children. Matched by element rather
4503
+ * the name in that state. Matched by element rather
4464
4504
  * than by `:last-child` (which is what the helm's own `truncate` uses): an expandable entry ends
4465
4505
  * with a trailing chevron, so the label is no longer the last child and a positional selector
4466
4506
  * would skip exactly those entries. `span` is unambiguous here — the label is the only one a menu
@@ -4555,179 +4595,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
4555
4595
  hostDirectives: [{ directive: HlmSidebarMenuSubButton, inputs: ['size', 'isActive', 'closeMobileSidebarOnClick'] }],
4556
4596
  }]
4557
4597
  }], ctorParameters: () => [] });
4558
- /**
4559
- * Host of a collapsed-state flyout: the element that scopes the overlay for one entry. Apply
4560
- * alongside `[yuwSidebarMenuItem]` on the `<li>` holding the entry and its panel.
4561
- *
4562
- * Provides `BrnHoverCardContentService` itself instead of composing `HlmHoverCard`. The service has
4563
- * to be scoped per `<li>` — it holds the single overlay and its content, so a shared one would have
4564
- * every entry in the sidebar fighting over the same panel — and providing it here is all that is
4565
- * needed for that. What `HlmHoverCard` adds on top is a `contentChild` pairing that assigns the
4566
- * trigger's content in `ngAfterContentInit`, and that pairing is actively harmful here: it writes
4567
- * into the same writable signal the trigger's own input feeds, so its one-time value outlives and
4568
- * overrides the binding that is supposed to turn the flyout off while the sidebar is expanded.
4569
- */
4570
- class YuwSidebarFlyoutHostDirective {
4571
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutHostDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4572
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.8", type: YuwSidebarFlyoutHostDirective, isStandalone: true, selector: "[yuwSidebarFlyoutHost]", providers: [BrnHoverCardContentService], ngImport: i0 }); }
4573
- }
4574
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutHostDirective, decorators: [{
4575
- type: Directive,
4576
- args: [{
4577
- selector: '[yuwSidebarFlyoutHost]',
4578
- providers: [BrnHoverCardContentService],
4579
- }]
4580
- }] });
4581
- /**
4582
- * The entry whose hover opens a flyout. Apply to the same element as `[yuwSidebarMenuButton]`, bound
4583
- * to the panel's `<ng-template>` reference — or to `undefined` to switch the flyout off entirely,
4584
- * which is how an expanded sidebar keeps its submenus inline.
4585
- *
4586
- * Drives `BrnHoverCardContentService` directly instead of composing `BrnHoverCardTrigger`. The brain
4587
- * trigger has no way to be turned off once it has run: it feeds the panel to the service through an
4588
- * effect that ignores falsy values, and the service's `show()` consults only its stored content, so
4589
- * a trigger that was ever enabled keeps opening its overlay forever. Rebinding to `undefined` cannot
4590
- * undo it, and neither can `hide()`, which detaches the overlay but leaves the content in place.
4591
- * Owning the wiring here is what makes an unbound panel mean "inert".
4592
- *
4593
- * The `effect` is the whole lifecycle: it runs when a panel arrives, and its `onCleanup` closes the
4594
- * overlay and drops the subscription when the panel goes away or the entry is destroyed. Nothing
4595
- * else tracks teardown, which is why there is no `DestroyRef` or `takeUntilDestroyed` here — a second
4596
- * mechanism would only be able to disagree with this one.
4597
- *
4598
- * Delays are read inside `switchMap` rather than captured when the effect runs, so retuning them
4599
- * does not tear down and rebuild the subscription.
4600
- *
4601
- * `distinctUntilChanged` before the timer is load-bearing, and not as an optimisation: the five
4602
- * merged sources overlap, so crossing from the entry to the panel emits a `mouseleave` and the
4603
- * panel's own hover almost together, and `mouseenter` and `focusin` both fire on the same pointer
4604
- * arriving. Each duplicate would restart `switchMap` and cancel the timer already in flight, so a
4605
- * repeat during the show delay could keep the panel from ever opening.
4606
- *
4607
- * It cannot dedupe the crossing itself, though — that genuinely alternates `false` then `true`, so
4608
- * both values are distinct and both survive. `toggle` is therefore guarded against the state it is
4609
- * already in, because `show()` is not idempotent: it calls `detach()` then `attach()`, tearing the
4610
- * panel down and rebuilding it. Re-showing an open panel replays its enter animation, which is the
4611
- * flicker you get when the pointer moves from the rail into the flyout.
4612
- *
4613
- * Note there is no click handling. `BrnHoverCardTrigger` maps a click to `false`, which is right for
4614
- * a hover card — clicking the trigger dismisses it — and wrong for a nav rail, where the entry's own
4615
- * click has nothing to collapse while collapsed and closing the panel would take away the links the
4616
- * pointer is travelling to. Activating a child closes the flyout anyway, since the pointer leaves
4617
- * the panel as the page changes.
4618
- *
4619
- * `align` is `'right'` for a sidebar flyout rather than the hover card's own `'bottom'`. It is set as
4620
- * an input rather than through `provideBrnHoverCardDefaultOptions` because that provider types its
4621
- * `align` as `'top' | 'bottom'`, even though the position map handles all four sides.
4622
- */
4623
- class YuwSidebarFlyoutTriggerDirective {
4624
- constructor() {
4625
- this.element = inject(ElementRef);
4626
- this.viewContainerRef = inject(ViewContainerRef);
4627
- this.service = inject(BrnHoverCardContentService);
4628
- this.panel = input(undefined, { ...(ngDevMode ? { debugName: "panel" } : /* istanbul ignore next */ {}), alias: 'yuwSidebarFlyoutTrigger' });
4629
- this.align = input('right', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
4630
- this.sideOffset = input(0, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
4631
- this.showDelay = input(120, { ...(ngDevMode ? { debugName: "showDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
4632
- this.hideDelay = input(300, { ...(ngDevMode ? { debugName: "hideDelay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
4633
- 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$);
4634
- effect((onCleanup) => {
4635
- const panel = this.panel();
4636
- if (!panel)
4637
- return;
4638
- this.service.setConfig({
4639
- attachTo: this.element,
4640
- align: this.align(),
4641
- sideOffset: this.sideOffset(),
4642
- });
4643
- this.service.setContent(panel, this.viewContainerRef);
4644
- const subscription = this.pointerOver
4645
- .pipe(distinctUntilChanged(), switchMap$1((visible) => timer(visible ? this.showDelay() : this.hideDelay()).pipe(map(() => visible))))
4646
- .subscribe((visible) => this.toggle(visible));
4647
- onCleanup(() => {
4648
- subscription.unsubscribe();
4649
- this.toggle(false);
4650
- });
4651
- });
4652
- }
4653
- toggle(open) {
4654
- if (open === (this.service.state() === 'open'))
4655
- return;
4656
- this.service.setState(open ? 'open' : 'closed');
4657
- if (open) {
4658
- this.service.show();
4659
- return;
4660
- }
4661
- this.service.hide();
4662
- }
4663
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4664
- 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 }); }
4665
- }
4666
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutTriggerDirective, decorators: [{
4667
- type: Directive,
4668
- args: [{
4669
- selector: '[yuwSidebarFlyoutTrigger]',
4670
- }]
4671
- }], 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 }] }] } });
4672
- /**
4673
- * Marks the `<ng-template>` holding a flyout's markup, and is what `[yuwSidebarFlyoutTrigger]` is
4674
- * bound to. Exported as `yuwSidebarFlyoutPanel` so the template can name it.
4675
- *
4676
- * Structural — the composed primitive injects the `TemplateRef`, which is what lets the panel be
4677
- * portalled into a CDK overlay instead of rendering inside the rail.
4678
- *
4679
- * The trigger is bound to the template's own `#ref` (a `TemplateRef`, which its input accepts), so
4680
- * this directive is never referenced by name — but it cannot be dropped: it is the sole provider of
4681
- * the exposed state and side tokens that `[yuwSidebarFlyout]` injects from its host, and without it
4682
- * the panel throws NG0201 the moment the overlay instantiates it.
4683
- */
4684
- class YuwSidebarFlyoutPanelDirective {
4685
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutPanelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4686
- 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 }); }
4687
- }
4688
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutPanelDirective, decorators: [{
4689
- type: Directive,
4690
- args: [{
4691
- selector: 'ng-template[yuwSidebarFlyoutPanel]',
4692
- hostDirectives: [HlmHoverCardPortal],
4693
- }]
4694
- }] });
4695
- /**
4696
- * The flyout's visible surface. Apply to the single root element inside a `[yuwSidebarFlyoutPanel]`
4697
- * template.
4698
- *
4699
- * Separate from the panel marker because the two sit on different nodes: the marker is the
4700
- * `<ng-template>`, this is the element the overlay renders. Carries the popover surface of the
4701
- * composed helm content plus `yuwSidebarFlyoutClass`.
4702
- *
4703
- * That class layer exists because the panel lives in the overlay, outside the sidebar's DOM subtree,
4704
- * and so is no longer a descendant of the `group/sidebar-wrapper` element. Every
4705
- * `group-data-[collapsible=…]` selector therefore resolves against nothing and stays inert —
4706
- * including the `hidden` that `HlmSidebarMenuSub` and `HlmSidebarMenuSubButton` apply to themselves
4707
- * in exactly this state, which is why the submenu markup renders visible in here with no override.
4708
- * What the layer undoes instead is the indentation and vertical rule those primitives carry for the
4709
- * inline case, which make no sense in a panel.
4710
- *
4711
- * The gap between rail and panel is that layer's `ms-2`, not the trigger's `sideOffset`, which is
4712
- * deliberately `0`. An offset moves the overlay away from the trigger and leaves dead space between
4713
- * them: crossing it slowly means the pointer is over neither element, and the hover card closes
4714
- * mid-journey. A margin keeps the same visual gap inside the overlay's own box, so the pointer never
4715
- * leaves the hover target on its way in.
4716
- */
4717
- class YuwSidebarFlyoutDirective {
4718
- constructor() {
4719
- classes(() => yuwSidebarFlyoutClass);
4720
- }
4721
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4722
- 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 }); }
4723
- }
4724
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarFlyoutDirective, decorators: [{
4725
- type: Directive,
4726
- args: [{
4727
- selector: '[yuwSidebarFlyout]',
4728
- hostDirectives: [HlmHoverCardContent],
4729
- }]
4730
- }], ctorParameters: () => [] });
4731
4598
  /** Divider between sidebar sections. */
4732
4599
  class YuwSidebarSeparatorDirective {
4733
4600
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSeparatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -4775,11 +4642,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
4775
4642
  }]
4776
4643
  }] });
4777
4644
 
4778
- const CARET_RIGHT_BORDER_CLASSES = `
4779
- border-l-4 border-t-4 border-t-transparent border-r-0
4780
- border-b-4 border-b-transparent -right-[4.5px] border-[var(--sidebar-foreground)]
4781
- absolute transition-opacity
4782
- `;
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
+ * `closeUnhandled` is what dismisses the sheet for a click that lands on the rail but on nothing that
4654
+ * owns the submenu — the padding between entries, a separator, the header, a plain rail link.
4655
+ * `<yuw-sidebar>` calls it from a bubble-phase listener on its own host, which therefore runs *after*
4656
+ * the handler of whatever entry was clicked, so an entry that has just opened or swapped the sheet has
4657
+ * to be able to say "this click was mine". `toggle` records the event it acted on for exactly that,
4658
+ * keyed on event identity so no timer or DOM-target test is involved: there is one event object per
4659
+ * click and both handlers see it. Together with the backdrop — inset to the rail's right edge, so it
4660
+ * covers the rest of the viewport — that listener closes the sheet from anywhere outside it.
4661
+ *
4662
+ * The brain's own `closeOnOutsidePointerEvents` is deliberately *not* used for this. The CDK
4663
+ * dispatches outside pointer events from a capture listener on `body`, so it would close the sheet
4664
+ * before the clicked entry's own bubble-phase handler ran, and `toggle` would then see no active item
4665
+ * and re-open on the very click that dismissed it.
4666
+ */
4667
+ class YuwSidebarSubmenuService {
4668
+ constructor() {
4669
+ this.item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
4670
+ this.lastItem = signal(null, ...(ngDevMode ? [{ debugName: "lastItem" }] : /* istanbul ignore next */ []));
4671
+ this.handledEvent = null;
4672
+ this.activeItem = this.item.asReadonly();
4673
+ this.renderedItem = this.lastItem.asReadonly();
4674
+ this.open = computed(() => this.item() !== null, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
4675
+ }
4676
+ toggle(item, event) {
4677
+ this.handledEvent = event;
4678
+ const next = this.item()?.id === item.id ? null : item;
4679
+ this.item.set(next);
4680
+ if (next)
4681
+ this.lastItem.set(next);
4682
+ }
4683
+ close() {
4684
+ this.item.set(null);
4685
+ }
4686
+ closeUnhandled(event) {
4687
+ const handled = event === this.handledEvent;
4688
+ if (handled) {
4689
+ this.handledEvent = null;
4690
+ return;
4691
+ }
4692
+ this.close();
4693
+ }
4694
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4695
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuService }); }
4696
+ }
4697
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuService, decorators: [{
4698
+ type: Injectable
4699
+ }] });
4700
+
4783
4701
  /**
4784
4702
  * Renders one {@link YuwSidebarContentDto} as the group/menu/item tree.
4785
4703
  *
@@ -4793,19 +4711,33 @@ const CARET_RIGHT_BORDER_CLASSES = `
4793
4711
  * `group-data-[collapsible=icon]:` selectors — which resolve against the sidebar root — working
4794
4712
  * identically for object-rendered and hand-written markup.
4795
4713
  *
4796
- * An entry with `children` renders its submenu two ways, one per sidebar state. Expanded, it is an
4797
- * accordion: the entry carries `aria-expanded` and the submenu is nested beneath it. Collapsed to
4798
- * icons, where there is no room for either the label or the nesting, the same submenu moves into a
4799
- * hover flyout beside the rail. Both are always in the template the sidebar's own state decides
4800
- * which one is live, so nothing has to be re-created when the user toggles the rail.
4801
- *
4802
- * A click on such an entry toggles the accordion while the panel is open. When the entry also has a
4803
- * `route` or an `href` it navigates *and* toggles, which is why an active one keeps its pointer
4804
- * events instead of being locked like a childless active entry; when it has neither, toggling is all
4805
- * it does and it stays out of `itemClicked`, since opening a submenu is not an action for the
4806
- * consumer to handle. Collapsed to a rail the click does nothing at all: there is no inline submenu
4807
- * to fold there, and toggling would mutate state the user cannot see while closing the panel they
4808
- * are aiming at.
4714
+ * An entry with `children` shows its submenu two ways, one per sidebar state. Expanded, it is an
4715
+ * accordion rendered here: the entry carries `aria-expanded` and the submenu is nested beneath it.
4716
+ * Collapsed to icons, where there is no room for either the label or the nesting, it moves into the
4717
+ * sheet beside the rail which this component does not own. `<yuw-sidebar>` renders one sheet and
4718
+ * this component only reports, through `YuwSidebarSubmenuService`, which entry the user picked. It
4719
+ * cannot own the panel itself: `<yuw-sidebar>` instantiates this component twice, once for `content`
4720
+ * and once for `footer`, so a sheet in here would be two sheets fighting over one screen position.
4721
+ *
4722
+ * Such an entry also opts out of the helm's close-the-mobile-sheet-on-click behaviour, which every
4723
+ * other entry keeps. On mobile the sidebar *is* a sheet, and that behaviour assumes a click means
4724
+ * "I have navigated, take this away" true of a leaf, false of an accordion header, whose click only
4725
+ * unfolds a submenu inside the very panel it would be dismissing. Its children still close it, since
4726
+ * activating one of those really is the navigation the panel was opened for.
4727
+ *
4728
+ * A click on such an entry toggles the accordion while the panel is open, and opens the sheet on that
4729
+ * entry once collapsed — the same gesture either way, differing only in where the submenu appears.
4730
+ * Clicking the entry the sheet is already showing closes it; clicking a different one swaps the
4731
+ * sheet's contents. Only an entry that actually has children does any of this: `onParentClick` is the
4732
+ * click handler of every navigating entry, so it returns early for a childless one rather than opening
4733
+ * a sheet on an empty `children`. That guard lives in the method and not in the template so the
4734
+ * `route`, `href` and `<button>` branches cannot drift apart on it, and a childless entry then falls
4735
+ * through to `<yuw-sidebar>`'s host listener, which dismisses whatever sheet was open — clicking a
4736
+ * plain rail link should take its submenu away, not leave it hanging over the new page. When the entry
4737
+ * also has a `route` or an `href` it navigates *and* toggles, which is why an active one keeps its
4738
+ * pointer events instead of being locked like a childless active entry; when it has neither, toggling
4739
+ * is all it does and it stays out of `itemClicked`, since opening a submenu is not an action for the
4740
+ * consumer to handle.
4809
4741
  *
4810
4742
  * The chevron marking an expandable entry rotates off that same `aria-expanded`, read from the
4811
4743
  * button through the `group/menu-button` the helm already declares on every menu button. Its
@@ -4818,11 +4750,11 @@ const CARET_RIGHT_BORDER_CLASSES = `
4818
4750
  * Which of the two forms is live comes from `isRail`, and all three of its conditions are
4819
4751
  * load-bearing. `collapsible` must be `'icon'`, the only mode that leaves a narrow rail behind:
4820
4752
  * `'offcanvas'` moves the whole panel off-screen and `'none'` never collapses, yet the service
4821
- * reports `state() === 'collapsed'` for both — reading the state alone puts a flyout on a sidebar
4822
- * sitting there at full width. It must not be mobile, where the panel is a full-width sheet showing
4823
- * the accordion. And the collapse must have finished animating, which is what `railSettled` waits
4824
- * for: swapping the accordion for a flyout while the panel is still wide would tear the submenu out
4825
- * from under the pointer mid-transition. That same settled signal drives the rail's own styling, so
4753
+ * reports `state() === 'collapsed'` for both — reading the state alone opens the sheet beside a
4754
+ * sidebar sitting there at full width. It must not be mobile, where the panel is a full-width sheet
4755
+ * showing the accordion. And the collapse must have finished animating, which is what `railSettled`
4756
+ * waits for: switching to the sheet while the panel is still wide would leave it overlapping the very
4757
+ * sidebar it is supposed to sit beside. That same settled signal drives the rail's own styling, so
4826
4758
  * the geometry and the submenu form always change on the same frame.
4827
4759
  *
4828
4760
  * The accordion opens and closes over a grid-rows transition rather than by appearing outright, which
@@ -4857,8 +4789,8 @@ const CARET_RIGHT_BORDER_CLASSES = `
4857
4789
  * `routerLinkActiveOptions` a stable object identity: a literal in the template
4858
4790
  * (`[routerLinkActiveOptions]="{exact: item.exact ?? false}"`) allocates a new object on every
4859
4791
  * change-detection pass, and `RouterLinkActive` treats that as a changed input and re-runs its
4860
- * subscription. An entry with children resolves no tooltip at all the flyout already labels it
4861
- * while collapsed, and a tooltip would fire on the same hover at the same screen position.
4792
+ * subscription. Every entry resolves a tooltip, entries with children included: the submenu opens on
4793
+ * click, so hover is free to do what it does for every other rail icon and name the thing.
4862
4794
  */
4863
4795
  class YuwSidebarNavComponent {
4864
4796
  constructor() {
@@ -4866,15 +4798,14 @@ class YuwSidebarNavComponent {
4866
4798
  this.injector = inject(Injector);
4867
4799
  this.sidebarService = inject(HlmSidebarService);
4868
4800
  this.rail = inject(YuwSidebarRailService);
4801
+ this.submenu = inject(YuwSidebarSubmenuService);
4869
4802
  this.content = input.required(...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
4870
4803
  this.collapsible = input('offcanvas', ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
4871
4804
  this.itemClicked = output();
4872
4805
  this.activeRoutes = new Map();
4873
4806
  this.chevronClass = yuwSidebarMenuChevronClass;
4874
- this.flyoutLabelClass = yuwSidebarFlyoutLabelClass;
4875
4807
  this.badgeClass = yuwSidebarMenuBadgeClass;
4876
4808
  this.groupLabelTextClass = yuwSidebarGroupLabelTextClass;
4877
- this.caretRightBorderClasses = CARET_RIGHT_BORDER_CLASSES;
4878
4809
  this.isRail = computed(() => this.collapsible() === 'icon' && !this.sidebarService.isMobile() && this.rail.railSettled(), ...(ngDevMode ? [{ debugName: "isRail" }] : /* istanbul ignore next */ []));
4879
4810
  this.expandedIds = linkedSignal({ ...(ngDevMode ? { debugName: "expandedIds" } : /* istanbul ignore next */ {}), source: () => ({ content: this.content(), rail: this.isRail() }),
4880
4811
  computation: ({ content, rail }, previous) => rail || previous
@@ -4896,7 +4827,7 @@ class YuwSidebarNavComponent {
4896
4827
  ...item,
4897
4828
  children,
4898
4829
  hasChildren,
4899
- tooltipText: hasChildren ? null : (item.tooltip ?? item.label),
4830
+ tooltipText: item.tooltip ?? item.label,
4900
4831
  activeOptions: { exact: item.exact ?? false },
4901
4832
  expanded,
4902
4833
  submenuClass: `${yuwSidebarSubmenuWrapperClass} ${expanded ? yuwSidebarSubmenuOpenClass : yuwSidebarSubmenuClosedClass}`,
@@ -4923,20 +4854,24 @@ class YuwSidebarNavComponent {
4923
4854
  onItemClick(id, event) {
4924
4855
  this.itemClicked.emit({ id, event });
4925
4856
  }
4926
- onParentClick(id, expanded) {
4927
- if (this.isRail())
4857
+ onParentClick(item, expanded, event) {
4858
+ if (!(item.children?.length ?? 0))
4859
+ return;
4860
+ if (this.isRail()) {
4861
+ this.submenu.toggle(item, event);
4928
4862
  return;
4863
+ }
4929
4864
  this.expandedIds.update((ids) => {
4930
4865
  const next = new Set(ids);
4931
4866
  if (expanded)
4932
- next.delete(id);
4867
+ next.delete(item.id);
4933
4868
  else
4934
- next.add(id);
4869
+ next.add(item.id);
4935
4870
  return next;
4936
4871
  });
4937
4872
  }
4938
4873
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4939
- 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 yuwSidebarFlyoutHost>\n <ng-template yuwSidebarFlyoutPanel #panel>\n <div yuwSidebarFlyout>\n <span [class]=\"flyoutLabelClass\">{{ item.label }}</span>\n <ng-container [ngTemplateOutlet]=\"submenu\" [ngTemplateOutletContext]=\"{ $implicit: item }\" />\n </div>\n </ng-template>\n\n @if (item.route) {\n <a\n yuwSidebarMenuButton\n closeMobileSidebarOnClick\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 [yuwSidebarFlyoutTrigger]=\"item.hasChildren && isRail() ? panel : undefined\"\n align=\"right\"\n [sideOffset]=\"0\"\n [showDelay]=\"120\"\n [hideDelay]=\"300\"\n (click)=\"onParentClick(item.id, 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\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 [yuwSidebarFlyoutTrigger]=\"item.hasChildren && isRail() ? panel : undefined\"\n align=\"right\"\n [sideOffset]=\"0\"\n [showDelay]=\"120\"\n [hideDelay]=\"300\"\n (click)=\"onParentClick(item.id, 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\n type=\"button\"\n [tooltip]=\"item.tooltipText\"\n [disabled]=\"item.disabled ?? false\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [yuwSidebarFlyoutTrigger]=\"item.hasChildren && isRail() ? panel : undefined\"\n align=\"right\"\n [sideOffset]=\"0\"\n [showDelay]=\"120\"\n [hideDelay]=\"300\"\n (click)=\"item.hasChildren ? onParentClick(item.id, 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 <div\n [class]=\"caretRightBorderClasses\"\n [class.opacity-100]=\"isRail()\"\n [class.opacity-0]=\"!isRail()\"\n ></div>\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" }, { kind: "directive", type: YuwSidebarFlyoutHostDirective, selector: "[yuwSidebarFlyoutHost]" }, { kind: "directive", type: YuwSidebarFlyoutPanelDirective, selector: "ng-template[yuwSidebarFlyoutPanel]" }, { kind: "directive", type: YuwSidebarFlyoutTriggerDirective, selector: "[yuwSidebarFlyoutTrigger]", inputs: ["yuwSidebarFlyoutTrigger", "align", "sideOffset", "showDelay", "hideDelay"] }, { kind: "directive", type: YuwSidebarFlyoutDirective, selector: "[yuwSidebarFlyout]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4874
+ 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, $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 </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, $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 </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, $event) : 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 }); }
4940
4875
  }
4941
4876
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarNavComponent, decorators: [{
4942
4877
  type: Component,
@@ -4957,15 +4892,78 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
4957
4892
  YuwSidebarMenuSubItemDirective,
4958
4893
  YuwSidebarMenuSubButtonDirective,
4959
4894
  YuwSidebarSeparatorDirective,
4960
- YuwSidebarFlyoutHostDirective,
4961
- YuwSidebarFlyoutPanelDirective,
4962
- YuwSidebarFlyoutTriggerDirective,
4963
- YuwSidebarFlyoutDirective,
4964
4895
  ], providers: [provideIcons({ lucideChevronRight })], host: {
4965
4896
  class: 'contents',
4966
- }, 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 yuwSidebarFlyoutHost>\n <ng-template yuwSidebarFlyoutPanel #panel>\n <div yuwSidebarFlyout>\n <span [class]=\"flyoutLabelClass\">{{ item.label }}</span>\n <ng-container [ngTemplateOutlet]=\"submenu\" [ngTemplateOutletContext]=\"{ $implicit: item }\" />\n </div>\n </ng-template>\n\n @if (item.route) {\n <a\n yuwSidebarMenuButton\n closeMobileSidebarOnClick\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 [yuwSidebarFlyoutTrigger]=\"item.hasChildren && isRail() ? panel : undefined\"\n align=\"right\"\n [sideOffset]=\"0\"\n [showDelay]=\"120\"\n [hideDelay]=\"300\"\n (click)=\"onParentClick(item.id, 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\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 [yuwSidebarFlyoutTrigger]=\"item.hasChildren && isRail() ? panel : undefined\"\n align=\"right\"\n [sideOffset]=\"0\"\n [showDelay]=\"120\"\n [hideDelay]=\"300\"\n (click)=\"onParentClick(item.id, 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\n type=\"button\"\n [tooltip]=\"item.tooltipText\"\n [disabled]=\"item.disabled ?? false\"\n [attr.aria-expanded]=\"item.hasChildren ? item.expanded : null\"\n [yuwSidebarFlyoutTrigger]=\"item.hasChildren && isRail() ? panel : undefined\"\n align=\"right\"\n [sideOffset]=\"0\"\n [showDelay]=\"120\"\n [hideDelay]=\"300\"\n (click)=\"item.hasChildren ? onParentClick(item.id, 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 <div\n [class]=\"caretRightBorderClasses\"\n [class.opacity-100]=\"isRail()\"\n [class.opacity-0]=\"!isRail()\"\n ></div>\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" }]
4897
+ }, 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, $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 </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, $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 </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, $event) : 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" }]
4967
4898
  }], 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"] }] } });
4968
4899
 
4900
+ /**
4901
+ * The one submenu panel of a collapsed sidebar, showing whatever `YuwSidebarSubmenuService` holds.
4902
+ * Lives here rather than in `YuwSidebarNavComponent`, which `<yuw-sidebar>` instantiates twice.
4903
+ *
4904
+ * The rail width is re-declared as `--yuw-sidebar-rail-width` on the CDK overlay *container*: the
4905
+ * overlay is portalled out of the wrapper that owns `--sidebar-width-icon`, and the panel and
4906
+ * backdrop are siblings there that both need it. It is read off the live wrapper because
4907
+ * `[sidebarWidthIcon]` overrides the config without writing back to it.
4908
+ *
4909
+ * Not `aria-modal`, and scroll is left alone: the rail stays live behind the dim.
4910
+ */
4911
+ class YuwSidebarSubmenuSheetComponent {
4912
+ constructor() {
4913
+ this.config = injectHlmSidebarConfig();
4914
+ this.rail = inject(YuwSidebarRailService);
4915
+ this.host = inject(ElementRef);
4916
+ this.overlayContainer = inject(OverlayContainer);
4917
+ this._submenu = inject(YuwSidebarSubmenuService);
4918
+ this.itemClicked = output();
4919
+ this.panelClass = yuwSidebarSubmenuSheetClass;
4920
+ this.overlayClass = yuwSidebarSubmenuOverlayClass;
4921
+ this.bodyClass = yuwSidebarSubmenuSheetBodyClass;
4922
+ this.labelClass = yuwSidebarSubmenuSheetLabelClass;
4923
+ this._item = this._submenu.renderedItem;
4924
+ this._activeOptions = computed(() => Object.fromEntries((this._item()?.children ?? []).map((child) => [child.id, { exact: child.exact ?? false }])), ...(ngDevMode ? [{ debugName: "_activeOptions" }] : /* istanbul ignore next */ []));
4925
+ effect(() => {
4926
+ if (this.rail.railSettled())
4927
+ return;
4928
+ this._submenu.close();
4929
+ });
4930
+ effect(() => {
4931
+ if (!this._submenu.open())
4932
+ return;
4933
+ this.overlayContainer.getContainerElement().style.setProperty(YUW_SIDEBAR_RAIL_WIDTH_VAR, this.railWidth());
4934
+ });
4935
+ }
4936
+ railWidth() {
4937
+ const wrapper = this.host.nativeElement.closest('[data-slot=sidebar-wrapper]');
4938
+ const resolved = wrapper ? getComputedStyle(wrapper).getPropertyValue('--sidebar-width-icon').trim() : '';
4939
+ return resolved || this.config.sidebarWidthIcon;
4940
+ }
4941
+ onOpenChange(open) {
4942
+ if (open)
4943
+ return;
4944
+ this._submenu.close();
4945
+ }
4946
+ onChildClick(id, event) {
4947
+ this._submenu.close();
4948
+ this.itemClicked.emit({ id, event });
4949
+ }
4950
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4951
+ 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 }); }
4952
+ }
4953
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarSubmenuSheetComponent, decorators: [{
4954
+ type: Component,
4955
+ args: [{ selector: 'yuw-sidebar-submenu-sheet', imports: [
4956
+ YuwSheetComponent,
4957
+ RouterLink,
4958
+ RouterLinkActive,
4959
+ YuwSidebarMenuSubDirective,
4960
+ YuwSidebarMenuSubItemDirective,
4961
+ YuwSidebarMenuSubButtonDirective,
4962
+ ], host: {
4963
+ class: 'contents',
4964
+ }, 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" }]
4965
+ }], ctorParameters: () => [], propDecorators: { itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
4966
+
4969
4967
  /**
4970
4968
  * Collapsible navigation sidebar. Renders as a fixed panel on desktop and as a slide-in sheet on
4971
4969
  * mobile, and reads its colors from the `--sidebar-*` theme tokens.
@@ -4985,8 +4983,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
4985
4983
  * `[routerLink]` anchor whose active state, `aria-current` and pointer-lock resolve automatically
4986
4984
  * from `routerLinkActive`; one with an `href` becomes a plain anchor; one with neither becomes a
4987
4985
  * button that reports through `itemClicked`. An item with `children` gets a submenu that follows
4988
- * the sidebar's own state: an accordion while the panel is open, and a hover flyout to the side
4989
- * once it is collapsed to icons, so nested entries stay reachable from the rail. Its `expanded`
4986
+ * the sidebar's own state: an accordion while the panel is open, and a sheet sliding out beside the
4987
+ * rail once it is collapsed to icons, so nested entries stay reachable there. Its `expanded`
4990
4988
  * field seeds the accordion; the item holding the active route opens on its own.
4991
4989
  * - `footer`: The same, rendered into the footer region.
4992
4990
  *
@@ -5008,6 +5006,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
5008
5006
  * content area's flex sizing — mark it `[yuwSidebarContentExtra]` or `[yuwSidebarFooterExtra]`; the
5009
5007
  * default slot keeps everything else, so existing projection-only usage is unaffected.
5010
5008
  *
5009
+ * With `collapsible="icon"` the component also renders a single submenu sheet, shared by every entry
5010
+ * that has `children` in either region. It is one panel rather than one per entry because a sheet is a
5011
+ * modal overlay: several would compete for the same screen position, and only one submenu is ever on
5012
+ * screen anyway.
5013
+ *
5011
5014
  * `header` has no object form: it is a free-form branding area with no repeating structure to model.
5012
5015
  *
5013
5016
  * Deliberately not exposed from the helm sidebar (add a wrapper only when a real consumer needs
@@ -5053,6 +5056,7 @@ class YuwSidebarComponent {
5053
5056
  constructor() {
5054
5057
  this.config = injectHlmSidebarConfig();
5055
5058
  this._rail = inject(YuwSidebarRailService);
5059
+ this._submenu = inject(YuwSidebarSubmenuService);
5056
5060
  this.side = input('left', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
5057
5061
  this.variant = input('sidebar', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
5058
5062
  this.collapsible = input('offcanvas', ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
@@ -5067,19 +5071,21 @@ class YuwSidebarComponent {
5067
5071
  this.railSettledChange = outputFromObservable(toObservable(this._rail.railSettled).pipe(distinctUntilChanged()));
5068
5072
  }
5069
5073
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5070
- 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 }); }
5074
+ 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: { listeners: { "click": "_submenu.closeUnhandled($event)" }, 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 }); }
5071
5075
  }
5072
5076
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: YuwSidebarComponent, decorators: [{
5073
5077
  type: Component,
5074
5078
  args: [{ selector: 'yuw-sidebar', imports: [
5075
5079
  HlmSidebar,
5076
5080
  YuwSidebarNavComponent,
5081
+ YuwSidebarSubmenuSheetComponent,
5077
5082
  YuwSidebarContentDirective,
5078
5083
  YuwSidebarFooterDirective,
5079
5084
  YuwSidebarSeparatorDirective,
5080
5085
  ], host: {
5081
5086
  class: 'contents',
5082
- }, 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" }]
5087
+ '(click)': '_submenu.closeUnhandled($event)',
5088
+ }, 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" }]
5083
5089
  }], 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"] }] } });
5084
5090
 
5085
5091
  /**
@@ -5117,5 +5123,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
5117
5123
  * Generated bundle index. Do not edit.
5118
5124
  */
5119
5125
 
5120
- 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, YuwSidebarFlyoutDirective, YuwSidebarFlyoutHostDirective, YuwSidebarFlyoutPanelDirective, YuwSidebarFlyoutTriggerDirective, YuwSidebarFooterDirective, YuwSidebarFooterExtraDirective, YuwSidebarGroupContentDirective, YuwSidebarGroupDirective, YuwSidebarGroupLabelDirective, YuwSidebarHeaderDirective, YuwSidebarInsetDirective, YuwSidebarMenuBadgeDirective, YuwSidebarMenuButtonDirective, YuwSidebarMenuDirective, YuwSidebarMenuItemDirective, YuwSidebarMenuSubButtonDirective, YuwSidebarMenuSubDirective, YuwSidebarMenuSubItemDirective, YuwSidebarRailDirective, YuwSidebarRailService, YuwSidebarSeparatorDirective, 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 };
5126
+ 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 };
5121
5127
  //# sourceMappingURL=yukit-web.mjs.map