@crowdfarming/oliva-ds 1.28.2 → 1.29.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,8 @@ import * as i1 from '@angular/platform-browser';
6
6
  import * as i1$2 from '@angular/forms';
7
7
  import { NG_VALUE_ACCESSOR, ReactiveFormsModule, FormControl, FormsModule } from '@angular/forms';
8
8
  import { TemplatePortal, DomPortalOutlet, PortalModule, ComponentPortal } from '@angular/cdk/portal';
9
- import { RouterLink } from '@angular/router';
9
+ import { FocusTrapFactory } from '@angular/cdk/a11y';
10
+ import { Router, NavigationStart, RouterLink } from '@angular/router';
10
11
  import * as i1$3 from '@angular/cdk/overlay';
11
12
 
12
13
  // Auto-generated icons from Figma
@@ -2484,8 +2485,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
2484
2485
 
2485
2486
  class AlertComponent {
2486
2487
  variant = input('neutral');
2487
- text = input('');
2488
2488
  title = input('');
2489
+ text = input('');
2489
2490
  extraClass = input('');
2490
2491
  showIcon = input(true);
2491
2492
  removable = input(true);
@@ -2524,11 +2525,11 @@ class AlertComponent {
2524
2525
  }
2525
2526
  }
2526
2527
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2527
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: AlertComponent, isStandalone: true, selector: "lib-alert", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, extraClass: { classPropertyName: "extraClass", publicName: "extraClass", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (visibility) {\n<div\n role=\"alert\"\n [ngClass]=\"[\n 'c-alert',\n variant() ? 'c-alert--' + variant() : '',\n extraClass() ? extraClass() : '',\n closeActive ? 'c-alert--hide' : ''\n ]\"\n>\n @if (showIcon()) {\n <lib-icon [name]=\"getIconName()\" [color]=\"getIconColor()\" size=\"lg\" />\n }\n\n <div class=\"c-alert__content\">\n <p class=\"c-alert__title\">{{ title() }}</p>\n <p class=\"c-alert__text\">{{ text() }}</p>\n </div>\n\n @if (removable()) {\n <lib-button-icon\n role=\"button\"\n [ariaLabel]=\"variant()\"\n [loading]=\"false\"\n variant=\"neutral\"\n size=\"sm\"\n class=\"c-alert__close\"\n iconName=\"x-regular\"\n (click)=\"close()\"\n />\n }\n</div>\n}\n", styles: [".c-alert{width:100%;width:-moz-available;width:-webkit-fill-available;width:stretch;padding:var(--space-component-padding-md);border-radius:var(--size-textfield-border-radius);border:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-surface-raised);display:flex;align-items:flex-start;gap:var(--space-component-gap-md)}.c-alert--danger{border-color:var(--color-feedback-danger-surface-border);background:var(--color-feedback-danger-surface-background)}.c-alert--success{border-color:var(--color-feedback-success-surface-border);background:var(--color-feedback-success-surface-background)}.c-alert--warning{border-color:var(--color-feedback-warning-surface-border);background:var(--color-feedback-warning-surface-background)}.c-alert--info{border-color:var(--color-feedback-info-surface-border);background:var(--color-feedback-info-surface-background)}.c-alert--neutral{border-color:var(--color-core-border-default);background:var(--color-core-background-neutral-soft)}.c-alert__content{display:flex;flex:1;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:var(--space-component-gap-sm)}.c-alert__close{justify-self:flex-end;margin:0 0 0 auto}.c-alert__title{color:var(--color-core-content-default);font-family:var(--typography-title-sm-family);font-size:var(--typography-title-sm-size);font-style:normal;font-weight:var(--typography-title-sm-weight);line-height:var(--typography-title-sm-line-height);letter-spacing:var(--typography-title-sm-letter-spacing);margin:0 0 auto}.c-alert__text{color:var(--color-core-content-soft);font-family:var(--typography-body-sm-family);font-size:var(--typography-body-sm-size);font-style:normal;font-weight:var(--typography-body-sm-weight);line-height:var(--typography-body-sm-line-height);letter-spacing:var(--typography-body-sm-letter-spacing);margin:0 0 auto}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: IconComponent, selector: "lib-icon", inputs: ["size", "icon", "name", "color"] }, { kind: "component", type: ButtonIconComponent, selector: "lib-button-icon", inputs: ["ariaLabel", "variant", "size", "iconName", "disabled", "loading", "skeletonActive"], outputs: ["clicked"] }] });
2528
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: AlertComponent, isStandalone: true, selector: "lib-alert", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: false, transformFunction: null }, extraClass: { classPropertyName: "extraClass", publicName: "extraClass", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (visibility) {\n<div\n role=\"alert\"\n [ngClass]=\"[\n 'c-alert',\n variant() ? 'c-alert--' + variant() : '',\n extraClass() ? extraClass() : '',\n closeActive ? 'c-alert--hide' : ''\n ]\"\n>\n @if (showIcon()) {\n <lib-icon [name]=\"getIconName()\" [color]=\"getIconColor()\" size=\"lg\" />\n }\n\n <div class=\"c-alert__content\">\n @if (title()) {\n <p class=\"c-alert__title\">{{ title() }}</p>\n } @if (text()) {\n <p class=\"c-alert__text\">{{ text() }}</p>\n }\n </div>\n\n @if (removable()) {\n <lib-button-icon\n role=\"button\"\n [ariaLabel]=\"variant()\"\n [loading]=\"false\"\n variant=\"neutral\"\n size=\"sm\"\n class=\"c-alert__close\"\n iconName=\"x-regular\"\n (click)=\"close()\"\n />\n }\n</div>\n}\n", styles: [".c-alert{width:100%;width:-moz-available;width:-webkit-fill-available;width:stretch;padding:var(--space-component-padding-md);border-radius:var(--size-textfield-border-radius);border:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-surface-raised);display:flex;align-items:flex-start;gap:var(--space-component-gap-md)}.c-alert--danger{border-color:var(--color-feedback-danger-surface-border);background:var(--color-feedback-danger-surface-background)}.c-alert--success{border-color:var(--color-feedback-success-surface-border);background:var(--color-feedback-success-surface-background)}.c-alert--warning{border-color:var(--color-feedback-warning-surface-border);background:var(--color-feedback-warning-surface-background)}.c-alert--info{border-color:var(--color-feedback-info-surface-border);background:var(--color-feedback-info-surface-background)}.c-alert--neutral{border-color:var(--color-core-border-default);background:var(--color-core-background-neutral-soft)}.c-alert__content{display:flex;flex:1;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:var(--space-component-gap-sm)}.c-alert__close{justify-self:flex-end;margin:0 0 0 auto}.c-alert__title{color:var(--color-core-content-default);font-family:var(--typography-title-sm-family);font-size:var(--typography-title-sm-size);font-style:normal;font-weight:var(--typography-title-sm-weight);line-height:var(--typography-title-sm-line-height);letter-spacing:var(--typography-title-sm-letter-spacing);margin:0 0 auto}.c-alert__text{color:var(--color-core-content-soft);font-family:var(--typography-body-sm-family);font-size:var(--typography-body-sm-size);font-style:normal;font-weight:var(--typography-body-sm-weight);line-height:var(--typography-body-sm-line-height);letter-spacing:var(--typography-body-sm-letter-spacing);margin:0 0 auto}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: IconComponent, selector: "lib-icon", inputs: ["size", "icon", "name", "color"] }, { kind: "component", type: ButtonIconComponent, selector: "lib-button-icon", inputs: ["ariaLabel", "variant", "size", "iconName", "disabled", "loading", "skeletonActive"], outputs: ["clicked"] }] });
2528
2529
  }
2529
2530
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: AlertComponent, decorators: [{
2530
2531
  type: Component,
2531
- args: [{ selector: 'lib-alert', imports: [NgClass, IconComponent, ButtonIconComponent], template: "@if (visibility) {\n<div\n role=\"alert\"\n [ngClass]=\"[\n 'c-alert',\n variant() ? 'c-alert--' + variant() : '',\n extraClass() ? extraClass() : '',\n closeActive ? 'c-alert--hide' : ''\n ]\"\n>\n @if (showIcon()) {\n <lib-icon [name]=\"getIconName()\" [color]=\"getIconColor()\" size=\"lg\" />\n }\n\n <div class=\"c-alert__content\">\n <p class=\"c-alert__title\">{{ title() }}</p>\n <p class=\"c-alert__text\">{{ text() }}</p>\n </div>\n\n @if (removable()) {\n <lib-button-icon\n role=\"button\"\n [ariaLabel]=\"variant()\"\n [loading]=\"false\"\n variant=\"neutral\"\n size=\"sm\"\n class=\"c-alert__close\"\n iconName=\"x-regular\"\n (click)=\"close()\"\n />\n }\n</div>\n}\n", styles: [".c-alert{width:100%;width:-moz-available;width:-webkit-fill-available;width:stretch;padding:var(--space-component-padding-md);border-radius:var(--size-textfield-border-radius);border:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-surface-raised);display:flex;align-items:flex-start;gap:var(--space-component-gap-md)}.c-alert--danger{border-color:var(--color-feedback-danger-surface-border);background:var(--color-feedback-danger-surface-background)}.c-alert--success{border-color:var(--color-feedback-success-surface-border);background:var(--color-feedback-success-surface-background)}.c-alert--warning{border-color:var(--color-feedback-warning-surface-border);background:var(--color-feedback-warning-surface-background)}.c-alert--info{border-color:var(--color-feedback-info-surface-border);background:var(--color-feedback-info-surface-background)}.c-alert--neutral{border-color:var(--color-core-border-default);background:var(--color-core-background-neutral-soft)}.c-alert__content{display:flex;flex:1;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:var(--space-component-gap-sm)}.c-alert__close{justify-self:flex-end;margin:0 0 0 auto}.c-alert__title{color:var(--color-core-content-default);font-family:var(--typography-title-sm-family);font-size:var(--typography-title-sm-size);font-style:normal;font-weight:var(--typography-title-sm-weight);line-height:var(--typography-title-sm-line-height);letter-spacing:var(--typography-title-sm-letter-spacing);margin:0 0 auto}.c-alert__text{color:var(--color-core-content-soft);font-family:var(--typography-body-sm-family);font-size:var(--typography-body-sm-size);font-style:normal;font-weight:var(--typography-body-sm-weight);line-height:var(--typography-body-sm-line-height);letter-spacing:var(--typography-body-sm-letter-spacing);margin:0 0 auto}\n"] }]
2532
+ args: [{ selector: 'lib-alert', imports: [NgClass, IconComponent, ButtonIconComponent], template: "@if (visibility) {\n<div\n role=\"alert\"\n [ngClass]=\"[\n 'c-alert',\n variant() ? 'c-alert--' + variant() : '',\n extraClass() ? extraClass() : '',\n closeActive ? 'c-alert--hide' : ''\n ]\"\n>\n @if (showIcon()) {\n <lib-icon [name]=\"getIconName()\" [color]=\"getIconColor()\" size=\"lg\" />\n }\n\n <div class=\"c-alert__content\">\n @if (title()) {\n <p class=\"c-alert__title\">{{ title() }}</p>\n } @if (text()) {\n <p class=\"c-alert__text\">{{ text() }}</p>\n }\n </div>\n\n @if (removable()) {\n <lib-button-icon\n role=\"button\"\n [ariaLabel]=\"variant()\"\n [loading]=\"false\"\n variant=\"neutral\"\n size=\"sm\"\n class=\"c-alert__close\"\n iconName=\"x-regular\"\n (click)=\"close()\"\n />\n }\n</div>\n}\n", styles: [".c-alert{width:100%;width:-moz-available;width:-webkit-fill-available;width:stretch;padding:var(--space-component-padding-md);border-radius:var(--size-textfield-border-radius);border:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-surface-raised);display:flex;align-items:flex-start;gap:var(--space-component-gap-md)}.c-alert--danger{border-color:var(--color-feedback-danger-surface-border);background:var(--color-feedback-danger-surface-background)}.c-alert--success{border-color:var(--color-feedback-success-surface-border);background:var(--color-feedback-success-surface-background)}.c-alert--warning{border-color:var(--color-feedback-warning-surface-border);background:var(--color-feedback-warning-surface-background)}.c-alert--info{border-color:var(--color-feedback-info-surface-border);background:var(--color-feedback-info-surface-background)}.c-alert--neutral{border-color:var(--color-core-border-default);background:var(--color-core-background-neutral-soft)}.c-alert__content{display:flex;flex:1;flex-direction:column;align-items:flex-start;justify-content:flex-start;gap:var(--space-component-gap-sm)}.c-alert__close{justify-self:flex-end;margin:0 0 0 auto}.c-alert__title{color:var(--color-core-content-default);font-family:var(--typography-title-sm-family);font-size:var(--typography-title-sm-size);font-style:normal;font-weight:var(--typography-title-sm-weight);line-height:var(--typography-title-sm-line-height);letter-spacing:var(--typography-title-sm-letter-spacing);margin:0 0 auto}.c-alert__text{color:var(--color-core-content-soft);font-family:var(--typography-body-sm-family);font-size:var(--typography-body-sm-size);font-style:normal;font-weight:var(--typography-body-sm-weight);line-height:var(--typography-body-sm-line-height);letter-spacing:var(--typography-body-sm-letter-spacing);margin:0 0 auto}\n"] }]
2532
2533
  }] });
2533
2534
 
2534
2535
  class ArrowsComponent {
@@ -2957,7 +2958,7 @@ class CheckboxComponent {
2957
2958
  useExisting: forwardRef(() => CheckboxComponent),
2958
2959
  multi: true,
2959
2960
  },
2960
- ], ngImport: i0, template: "<div [ngClass]=\"classes()\" class=\"c-checkbox\">\n <div class=\"c-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [id]=\"name()\"\n [ngClass]=\"inputClasses()\"\n [checked]=\"isChecked()\"\n [indeterminate]=\"isIndeterminate()\"\n [disabled]=\"isDisabled()\"\n [name]=\"name()\"\n [value]=\"value()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-checked]=\"ariaChecked()\"\n (change)=\"handleChange($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n </div>\n @if(isSkeleton()) {\n <div class=\"c-checkbox__label__skeleton\">\n <span></span>\n </div>\n } @else { @if(label()) {\n <lib-input-label\n size=\"md\"\n [text]=\"label()\"\n [disabled]=\"disabled()\"\n [required]=\"true\"\n [for]=\"name()\"\n [innerHTML]=\"innerHTML()\"\n ></lib-input-label>\n } }\n</div>\n", styles: [".c-checkbox{display:flex;align-items:flex-start;gap:var(--space-component-gap-sm)}.c-checkbox__input-wrapper{height:var(--typography-label-md-default-line-height);display:flex;align-items:center}.c-checkbox__label{cursor:pointer}.c-checkbox__label__skeleton{width:64px;height:24px;display:flex;align-items:center}.c-checkbox__label__skeleton span{width:100%;height:8px;background-color:var(--color-effect-skeleton-default);border-radius:var(--size-border-radius-sm, 4px)}.c-checkbox--skeleton .c-checkbox__label{cursor:default;pointer-events:none}.c-checkbox input[type=checkbox]{-webkit-appearance:none;appearance:none;width:18px;height:18px;border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-default, #929a99);background-color:var(--color-textfield-background-default);border-radius:var(--size-border-radius-sm, 4px);display:grid;place-content:center;cursor:pointer}.c-checkbox input[type=checkbox]:hover{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-hover, #7d8483)}.c-checkbox input[type=checkbox]:not(:disabled):not(.c-checkbox__input--skeleton):focus-visible{box-shadow:var(--focus-outset);outline:none}.c-checkbox input[type=checkbox].c-checkbox__input--error{border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox].c-checkbox__input--error:checked,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate,.c-checkbox input[type=checkbox].c-checkbox__input--error:checked:hover,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate:hover{background-color:var(--color-feedback-danger-default, #ba2f1e);border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox]:checked,.c-checkbox input[type=checkbox]:indeterminate{border-color:var(--color-action-primary-selected-background-default, #217870);background-color:var(--color-action-primary-selected-background-default, #217870)}.c-checkbox input[type=checkbox]:checked:hover,.c-checkbox input[type=checkbox]:indeterminate:hover{background-color:var(--color-action-primary-selected-background-hover, #19625b);border-color:var(--color-action-primary-selected-background-hover, #19625b)}.c-checkbox input[type=checkbox]:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:disabled+.c-checkbox__label{pointer-events:none;cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:disabled,.c-checkbox input[type=checkbox]:indeterminate:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0%,43% 62%)}.c-checkbox input[type=checkbox]:indeterminate:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(0% 38%,100% 38%,100% 62%,0 62%)}.c-checkbox input[type=checkbox]:checked:disabled:before,.c-checkbox input[type=checkbox]:indeterminate:disabled:before{box-shadow:inset 1em 1em #7d8483}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton{border-color:var(--color-effect-skeleton-soft);background-color:var(--color-textfield-background-disabled);cursor:not-allowed;pointer-events:none}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton:before{content:none!important}.c-checkbox ::ng-deep lib-input-label span{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: InputLabelComponent, selector: "lib-input-label", inputs: ["text", "required", "size", "disabled", "for", "innerHTML"] }] });
2961
+ ], ngImport: i0, template: "<div [ngClass]=\"classes()\" class=\"c-checkbox\">\n <div class=\"c-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [id]=\"name()\"\n [ngClass]=\"inputClasses()\"\n [checked]=\"isChecked()\"\n [indeterminate]=\"isIndeterminate()\"\n [disabled]=\"isDisabled()\"\n [name]=\"name()\"\n [value]=\"value()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-checked]=\"ariaChecked()\"\n (change)=\"handleChange($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n </div>\n @if(isSkeleton()) {\n <div class=\"c-checkbox__label__skeleton\">\n <span></span>\n </div>\n } @else { @if(label() || innerHTML()) {\n <lib-input-label\n size=\"md\"\n [text]=\"label()\"\n [disabled]=\"disabled()\"\n [required]=\"true\"\n [for]=\"name()\"\n [innerHTML]=\"innerHTML()\"\n ></lib-input-label>\n } }\n</div>\n", styles: [".c-checkbox{display:flex;align-items:flex-start;gap:var(--space-component-gap-sm)}.c-checkbox__input-wrapper{height:var(--typography-label-md-default-line-height);display:flex;align-items:center}.c-checkbox__label{cursor:pointer}.c-checkbox__label__skeleton{width:64px;height:24px;display:flex;align-items:center}.c-checkbox__label__skeleton span{width:100%;height:8px;background-color:var(--color-effect-skeleton-default);border-radius:var(--size-border-radius-sm, 4px)}.c-checkbox--skeleton .c-checkbox__label{cursor:default;pointer-events:none}.c-checkbox input[type=checkbox]{-webkit-appearance:none;appearance:none;width:18px;height:18px;border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-default, #929a99);background-color:var(--color-textfield-background-default);border-radius:var(--size-border-radius-sm, 4px);display:grid;place-content:center;cursor:pointer}.c-checkbox input[type=checkbox]:hover{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-hover, #7d8483)}.c-checkbox input[type=checkbox]:not(:disabled):not(.c-checkbox__input--skeleton):focus-visible{box-shadow:var(--focus-outset);outline:none}.c-checkbox input[type=checkbox].c-checkbox__input--error{border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox].c-checkbox__input--error:checked,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate,.c-checkbox input[type=checkbox].c-checkbox__input--error:checked:hover,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate:hover{background-color:var(--color-feedback-danger-default, #ba2f1e);border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox]:checked,.c-checkbox input[type=checkbox]:indeterminate{border-color:var(--color-action-primary-selected-background-default, #217870);background-color:var(--color-action-primary-selected-background-default, #217870)}.c-checkbox input[type=checkbox]:checked:hover,.c-checkbox input[type=checkbox]:indeterminate:hover{background-color:var(--color-action-primary-selected-background-hover, #19625b);border-color:var(--color-action-primary-selected-background-hover, #19625b)}.c-checkbox input[type=checkbox]:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:disabled+.c-checkbox__label{pointer-events:none;cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:disabled,.c-checkbox input[type=checkbox]:indeterminate:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0%,43% 62%)}.c-checkbox input[type=checkbox]:indeterminate:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(0% 38%,100% 38%,100% 62%,0 62%)}.c-checkbox input[type=checkbox]:checked:disabled:before,.c-checkbox input[type=checkbox]:indeterminate:disabled:before{box-shadow:inset 1em 1em #7d8483}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton{border-color:var(--color-effect-skeleton-soft);background-color:var(--color-textfield-background-disabled);cursor:not-allowed;pointer-events:none}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton:before{content:none!important}.c-checkbox ::ng-deep lib-input-label span{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: InputLabelComponent, selector: "lib-input-label", inputs: ["text", "required", "size", "disabled", "for", "innerHTML"] }] });
2961
2962
  }
2962
2963
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: CheckboxComponent, decorators: [{
2963
2964
  type: Component,
@@ -2967,7 +2968,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
2967
2968
  useExisting: forwardRef(() => CheckboxComponent),
2968
2969
  multi: true,
2969
2970
  },
2970
- ], template: "<div [ngClass]=\"classes()\" class=\"c-checkbox\">\n <div class=\"c-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [id]=\"name()\"\n [ngClass]=\"inputClasses()\"\n [checked]=\"isChecked()\"\n [indeterminate]=\"isIndeterminate()\"\n [disabled]=\"isDisabled()\"\n [name]=\"name()\"\n [value]=\"value()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-checked]=\"ariaChecked()\"\n (change)=\"handleChange($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n </div>\n @if(isSkeleton()) {\n <div class=\"c-checkbox__label__skeleton\">\n <span></span>\n </div>\n } @else { @if(label()) {\n <lib-input-label\n size=\"md\"\n [text]=\"label()\"\n [disabled]=\"disabled()\"\n [required]=\"true\"\n [for]=\"name()\"\n [innerHTML]=\"innerHTML()\"\n ></lib-input-label>\n } }\n</div>\n", styles: [".c-checkbox{display:flex;align-items:flex-start;gap:var(--space-component-gap-sm)}.c-checkbox__input-wrapper{height:var(--typography-label-md-default-line-height);display:flex;align-items:center}.c-checkbox__label{cursor:pointer}.c-checkbox__label__skeleton{width:64px;height:24px;display:flex;align-items:center}.c-checkbox__label__skeleton span{width:100%;height:8px;background-color:var(--color-effect-skeleton-default);border-radius:var(--size-border-radius-sm, 4px)}.c-checkbox--skeleton .c-checkbox__label{cursor:default;pointer-events:none}.c-checkbox input[type=checkbox]{-webkit-appearance:none;appearance:none;width:18px;height:18px;border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-default, #929a99);background-color:var(--color-textfield-background-default);border-radius:var(--size-border-radius-sm, 4px);display:grid;place-content:center;cursor:pointer}.c-checkbox input[type=checkbox]:hover{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-hover, #7d8483)}.c-checkbox input[type=checkbox]:not(:disabled):not(.c-checkbox__input--skeleton):focus-visible{box-shadow:var(--focus-outset);outline:none}.c-checkbox input[type=checkbox].c-checkbox__input--error{border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox].c-checkbox__input--error:checked,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate,.c-checkbox input[type=checkbox].c-checkbox__input--error:checked:hover,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate:hover{background-color:var(--color-feedback-danger-default, #ba2f1e);border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox]:checked,.c-checkbox input[type=checkbox]:indeterminate{border-color:var(--color-action-primary-selected-background-default, #217870);background-color:var(--color-action-primary-selected-background-default, #217870)}.c-checkbox input[type=checkbox]:checked:hover,.c-checkbox input[type=checkbox]:indeterminate:hover{background-color:var(--color-action-primary-selected-background-hover, #19625b);border-color:var(--color-action-primary-selected-background-hover, #19625b)}.c-checkbox input[type=checkbox]:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:disabled+.c-checkbox__label{pointer-events:none;cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:disabled,.c-checkbox input[type=checkbox]:indeterminate:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0%,43% 62%)}.c-checkbox input[type=checkbox]:indeterminate:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(0% 38%,100% 38%,100% 62%,0 62%)}.c-checkbox input[type=checkbox]:checked:disabled:before,.c-checkbox input[type=checkbox]:indeterminate:disabled:before{box-shadow:inset 1em 1em #7d8483}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton{border-color:var(--color-effect-skeleton-soft);background-color:var(--color-textfield-background-disabled);cursor:not-allowed;pointer-events:none}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton:before{content:none!important}.c-checkbox ::ng-deep lib-input-label span{cursor:pointer}\n"] }]
2971
+ ], template: "<div [ngClass]=\"classes()\" class=\"c-checkbox\">\n <div class=\"c-checkbox__input-wrapper\">\n <input\n type=\"checkbox\"\n [id]=\"name()\"\n [ngClass]=\"inputClasses()\"\n [checked]=\"isChecked()\"\n [indeterminate]=\"isIndeterminate()\"\n [disabled]=\"isDisabled()\"\n [name]=\"name()\"\n [value]=\"value()\"\n [attr.aria-label]=\"computedAriaLabel()\"\n [attr.aria-checked]=\"ariaChecked()\"\n (change)=\"handleChange($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n </div>\n @if(isSkeleton()) {\n <div class=\"c-checkbox__label__skeleton\">\n <span></span>\n </div>\n } @else { @if(label() || innerHTML()) {\n <lib-input-label\n size=\"md\"\n [text]=\"label()\"\n [disabled]=\"disabled()\"\n [required]=\"true\"\n [for]=\"name()\"\n [innerHTML]=\"innerHTML()\"\n ></lib-input-label>\n } }\n</div>\n", styles: [".c-checkbox{display:flex;align-items:flex-start;gap:var(--space-component-gap-sm)}.c-checkbox__input-wrapper{height:var(--typography-label-md-default-line-height);display:flex;align-items:center}.c-checkbox__label{cursor:pointer}.c-checkbox__label__skeleton{width:64px;height:24px;display:flex;align-items:center}.c-checkbox__label__skeleton span{width:100%;height:8px;background-color:var(--color-effect-skeleton-default);border-radius:var(--size-border-radius-sm, 4px)}.c-checkbox--skeleton .c-checkbox__label{cursor:default;pointer-events:none}.c-checkbox input[type=checkbox]{-webkit-appearance:none;appearance:none;width:18px;height:18px;border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-default, #929a99);background-color:var(--color-textfield-background-default);border-radius:var(--size-border-radius-sm, 4px);display:grid;place-content:center;cursor:pointer}.c-checkbox input[type=checkbox]:hover{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-hover, #7d8483)}.c-checkbox input[type=checkbox]:not(:disabled):not(.c-checkbox__input--skeleton):focus-visible{box-shadow:var(--focus-outset);outline:none}.c-checkbox input[type=checkbox].c-checkbox__input--error{border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox].c-checkbox__input--error:checked,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate,.c-checkbox input[type=checkbox].c-checkbox__input--error:checked:hover,.c-checkbox input[type=checkbox].c-checkbox__input--error:indeterminate:hover{background-color:var(--color-feedback-danger-default, #ba2f1e);border-color:var(--color-feedback-danger-default, #ba2f1e)}.c-checkbox input[type=checkbox]:checked,.c-checkbox input[type=checkbox]:indeterminate{border-color:var(--color-action-primary-selected-background-default, #217870);background-color:var(--color-action-primary-selected-background-default, #217870)}.c-checkbox input[type=checkbox]:checked:hover,.c-checkbox input[type=checkbox]:indeterminate:hover{background-color:var(--color-action-primary-selected-background-hover, #19625b);border-color:var(--color-action-primary-selected-background-hover, #19625b)}.c-checkbox input[type=checkbox]:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:disabled+.c-checkbox__label{pointer-events:none;cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:disabled,.c-checkbox input[type=checkbox]:indeterminate:disabled{border:var(--size-border-width-md, 2px) solid var(--color-textfield-border-disabled, #a6b0af);background:var(--color-textfield-background-disabled, rgba(0, 0, 0, .02));cursor:not-allowed}.c-checkbox input[type=checkbox]:checked:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0%,43% 62%)}.c-checkbox input[type=checkbox]:indeterminate:before{content:\"\";width:10px;height:10px;transition:.12s transform ease-in-out;box-shadow:inset 1em 1em #fff;clip-path:polygon(0% 38%,100% 38%,100% 62%,0 62%)}.c-checkbox input[type=checkbox]:checked:disabled:before,.c-checkbox input[type=checkbox]:indeterminate:disabled:before{box-shadow:inset 1em 1em #7d8483}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton{border-color:var(--color-effect-skeleton-soft);background-color:var(--color-textfield-background-disabled);cursor:not-allowed;pointer-events:none}.c-checkbox input[type=checkbox].c-checkbox__input--skeleton:before{content:none!important}.c-checkbox ::ng-deep lib-input-label span{cursor:pointer}\n"] }]
2971
2972
  }], ctorParameters: () => [] });
2972
2973
 
2973
2974
  class HelperTextComponent {
@@ -3145,21 +3146,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
3145
3146
  }] });
3146
3147
 
3147
3148
  class OverlayComponent {
3148
- // Constants
3149
3149
  static MOBILE_BREAKPOINT = 768;
3150
3150
  static DROPDOWN_HEIGHT = 320;
3151
3151
  static DROPDOWN_GAP = 2;
3152
3152
  static VIEWPORT_MARGIN = 16;
3153
3153
  static ANIMATION_DURATION = 20;
3154
3154
  static DEFAULT_MENU_WIDTH = 200;
3155
- // Inputs
3156
3155
  position = input('right');
3157
3156
  disabled = input(false);
3158
3157
  width = input(`${OverlayComponent.DEFAULT_MENU_WIDTH}px`);
3159
- // Outputs
3160
3158
  opened = output();
3161
3159
  closed = output();
3162
- // Signals
3163
3160
  _isOpen = signal(false);
3164
3161
  _isClosing = signal(false);
3165
3162
  _isMobile = signal(false);
@@ -3168,12 +3165,10 @@ class OverlayComponent {
3168
3165
  left: 0,
3169
3166
  width: OverlayComponent.DEFAULT_MENU_WIDTH,
3170
3167
  });
3171
- // Computed
3172
3168
  isOpen = this._isOpen.asReadonly();
3173
3169
  isClosing = this._isClosing.asReadonly();
3174
3170
  getMenuClasses = computed(() => ['c-overlay__menu', `c-overlay__menu--${this.position()}`].join(' '));
3175
3171
  getMenuStyles = computed(() => {
3176
- // On mobile we don't apply position styles, it's handled with CSS
3177
3172
  if (this._isMobile()) {
3178
3173
  return {};
3179
3174
  }
@@ -3198,17 +3193,32 @@ class OverlayComponent {
3198
3193
  }
3199
3194
  return classes.join(' ');
3200
3195
  });
3201
- // Element refs
3202
3196
  elementRef = inject(ElementRef);
3203
3197
  viewContainerRef = inject(ViewContainerRef);
3204
3198
  applicationRef = inject(ApplicationRef);
3205
3199
  platformId = inject(PLATFORM_ID);
3206
3200
  destroyRef = inject(DestroyRef);
3201
+ focusTrapFactory = inject(FocusTrapFactory);
3202
+ router = inject(Router);
3203
+ // Portal and container management
3207
3204
  triggerButtonRef;
3208
3205
  portal;
3209
3206
  portalOutlet;
3210
3207
  portalContainer;
3208
+ boundPortalClickHandler;
3209
+ // Focus and accessibility management
3210
+ focusTrap;
3211
+ previouslyFocusedElement;
3212
+ triggerKeydownHandler;
3213
+ inertElements = [];
3214
+ escapeKeyHandler;
3215
+ // Scroll and navigation management
3211
3216
  originalBodyOverflow;
3217
+ navigationSub;
3218
+ // Helper to get the correct document context (important for Storybook)
3219
+ getDocument() {
3220
+ return this.elementRef.nativeElement.ownerDocument || document;
3221
+ }
3212
3222
  menuTemplate;
3213
3223
  contentTemplate;
3214
3224
  footerTemplate;
@@ -3223,20 +3233,32 @@ class OverlayComponent {
3223
3233
  else if (!this.isOpen() && !this.isClosing())
3224
3234
  this.closed.emit();
3225
3235
  });
3226
- // Cleanup when component is destroyed
3227
3236
  this.destroyRef.onDestroy(() => {
3228
3237
  if (this.isOpen() && this._isMobile()) {
3229
3238
  this.unblockBodyScroll();
3230
3239
  }
3240
+ this.destroyFocusTrap();
3241
+ this.cleanupTriggerListener();
3242
+ this.navigationSub?.unsubscribe();
3243
+ this.removeEscapeKeyListener();
3231
3244
  });
3232
3245
  }
3246
+ // ================== MOBILE DETECTION ==================
3233
3247
  updateMobileDetection() {
3234
3248
  this._isMobile.set(isPlatformBrowser(this.platformId)
3235
3249
  ? window.innerWidth <= OverlayComponent.MOBILE_BREAKPOINT
3236
3250
  : false);
3237
3251
  }
3252
+ // ================== TRIGGER MANAGEMENT ==================
3238
3253
  setTriggerButton(element) {
3239
3254
  this.triggerButtonRef = element;
3255
+ this.triggerKeydownHandler = (event) => {
3256
+ if (event.key === 'Enter' || event.key === ' ') {
3257
+ event.preventDefault();
3258
+ this.toggleOverlay();
3259
+ }
3260
+ };
3261
+ element.addEventListener('keydown', this.triggerKeydownHandler);
3240
3262
  }
3241
3263
  toggleOverlay() {
3242
3264
  if (this.disabled())
@@ -3252,75 +3274,160 @@ class OverlayComponent {
3252
3274
  onEscapeKey() {
3253
3275
  this.closeOverlay();
3254
3276
  }
3277
+ // ================== OVERLAY LIFECYCLE ==================
3255
3278
  openOverlay() {
3279
+ this.initializeOverlayState();
3280
+ this.prepareOverlayForOpening();
3281
+ this.createOverlayPortal();
3282
+ this.configureScrollBehavior();
3283
+ this.finalizeOverlayOpening();
3284
+ setTimeout(() => {
3285
+ this.trapFocus();
3286
+ this.makeOutsideElementsInert();
3287
+ this.setupEscapeKeyListener();
3288
+ }, 0);
3289
+ }
3290
+ initializeOverlayState() {
3256
3291
  this._isClosing.set(false);
3257
3292
  this.updateMobileDetection();
3258
- // Calculate position only on desktop, but always create portal
3293
+ this.previouslyFocusedElement = this.triggerButtonRef ?? this.getDocument().activeElement;
3294
+ }
3295
+ prepareOverlayForOpening() {
3259
3296
  if (!this._isMobile()) {
3260
3297
  this.calculatePosition();
3261
3298
  }
3262
- // Always create portal (both desktop and mobile)
3299
+ }
3300
+ createOverlayPortal() {
3263
3301
  this.createPortal();
3264
- // Block body scroll on mobile
3302
+ }
3303
+ configureScrollBehavior() {
3265
3304
  if (this._isMobile()) {
3266
3305
  this.blockBodyScroll();
3267
3306
  }
3307
+ }
3308
+ finalizeOverlayOpening() {
3268
3309
  this._isOpen.set(true);
3269
3310
  this.addResizeListener();
3311
+ this.listenToNavigation();
3270
3312
  }
3271
3313
  closeOverlay() {
3314
+ this.initializeOverlayClosing();
3315
+ this.cleanupOverlayResources();
3316
+ this.restoreScrollBehavior();
3317
+ this.destroyOverlayComponents();
3318
+ // Restore focus AFTER destroying DOM to avoid interference
3319
+ requestAnimationFrame(() => {
3320
+ this.restoreFocusToTrigger();
3321
+ });
3322
+ this.scheduleOverlayFinalization();
3323
+ }
3324
+ initializeOverlayClosing() {
3272
3325
  this._isClosing.set(true);
3326
+ }
3327
+ cleanupOverlayResources() {
3273
3328
  this.removeResizeListener();
3274
- // Unblock body scroll on mobile
3329
+ this.unsubscribeFromNavigation();
3330
+ }
3331
+ unsubscribeFromNavigation() {
3332
+ this.navigationSub?.unsubscribe();
3333
+ this.navigationSub = undefined;
3334
+ }
3335
+ restoreScrollBehavior() {
3275
3336
  if (this._isMobile()) {
3276
3337
  this.unblockBodyScroll();
3277
3338
  }
3278
- // Always destroy portal (both desktop and mobile)
3339
+ }
3340
+ destroyOverlayComponents() {
3341
+ this.destroyFocusTrap();
3279
3342
  this.destroyPortal();
3343
+ // Ensure elements are restored after destroying components
3344
+ this.restoreOutsideElements();
3345
+ }
3346
+ scheduleOverlayFinalization() {
3280
3347
  setTimeout(() => {
3281
- this._isOpen.set(false);
3282
- this._isClosing.set(false);
3348
+ this.finalizeOverlayClosing();
3283
3349
  }, OverlayComponent.ANIMATION_DURATION);
3284
3350
  }
3351
+ finalizeOverlayClosing() {
3352
+ this._isOpen.set(false);
3353
+ this._isClosing.set(false);
3354
+ }
3355
+ // ================== EVENT HANDLING ==================
3285
3356
  onPortalClick = (event) => {
3286
3357
  if (!this.isOpen() || this.isClosing())
3287
3358
  return;
3288
3359
  const target = event.target;
3289
- // Check if click is on the trigger button
3290
3360
  const onTrigger = this.triggerButtonRef?.contains(target);
3291
3361
  if (onTrigger) {
3292
- return; // Don't close if clicking on trigger
3362
+ return;
3293
3363
  }
3294
- // Check if click is inside the menu
3295
3364
  const menuEl = this.portalContainer?.querySelector('.c-overlay__menu');
3296
3365
  const insideMenu = menuEl?.contains(target);
3297
3366
  if (insideMenu) {
3298
- return; // Don't close if clicking inside menu
3367
+ return;
3299
3368
  }
3300
- // If we get here, click is outside both trigger and menu
3301
3369
  this.closeOverlay();
3302
3370
  };
3371
+ // ================== POSITIONING ==================
3303
3372
  calculatePosition() {
3304
3373
  if (!this.triggerButtonRef)
3305
3374
  return;
3306
3375
  const rect = this.triggerButtonRef.getBoundingClientRect();
3307
3376
  const menuWidth = this.parseWidth(rect.width);
3308
3377
  const menuHeight = OverlayComponent.DROPDOWN_HEIGHT;
3378
+ const viewportPosition = this.calculateViewportPosition(rect, menuWidth, menuHeight);
3379
+ const finalPosition = this.convertToFinalCoordinates(viewportPosition, menuWidth, menuHeight);
3380
+ this._menuPosition.set(finalPosition);
3381
+ }
3382
+ calculateViewportPosition(rect, menuWidth, menuHeight) {
3309
3383
  const gap = OverlayComponent.DROPDOWN_GAP;
3384
+ const viewportTop = this.calculateVerticalPosition(rect, menuHeight, gap);
3385
+ const viewportLeft = this.calculateHorizontalPosition(rect, menuWidth);
3386
+ return { top: viewportTop, left: viewportLeft };
3387
+ }
3388
+ calculateVerticalPosition(rect, menuHeight, gap) {
3310
3389
  let top = rect.bottom + gap;
3311
3390
  if (window.innerHeight - rect.bottom < menuHeight &&
3312
3391
  rect.top > rect.bottom) {
3313
3392
  top = rect.top - menuHeight - gap;
3314
3393
  }
3315
- let left = rect.left;
3316
- if (this.position() === 'right')
3317
- left = rect.right - menuWidth;
3318
- else if (this.position() === 'center')
3319
- left = rect.left + (rect.width - menuWidth) / 2;
3320
- // Clamp to viewport
3321
- top = Math.max(OverlayComponent.VIEWPORT_MARGIN, Math.min(top, window.innerHeight - menuHeight - OverlayComponent.VIEWPORT_MARGIN));
3322
- left = Math.max(OverlayComponent.VIEWPORT_MARGIN, Math.min(left, window.innerWidth - menuWidth - OverlayComponent.VIEWPORT_MARGIN));
3323
- this._menuPosition.set({ top, left, width: menuWidth });
3394
+ return top;
3395
+ }
3396
+ calculateHorizontalPosition(rect, menuWidth) {
3397
+ const position = this.position();
3398
+ switch (position) {
3399
+ case 'right':
3400
+ return rect.right - menuWidth;
3401
+ case 'center': {
3402
+ const triggerCenter = rect.left + rect.width / 2;
3403
+ return triggerCenter;
3404
+ }
3405
+ case 'left':
3406
+ default:
3407
+ return rect.left;
3408
+ }
3409
+ }
3410
+ convertToFinalCoordinates(viewportPosition, menuWidth, menuHeight) {
3411
+ const scrollTop = window.pageYOffset || this.getDocument().documentElement.scrollTop;
3412
+ const scrollLeft = window.pageXOffset || this.getDocument().documentElement.scrollLeft;
3413
+ let top;
3414
+ let left;
3415
+ if (this._isMobile()) {
3416
+ const clampedPosition = this.clampToViewport(viewportPosition, menuWidth, menuHeight);
3417
+ top = clampedPosition.top;
3418
+ left = clampedPosition.left;
3419
+ }
3420
+ else {
3421
+ const clampedPosition = this.clampToViewport(viewportPosition, menuWidth, menuHeight);
3422
+ top = clampedPosition.top + scrollTop;
3423
+ left = clampedPosition.left + scrollLeft;
3424
+ }
3425
+ return { top, left, width: menuWidth };
3426
+ }
3427
+ clampToViewport(position, menuWidth, menuHeight) {
3428
+ const clampedTop = Math.max(OverlayComponent.VIEWPORT_MARGIN, Math.min(position.top, window.innerHeight - menuHeight - OverlayComponent.VIEWPORT_MARGIN));
3429
+ const clampedLeft = Math.max(OverlayComponent.VIEWPORT_MARGIN, Math.min(position.left, window.innerWidth - menuWidth - OverlayComponent.VIEWPORT_MARGIN));
3430
+ return { top: clampedTop, left: clampedLeft };
3324
3431
  }
3325
3432
  parseWidth(triggerWidth) {
3326
3433
  if (this.width() === 'stretch')
@@ -3328,6 +3435,7 @@ class OverlayComponent {
3328
3435
  const w = parseFloat(this.width());
3329
3436
  return isNaN(w) ? OverlayComponent.DEFAULT_MENU_WIDTH : w;
3330
3437
  }
3438
+ // ================== RESIZE HANDLING ==================
3331
3439
  addResizeListener() {
3332
3440
  if (!isPlatformBrowser(this.platformId))
3333
3441
  return;
@@ -3344,61 +3452,94 @@ class OverlayComponent {
3344
3452
  const wasMobile = this._isMobile();
3345
3453
  this.updateMobileDetection();
3346
3454
  const isNowMobile = this._isMobile();
3347
- // If mobile state changed, re-render the overlay
3348
3455
  if (wasMobile !== isNowMobile) {
3349
- // Destroy and recreate portal to apply correct styles
3350
3456
  this.destroyPortal();
3351
3457
  this.createPortal();
3352
- // Recalculate position if now on desktop
3353
3458
  if (!isNowMobile && this.triggerButtonRef) {
3354
3459
  this.calculatePosition();
3355
3460
  }
3356
3461
  }
3357
3462
  else if (!isNowMobile && this.triggerButtonRef) {
3358
- // If still on desktop, just recalculate position
3359
3463
  this.calculatePosition();
3360
3464
  }
3361
3465
  };
3466
+ // ================== PORTAL MANAGEMENT ==================
3362
3467
  createPortal() {
3363
3468
  if (!this.menuTemplate || !this.contentTemplate)
3364
3469
  return;
3470
+ this.createPortalTemplate();
3471
+ this.createPortalContainer();
3472
+ this.setupPortalEventListeners();
3473
+ this.createPortalOutlet();
3474
+ this.attachPortalContent();
3475
+ // Focus trap will be set up in openOverlay()
3476
+ this.applyMenuPositioning();
3477
+ }
3478
+ createPortalTemplate() {
3365
3479
  this.portal = new TemplatePortal(this.menuTemplate, this.viewContainerRef);
3366
- // Create portal container
3367
- this.portalContainer = document.createElement('div');
3368
- this.portalContainer.style.position = 'fixed';
3480
+ }
3481
+ createPortalContainer() {
3482
+ this.portalContainer = this.getDocument().createElement('div');
3483
+ this.configurePortalContainerStyles();
3484
+ this.getDocument().body.appendChild(this.portalContainer);
3485
+ }
3486
+ configurePortalContainerStyles() {
3487
+ if (!this.portalContainer)
3488
+ return;
3489
+ this.portalContainer.style.position = this._isMobile() ? 'fixed' : 'absolute';
3369
3490
  this.portalContainer.style.top = '0';
3370
3491
  this.portalContainer.style.left = '0';
3371
3492
  this.portalContainer.style.width = '100%';
3372
3493
  this.portalContainer.style.height = '100%';
3373
3494
  this.portalContainer.style.zIndex = '1000';
3374
- this.portalContainer.style.pointerEvents = 'auto'; // Enable clicks to capture outside clicks
3375
- document.body.appendChild(this.portalContainer);
3376
- // Add click listener to portal container
3377
- this.portalContainer.addEventListener('click', this.onPortalClick.bind(this));
3378
- // Create outlet
3495
+ this.portalContainer.style.pointerEvents = 'auto';
3496
+ }
3497
+ setupPortalEventListeners() {
3498
+ if (!this.portalContainer)
3499
+ return;
3500
+ this.boundPortalClickHandler = this.onPortalClick.bind(this);
3501
+ this.portalContainer.addEventListener('click', this.boundPortalClickHandler);
3502
+ }
3503
+ createPortalOutlet() {
3504
+ if (!this.portalContainer)
3505
+ return;
3379
3506
  this.portalOutlet = new DomPortalOutlet(this.portalContainer, null, this.applicationRef, this.viewContainerRef.injector);
3507
+ }
3508
+ attachPortalContent() {
3509
+ if (!this.portalOutlet || !this.portal)
3510
+ return;
3380
3511
  this.portalOutlet.attach(this.portal);
3381
- // Apply position to menu only on desktop
3382
- const menuEl = this.portalContainer.querySelector('.c-overlay__menu');
3383
- if (menuEl) {
3384
- menuEl.style.pointerEvents = 'auto'; // Re-enable clicks on menu
3385
- // Apply styles based on current mobile state
3386
- if (!this._isMobile()) {
3387
- // Desktop: apply calculated position
3388
- const pos = this._menuPosition();
3389
- menuEl.style.position = 'fixed';
3390
- menuEl.style.top = `${pos.top}px`;
3391
- menuEl.style.left = `${pos.left}px`;
3392
- menuEl.style.width = `${pos.width}px`;
3393
- }
3394
- else {
3395
- // Mobile: clear desktop positioning styles
3396
- menuEl.style.position = '';
3397
- menuEl.style.top = '';
3398
- menuEl.style.left = '';
3399
- menuEl.style.width = '';
3400
- }
3512
+ }
3513
+ applyMenuPositioning() {
3514
+ const menuEl = this.portalContainer?.querySelector('.c-overlay__menu');
3515
+ if (!menuEl)
3516
+ return;
3517
+ this.configureMenuElement(menuEl);
3518
+ this.applyPositioningStyles(menuEl);
3519
+ }
3520
+ configureMenuElement(menuEl) {
3521
+ menuEl.style.pointerEvents = 'auto';
3522
+ }
3523
+ applyPositioningStyles(menuEl) {
3524
+ if (this._isMobile()) {
3525
+ this.applyMobilePositioning(menuEl);
3401
3526
  }
3527
+ else {
3528
+ this.applyDesktopPositioning(menuEl);
3529
+ }
3530
+ }
3531
+ applyMobilePositioning(menuEl) {
3532
+ menuEl.style.position = '';
3533
+ menuEl.style.top = '';
3534
+ menuEl.style.left = '';
3535
+ menuEl.style.width = '';
3536
+ }
3537
+ applyDesktopPositioning(menuEl) {
3538
+ const pos = this._menuPosition();
3539
+ menuEl.style.position = 'absolute';
3540
+ menuEl.style.top = `${pos.top}px`;
3541
+ menuEl.style.left = `${pos.left}px`;
3542
+ menuEl.style.width = `${pos.width}px`;
3402
3543
  }
3403
3544
  destroyPortal() {
3404
3545
  if (this.portalOutlet) {
@@ -3408,32 +3549,171 @@ class OverlayComponent {
3408
3549
  this.portal = undefined;
3409
3550
  }
3410
3551
  if (this.portalContainer && this.portalContainer.parentNode) {
3411
- // Remove event listener before removing from DOM
3412
- this.portalContainer.removeEventListener('click', this.onPortalClick);
3552
+ if (this.boundPortalClickHandler) {
3553
+ this.portalContainer.removeEventListener('click', this.boundPortalClickHandler);
3554
+ this.boundPortalClickHandler = undefined;
3555
+ }
3413
3556
  this.portalContainer.parentNode.removeChild(this.portalContainer);
3414
3557
  }
3415
3558
  this.portalContainer = undefined;
3416
3559
  }
3560
+ // ================== SCROLL MANAGEMENT ==================
3417
3561
  blockBodyScroll() {
3418
3562
  if (!isPlatformBrowser(this.platformId))
3419
3563
  return;
3420
- // Save original body overflow
3421
- this.originalBodyOverflow = document.body.style.overflow;
3422
- // Block body scroll
3423
- document.body.style.overflow = 'hidden';
3564
+ this.originalBodyOverflow = this.getDocument().body.style.overflow;
3565
+ this.getDocument().body.style.overflow = 'hidden';
3566
+ this.getDocument().body.style.position = 'fixed';
3567
+ this.getDocument().body.style.width = '100%';
3568
+ this.getDocument().body.style.top = `-${window.pageYOffset}px`;
3569
+ this.getDocument().documentElement.style.overflow = 'hidden';
3424
3570
  }
3425
3571
  unblockBodyScroll() {
3426
3572
  if (!isPlatformBrowser(this.platformId))
3427
3573
  return;
3428
- // Restore original body overflow
3574
+ const scrollY = this.getDocument().body.style.top;
3429
3575
  if (this.originalBodyOverflow !== undefined) {
3430
- document.body.style.overflow = this.originalBodyOverflow;
3576
+ this.getDocument().body.style.overflow = this.originalBodyOverflow;
3431
3577
  }
3432
3578
  else {
3433
- document.body.style.overflow = '';
3579
+ this.getDocument().body.style.overflow = '';
3580
+ }
3581
+ this.getDocument().body.style.position = '';
3582
+ this.getDocument().body.style.width = '';
3583
+ this.getDocument().body.style.top = '';
3584
+ this.getDocument().documentElement.style.overflow = '';
3585
+ if (scrollY) {
3586
+ window.scrollTo(0, parseInt(scrollY || '0') * -1);
3434
3587
  }
3435
3588
  this.originalBodyOverflow = undefined;
3436
3589
  }
3590
+ // ================== FOCUS MANAGEMENT ==================
3591
+ trapFocus() {
3592
+ if (!this.portalContainer) {
3593
+ return;
3594
+ }
3595
+ // Search for menu element in entire document, not just within portalContainer
3596
+ const doc = this.getDocument();
3597
+ const menuEl = doc.querySelector('.c-overlay__menu');
3598
+ if (!menuEl) {
3599
+ setTimeout(() => this.trapFocus(), 10);
3600
+ return;
3601
+ }
3602
+ // CDK FocusTrap
3603
+ this.focusTrap = this.focusTrapFactory.create(menuEl);
3604
+ this.focusTrap.focusInitialElement();
3605
+ }
3606
+ // ================== ESCAPE KEY HANDLING ==================
3607
+ setupEscapeKeyListener() {
3608
+ if (!isPlatformBrowser(this.platformId))
3609
+ return;
3610
+ this.escapeKeyHandler = (event) => {
3611
+ if (event.key === 'Escape' && this.isOpen() && !this.isClosing()) {
3612
+ event.preventDefault();
3613
+ this.closeOverlay();
3614
+ }
3615
+ };
3616
+ this.getDocument().addEventListener('keydown', this.escapeKeyHandler);
3617
+ }
3618
+ removeEscapeKeyListener() {
3619
+ if (!isPlatformBrowser(this.platformId))
3620
+ return;
3621
+ if (this.escapeKeyHandler) {
3622
+ this.getDocument().removeEventListener('keydown', this.escapeKeyHandler);
3623
+ this.escapeKeyHandler = undefined;
3624
+ }
3625
+ }
3626
+ // ================== FOCUS RESTORATION ==================
3627
+ restoreFocusToTrigger() {
3628
+ const doc = this.getDocument();
3629
+ // Prefer to return focus to trigger button
3630
+ if (this.triggerButtonRef && doc.contains(this.triggerButtonRef)) {
3631
+ const focusableElement = this.findFocusableButton(this.triggerButtonRef);
3632
+ if (focusableElement) {
3633
+ focusableElement.focus({ preventScroll: true });
3634
+ return;
3635
+ }
3636
+ }
3637
+ // Si no hay trigger, devolvemos el foco al elemento que estaba activo antes
3638
+ if (this.previouslyFocusedElement && doc.contains(this.previouslyFocusedElement)) {
3639
+ const focusableElement = this.findFocusableButton(this.previouslyFocusedElement);
3640
+ if (focusableElement) {
3641
+ focusableElement.focus({ preventScroll: true });
3642
+ return;
3643
+ }
3644
+ }
3645
+ // Safety fallback
3646
+ doc.body.focus();
3647
+ }
3648
+ findFocusableButton(element) {
3649
+ // If element is already a focusable button, return it
3650
+ if (element.tagName === 'BUTTON' && !element.hasAttribute('disabled')) {
3651
+ return element;
3652
+ }
3653
+ // If it's a lib-button or custom component, search for internal button
3654
+ const button = element.querySelector('button:not([disabled])');
3655
+ if (button) {
3656
+ return button;
3657
+ }
3658
+ // Search for any focusable element inside
3659
+ const focusableSelectors = [
3660
+ 'button:not([disabled])',
3661
+ 'input:not([disabled])',
3662
+ 'select:not([disabled])',
3663
+ 'textarea:not([disabled])',
3664
+ 'a[href]',
3665
+ '[tabindex]:not([tabindex="-1"])'
3666
+ ];
3667
+ const focusable = element.querySelector(focusableSelectors.join(', '));
3668
+ return focusable;
3669
+ }
3670
+ releaseFocusTrap() {
3671
+ if (this.focusTrap) {
3672
+ this.focusTrap.destroy();
3673
+ this.focusTrap = undefined;
3674
+ }
3675
+ this.removeEscapeKeyListener();
3676
+ }
3677
+ // ================== INERT OUTSIDE ELEMENTS ==================
3678
+ makeOutsideElementsInert() {
3679
+ if (!isPlatformBrowser(this.platformId))
3680
+ return;
3681
+ this.inertElements = [];
3682
+ const doc = this.getDocument();
3683
+ const bodyChildren = Array.from(doc.body.children);
3684
+ bodyChildren.forEach(el => {
3685
+ if (el !== this.portalContainer && !el.hasAttribute('aria-hidden')) {
3686
+ el.inert = true; // Hace que no sean focusables ni interactuables
3687
+ this.inertElements.push(el);
3688
+ }
3689
+ });
3690
+ }
3691
+ restoreOutsideElements() {
3692
+ if (!isPlatformBrowser(this.platformId))
3693
+ return;
3694
+ this.inertElements.forEach(el => {
3695
+ el.inert = false;
3696
+ });
3697
+ this.inertElements = [];
3698
+ }
3699
+ destroyFocusTrap() {
3700
+ this.releaseFocusTrap();
3701
+ this.restoreOutsideElements();
3702
+ }
3703
+ cleanupTriggerListener() {
3704
+ if (this.triggerButtonRef && this.triggerKeydownHandler) {
3705
+ this.triggerButtonRef.removeEventListener('keydown', this.triggerKeydownHandler);
3706
+ this.triggerKeydownHandler = undefined;
3707
+ }
3708
+ }
3709
+ listenToNavigation() {
3710
+ this.navigationSub?.unsubscribe(); // Clean up previous subscription
3711
+ this.navigationSub = this.router.events.subscribe(event => {
3712
+ if (event instanceof NavigationStart && this.isOpen()) {
3713
+ this.closeOverlay();
3714
+ }
3715
+ });
3716
+ }
3437
3717
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: OverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3438
3718
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: OverlayComponent, isStandalone: true, selector: "lib-overlay", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, queries: [{ propertyName: "contentTemplate", first: true, predicate: TemplateRef, descendants: true, static: true }, { propertyName: "footerTemplate", first: true, predicate: ["footer"], descendants: true, static: true }], viewQueries: [{ propertyName: "menuTemplate", first: true, predicate: ["menuTemplate"], descendants: true, static: true }], ngImport: i0, template: "\n\n\n<!-- Portal template for both desktop and mobile -->\n<ng-template #menuTemplate>\n <div class=\"c-overlay\" [ngClass]=\"getClasses()\">\n <!-- Backdrop for mobile -->\n @if (_isMobile() && (isOpen() || isClosing())) {\n <div\n class=\"c-overlay__backdrop\"\n [ngClass]=\"getBackdropClasses()\"\n (click)=\"onBackdropClick()\"\n (keydown.escape)=\"onEscapeKey()\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Close overlay\"\n ></div>\n }\n\n <!-- Overlay Menu -->\n @if (isOpen() || isClosing()) {\n <div\n class=\"c-overlay__menu\"\n [ngClass]=\"getMenuClasses()\"\n [ngStyle]=\"getMenuStyles()\"\n #overlayMenu\n >\n <div class=\"c-overlay__content\">\n <!-- Main content projection -->\n <ng-container *ngTemplateOutlet=\"contentTemplate\"></ng-container>\n </div>\n \n <!-- Footer slot for mobile action buttons -->\n @if (_isMobile() && footerTemplate) {\n <div class=\"c-overlay__footer\">\n <ng-container *ngTemplateOutlet=\"footerTemplate\"></ng-container>\n </div>\n }\n </div>\n }\n </div>\n</ng-template>", styles: [".c-overlay{position:relative}.c-overlay__backdrop{position:fixed;inset:0;z-index:999;background-color:var(--color-effect-overlay);opacity:0;transition:opacity .2s ease-in-out;display:none}.c-overlay__backdrop--open{opacity:1}.c-overlay__menu{position:absolute;margin-top:2px;z-index:1000;background-color:var(--color-core-background-surface-raised);border:var(--size-border-width-sm) solid var(--color-core-border-soft);border-radius:var(--size-textfield-border-radius);box-shadow:var(--elevation-raised);max-height:320px;min-width:200px;overflow:hidden;display:flex;flex-direction:column;opacity:0;transform:scale(.95);animation:overlay-enter .2s ease-out forwards;transform-origin:top center}.c-overlay__menu--fixed{position:fixed;min-width:0}.c-overlay__menu--right{left:0;right:auto}.c-overlay__menu--left{left:auto;right:0}.c-overlay__menu--center{left:50%;right:auto;transform:translate(-50%) scale(.95);animation:overlay-enter-center .2s ease-out forwards}.c-overlay__content{flex:1;overflow-y:auto}.c-overlay__footer{display:none}@keyframes overlay-enter{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes overlay-enter-center{0%{opacity:0;transform:translate(-50%) scale(.95)}to{opacity:1;transform:translate(-50%) scale(1)}}@keyframes overlay-exit{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:scale(.95)}}@media (max-width: 768px){.c-overlay__backdrop{display:block;z-index:999}.c-overlay__menu{position:fixed;bottom:0;left:0;right:0;width:100%;max-width:none;max-height:100vh;margin-top:0;border-radius:0;animation:none;z-index:1001;opacity:1;display:flex;flex-direction:column}.c-overlay__content{flex:1;overflow-y:auto;overflow-x:hidden;max-height:100vh;width:100%;min-width:0}.c-overlay__content>*{max-width:100%!important;width:100%!important;box-sizing:border-box!important;word-wrap:break-word!important;overflow-wrap:break-word!important;overflow-x:hidden!important}.c-overlay__content *{max-width:100%;box-sizing:border-box;word-wrap:break-word;overflow-wrap:break-word}.c-overlay--open .c-overlay__menu{transform:translateY(0)}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: PortalModule }] });
3439
3719
  }
@@ -5905,18 +6185,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
5905
6185
  * - **default**: Shows custom header content
5906
6186
  * - **navigation**: Shows back button with title in header
5907
6187
  */
5908
- class SidebarComponent {
6188
+ class SidebarProgrammaticComponent {
5909
6189
  visible = signal(false);
5910
6190
  state = signal('default');
5911
6191
  title = signal('');
5912
6192
  hasSlotHeader = signal(false);
5913
- hasSlotFooter = signal(false);
6193
+ savedHeaderContent = signal([]);
5914
6194
  setVisible(visible) {
5915
6195
  this.visible.set(visible);
5916
6196
  }
6197
+ updateTitle(title) {
6198
+ if (this.hasSlotHeader()) {
6199
+ this.saveHeaderContent();
6200
+ this.removeSlotHeader();
6201
+ }
6202
+ this.title.set(title);
6203
+ }
5917
6204
  setConfig(config) {
5918
6205
  if (config.title !== undefined) {
5919
- this.title.set(config.title);
6206
+ this.updateTitle(config.title);
5920
6207
  }
5921
6208
  if (config.state !== undefined) {
5922
6209
  this.state.set(config.state);
@@ -5929,7 +6216,15 @@ class SidebarComponent {
5929
6216
  // This method is overridden by the service
5930
6217
  }
5931
6218
  onBackNavigation() {
5932
- // This method is overridden by the service
6219
+ this.state.set('default');
6220
+ if (this.savedHeaderContent()) {
6221
+ setTimeout(() => {
6222
+ this.restoreHeaderFooterContent();
6223
+ }, 0);
6224
+ }
6225
+ else {
6226
+ this.updateTitle(this.title());
6227
+ }
5933
6228
  }
5934
6229
  onCloseButtonClick() {
5935
6230
  // This method is overridden by the service
@@ -5937,19 +6232,64 @@ class SidebarComponent {
5937
6232
  onArrowKeyNavigation(direction) {
5938
6233
  // This method is overridden by the content component
5939
6234
  }
5940
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5941
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: SidebarComponent, isStandalone: true, selector: "lib-sidebar", ngImport: i0, template: "<div class=\"c-sidebar\" [ngClass]=\"'c-sidebar--' + state() + (visible() ? ' c-sidebar--visible' : ' c-sidebar--hide')\">\n <!-- Backdrop -->\n <div\n class=\"c-sidebar__backdrop\"\n [ngClass]=\"{'c-sidebar__backdrop--open': visible()}\"\n (click)=\"onBackdropClick()\"\n (keydown.escape)=\"onEscapeKey()\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Close sidebar\"\n ></div>\n\n <!-- Sidebar Content -->\n <aside\n class=\"c-sidebar__content\"\n [ngClass]=\"'c-sidebar__content--' + state()\"\n (keydown.escape)=\"onEscapeKey()\"\n (keydown.arrowup)=\"onArrowKeyNavigation('up')\"\n (keydown.arrowdown)=\"onArrowKeyNavigation('down')\"\n role=\"dialog\"\n tabindex=\"-1\"\n >\n <!-- Header -->\n <header class=\"c-sidebar__header\">\n <div class=\"c-sidebar__header-content\">\n @if (state() === 'default') {\n @if (hasSlotHeader()) {\n <ng-content select=\"[slot=header]\"></ng-content>\n } @else if (title()) {\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n }\n }\n @if (state() === 'navigation') {\n <div class=\"c-sidebar__header-navigation\">\n <lib-button-icon \n iconName=\"caretleft-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Back\"\n (clicked)=\"onBackNavigation()\">\n </lib-button-icon>\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n </div>\n }\n </div>\n <lib-button-icon \n iconName=\"x-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Close\"\n (clicked)=\"onCloseButtonClick()\">\n </lib-button-icon>\n </header>\n \n <!-- Body Content -->\n <div class=\"c-sidebar__body\">\n <ng-content></ng-content>\n </div>\n \n <!-- Footer Content -->\n <footer class=\"c-sidebar__footer\" [ngClass]=\"{'c-sidebar__footer--hidden': !hasSlotFooter()}\">\n <div class=\"c-sidebar__footer-content\">\n <ng-content select=\"[slot=footer]\"></ng-content>\n </div>\n </footer>\n </aside>\n</div>\n", styles: [".c-sidebar{position:fixed;top:0;left:0;width:100%;height:100vh;z-index:1000}.c-sidebar__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:var(--color-effect-overlay);opacity:0;transition:opacity .2s ease-in-out;z-index:999}.c-sidebar__backdrop--open{opacity:1}.c-sidebar__content{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--color-core-background-surface-floating);border-right:var(--size-border-width-sm) solid var(--color-core-border-soft);box-shadow:0 4px 8px 0 var(--color-effect-shadow-soft),0 0 4px 0 var(--color-effect-shadow-soft);position:fixed;top:0;left:0;z-index:1000;transform:translate(-100%);transition:transform .33s ease-out}@media (min-width: 768px){.c-sidebar__content{width:360px;max-width:360px}}.c-sidebar--visible .c-sidebar__content{transform:translate(0)}.c-sidebar--hide .c-sidebar__content{transform:translate(-100%)}.c-sidebar__header{padding:var(--space-component-padding-lg) var(--space-container-padding-md);border-bottom:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-default);display:flex;align-items:center;justify-content:space-between;gap:var(--space-container-gap-sm)}.c-sidebar__header-content{height:2rem;display:flex;align-items:center;flex:1}.c-sidebar__header-title{flex:1;color:var(--color-core-content-default);font-family:var(--typography-label-lg-default-family, Satoshi);font-size:var(--typography-label-lg-default-size);font-style:normal;font-weight:var(--typography-label-lg-default-weight);line-height:var(--typography-label-lg-default-line-height);letter-spacing:var(--typography-label-lg-default-letter-spacing)}.c-sidebar__header-navigation{display:flex;align-items:center;gap:var(--space-container-gap-xs)}.c-sidebar__body{padding:var(--space-component-padding-sm);flex:1;overflow-y:auto}@media (min-width: 768px){.c-sidebar__body{padding:var(--space-component-padding-lg) var(--space-component-padding-md)}}.c-sidebar__footer{padding:var(--space-container-padding-sm);border-top:var(--size-border-width-sm) solid var(--color-core-border-soft);flex-shrink:0}.c-sidebar__footer--hidden{display:none}.c-sidebar__footer-content{display:flex;flex-direction:column;gap:var(--space-component-gap-xs)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ButtonIconComponent, selector: "lib-button-icon", inputs: ["ariaLabel", "variant", "size", "iconName", "disabled", "loading", "skeletonActive"], outputs: ["clicked"] }] });
6235
+ restoreHeaderFooterContent() {
6236
+ const headerContainer = document.querySelector('.c-sidebar__header-default');
6237
+ if (headerContainer) {
6238
+ headerContainer.innerHTML = '';
6239
+ const savedElements = this.savedHeaderContent();
6240
+ savedElements.forEach((element) => {
6241
+ const clonedElement = element.cloneNode(true);
6242
+ headerContainer.appendChild(clonedElement);
6243
+ });
6244
+ this.removeDuplicateContent();
6245
+ this.hasSlotHeader.set(true);
6246
+ }
6247
+ }
6248
+ removeDuplicateContent() {
6249
+ const contentContainer = document.querySelector('.c-sidebar__body');
6250
+ if (contentContainer) {
6251
+ const slotHeaderContent = contentContainer.querySelector('[slot="header"]');
6252
+ if (slotHeaderContent) {
6253
+ slotHeaderContent.remove();
6254
+ }
6255
+ const slotFooterContent = contentContainer.querySelector('[slot="footer"]');
6256
+ if (slotFooterContent) {
6257
+ slotFooterContent.remove();
6258
+ }
6259
+ }
6260
+ }
6261
+ saveHeaderContent() {
6262
+ const headerContainer = document.querySelector('.c-sidebar__header-default');
6263
+ if (headerContainer) {
6264
+ const elements = Array.from(headerContainer.children);
6265
+ this.savedHeaderContent.set(elements);
6266
+ }
6267
+ }
6268
+ removeSlotHeader() {
6269
+ const headerContainer = document.querySelector('.c-sidebar__header-default');
6270
+ if (headerContainer) {
6271
+ const slotHeaderContent = headerContainer.querySelector('[slot="header"]');
6272
+ if (slotHeaderContent) {
6273
+ slotHeaderContent.remove();
6274
+ }
6275
+ const customHeaderItems = headerContainer.querySelectorAll('[data-custom-header="true"]');
6276
+ customHeaderItems.forEach(item => item.remove());
6277
+ this.hasSlotHeader.set(false);
6278
+ }
6279
+ }
6280
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarProgrammaticComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6281
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: SidebarProgrammaticComponent, isStandalone: true, selector: "lib-sidebar-programmatic", ngImport: i0, template: "<div class=\"c-sidebar\" [ngClass]=\"'c-sidebar--' + state() + (visible() ? ' c-sidebar--visible' : ' c-sidebar--hide')\">\n <!-- Backdrop -->\n <div\n class=\"c-sidebar__backdrop\"\n [ngClass]=\"{'c-sidebar__backdrop--open': visible()}\"\n (click)=\"onBackdropClick()\"\n (keydown.escape)=\"onEscapeKey()\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Close sidebar\"\n ></div>\n\n <!-- Sidebar Content -->\n <aside\n class=\"c-sidebar__content\"\n [ngClass]=\"'c-sidebar__content--' + state()\"\n (keydown.escape)=\"onEscapeKey()\"\n role=\"dialog\"\n tabindex=\"-1\"\n >\n <!-- Header -->\n <header class=\"c-sidebar__header\">\n <div class=\"c-sidebar__header-content\">\n <div class=\"c-sidebar__header-default\">\n @if (state() === 'default') {\n @if (hasSlotHeader()) {\n <ng-content select=\"[slot=header]\"></ng-content>\n } @else if (title()) {\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n }\n }\n </div>\n \n @if (state() === 'navigation') {\n <div class=\"c-sidebar__header-navigation\">\n <lib-button-icon \n iconName=\"caretleft-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Back\"\n (clicked)=\"onBackNavigation()\">\n </lib-button-icon>\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n </div>\n }\n </div>\n <lib-button-icon \n iconName=\"x-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Close\"\n (clicked)=\"onCloseButtonClick()\">\n </lib-button-icon>\n </header>\n \n <!-- Body Content -->\n <div class=\"c-sidebar__body\">\n <ng-content></ng-content>\n </div>\n \n <!-- Footer Content -->\n <footer class=\"c-sidebar__footer\" [ngClass]=\"{'c-sidebar__footer--hidden': state() === 'navigation'}\">\n <div class=\"c-sidebar__footer-content\">\n <ng-content select=\"[slot=footer]\"></ng-content>\n </div>\n </footer>\n </aside>\n</div>\n", styles: [".c-sidebar{position:fixed;top:0;left:0;width:100%;height:100vh;z-index:1000}.c-sidebar__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:var(--color-effect-overlay);opacity:0;transition:opacity .2s ease-in-out;z-index:999}.c-sidebar__backdrop--open{opacity:1}.c-sidebar__content{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--color-core-background-surface-floating);border-right:var(--size-border-width-sm) solid var(--color-core-border-soft);box-shadow:0 4px 8px 0 var(--color-effect-shadow-soft),0 0 4px 0 var(--color-effect-shadow-soft);position:fixed;top:0;left:0;z-index:1000;transform:translate(-100%);transition:transform .33s ease-out}@media (min-width: 768px){.c-sidebar__content{width:360px;max-width:360px}}.c-sidebar--visible .c-sidebar__content{transform:translate(0)}.c-sidebar--hide .c-sidebar__content{transform:translate(-100%)}.c-sidebar__header{padding:var(--space-component-padding-lg) var(--space-container-padding-md);border-bottom:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-default);display:flex;align-items:center;justify-content:space-between;gap:var(--space-container-gap-sm)}.c-sidebar__header-content{height:2rem;display:flex;align-items:center;flex:1}.c-sidebar__header-title{flex:1;color:var(--color-core-content-default);font-family:var(--typography-label-lg-default-family, Satoshi);font-size:var(--typography-label-lg-default-size);font-style:normal;font-weight:var(--typography-label-lg-default-weight);line-height:var(--typography-label-lg-default-line-height);letter-spacing:var(--typography-label-lg-default-letter-spacing)}.c-sidebar__header-navigation{display:flex;align-items:center;gap:var(--space-container-gap-xs)}.c-sidebar__body{padding:var(--space-component-padding-sm);flex:1;overflow-y:auto}@media (min-width: 768px){.c-sidebar__body{padding:var(--space-component-padding-lg) var(--space-component-padding-md)}}.c-sidebar__footer{padding:var(--space-container-padding-sm);border-top:var(--size-border-width-sm) solid var(--color-core-border-soft);flex-shrink:0}.c-sidebar__footer--hidden{display:none}.c-sidebar__footer-content{display:flex;flex-direction:column;gap:var(--space-component-gap-xs)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ButtonIconComponent, selector: "lib-button-icon", inputs: ["ariaLabel", "variant", "size", "iconName", "disabled", "loading", "skeletonActive"], outputs: ["clicked"] }] });
5942
6282
  }
5943
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarComponent, decorators: [{
6283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarProgrammaticComponent, decorators: [{
5944
6284
  type: Component,
5945
- args: [{ selector: 'lib-sidebar', imports: [CommonModule, ButtonIconComponent, NgClass], template: "<div class=\"c-sidebar\" [ngClass]=\"'c-sidebar--' + state() + (visible() ? ' c-sidebar--visible' : ' c-sidebar--hide')\">\n <!-- Backdrop -->\n <div\n class=\"c-sidebar__backdrop\"\n [ngClass]=\"{'c-sidebar__backdrop--open': visible()}\"\n (click)=\"onBackdropClick()\"\n (keydown.escape)=\"onEscapeKey()\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Close sidebar\"\n ></div>\n\n <!-- Sidebar Content -->\n <aside\n class=\"c-sidebar__content\"\n [ngClass]=\"'c-sidebar__content--' + state()\"\n (keydown.escape)=\"onEscapeKey()\"\n (keydown.arrowup)=\"onArrowKeyNavigation('up')\"\n (keydown.arrowdown)=\"onArrowKeyNavigation('down')\"\n role=\"dialog\"\n tabindex=\"-1\"\n >\n <!-- Header -->\n <header class=\"c-sidebar__header\">\n <div class=\"c-sidebar__header-content\">\n @if (state() === 'default') {\n @if (hasSlotHeader()) {\n <ng-content select=\"[slot=header]\"></ng-content>\n } @else if (title()) {\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n }\n }\n @if (state() === 'navigation') {\n <div class=\"c-sidebar__header-navigation\">\n <lib-button-icon \n iconName=\"caretleft-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Back\"\n (clicked)=\"onBackNavigation()\">\n </lib-button-icon>\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n </div>\n }\n </div>\n <lib-button-icon \n iconName=\"x-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Close\"\n (clicked)=\"onCloseButtonClick()\">\n </lib-button-icon>\n </header>\n \n <!-- Body Content -->\n <div class=\"c-sidebar__body\">\n <ng-content></ng-content>\n </div>\n \n <!-- Footer Content -->\n <footer class=\"c-sidebar__footer\" [ngClass]=\"{'c-sidebar__footer--hidden': !hasSlotFooter()}\">\n <div class=\"c-sidebar__footer-content\">\n <ng-content select=\"[slot=footer]\"></ng-content>\n </div>\n </footer>\n </aside>\n</div>\n", styles: [".c-sidebar{position:fixed;top:0;left:0;width:100%;height:100vh;z-index:1000}.c-sidebar__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:var(--color-effect-overlay);opacity:0;transition:opacity .2s ease-in-out;z-index:999}.c-sidebar__backdrop--open{opacity:1}.c-sidebar__content{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--color-core-background-surface-floating);border-right:var(--size-border-width-sm) solid var(--color-core-border-soft);box-shadow:0 4px 8px 0 var(--color-effect-shadow-soft),0 0 4px 0 var(--color-effect-shadow-soft);position:fixed;top:0;left:0;z-index:1000;transform:translate(-100%);transition:transform .33s ease-out}@media (min-width: 768px){.c-sidebar__content{width:360px;max-width:360px}}.c-sidebar--visible .c-sidebar__content{transform:translate(0)}.c-sidebar--hide .c-sidebar__content{transform:translate(-100%)}.c-sidebar__header{padding:var(--space-component-padding-lg) var(--space-container-padding-md);border-bottom:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-default);display:flex;align-items:center;justify-content:space-between;gap:var(--space-container-gap-sm)}.c-sidebar__header-content{height:2rem;display:flex;align-items:center;flex:1}.c-sidebar__header-title{flex:1;color:var(--color-core-content-default);font-family:var(--typography-label-lg-default-family, Satoshi);font-size:var(--typography-label-lg-default-size);font-style:normal;font-weight:var(--typography-label-lg-default-weight);line-height:var(--typography-label-lg-default-line-height);letter-spacing:var(--typography-label-lg-default-letter-spacing)}.c-sidebar__header-navigation{display:flex;align-items:center;gap:var(--space-container-gap-xs)}.c-sidebar__body{padding:var(--space-component-padding-sm);flex:1;overflow-y:auto}@media (min-width: 768px){.c-sidebar__body{padding:var(--space-component-padding-lg) var(--space-component-padding-md)}}.c-sidebar__footer{padding:var(--space-container-padding-sm);border-top:var(--size-border-width-sm) solid var(--color-core-border-soft);flex-shrink:0}.c-sidebar__footer--hidden{display:none}.c-sidebar__footer-content{display:flex;flex-direction:column;gap:var(--space-component-gap-xs)}\n"] }]
6285
+ args: [{ selector: 'lib-sidebar-programmatic', imports: [CommonModule, ButtonIconComponent, NgClass], template: "<div class=\"c-sidebar\" [ngClass]=\"'c-sidebar--' + state() + (visible() ? ' c-sidebar--visible' : ' c-sidebar--hide')\">\n <!-- Backdrop -->\n <div\n class=\"c-sidebar__backdrop\"\n [ngClass]=\"{'c-sidebar__backdrop--open': visible()}\"\n (click)=\"onBackdropClick()\"\n (keydown.escape)=\"onEscapeKey()\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Close sidebar\"\n ></div>\n\n <!-- Sidebar Content -->\n <aside\n class=\"c-sidebar__content\"\n [ngClass]=\"'c-sidebar__content--' + state()\"\n (keydown.escape)=\"onEscapeKey()\"\n role=\"dialog\"\n tabindex=\"-1\"\n >\n <!-- Header -->\n <header class=\"c-sidebar__header\">\n <div class=\"c-sidebar__header-content\">\n <div class=\"c-sidebar__header-default\">\n @if (state() === 'default') {\n @if (hasSlotHeader()) {\n <ng-content select=\"[slot=header]\"></ng-content>\n } @else if (title()) {\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n }\n }\n </div>\n \n @if (state() === 'navigation') {\n <div class=\"c-sidebar__header-navigation\">\n <lib-button-icon \n iconName=\"caretleft-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Back\"\n (clicked)=\"onBackNavigation()\">\n </lib-button-icon>\n <div class=\"c-sidebar__header-title\">{{ title() }}</div>\n </div>\n }\n </div>\n <lib-button-icon \n iconName=\"x-regular\" \n variant=\"neutral\" \n size=\"sm\"\n ariaLabel=\"Close\"\n (clicked)=\"onCloseButtonClick()\">\n </lib-button-icon>\n </header>\n \n <!-- Body Content -->\n <div class=\"c-sidebar__body\">\n <ng-content></ng-content>\n </div>\n \n <!-- Footer Content -->\n <footer class=\"c-sidebar__footer\" [ngClass]=\"{'c-sidebar__footer--hidden': state() === 'navigation'}\">\n <div class=\"c-sidebar__footer-content\">\n <ng-content select=\"[slot=footer]\"></ng-content>\n </div>\n </footer>\n </aside>\n</div>\n", styles: [".c-sidebar{position:fixed;top:0;left:0;width:100%;height:100vh;z-index:1000}.c-sidebar__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:var(--color-effect-overlay);opacity:0;transition:opacity .2s ease-in-out;z-index:999}.c-sidebar__backdrop--open{opacity:1}.c-sidebar__content{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--color-core-background-surface-floating);border-right:var(--size-border-width-sm) solid var(--color-core-border-soft);box-shadow:0 4px 8px 0 var(--color-effect-shadow-soft),0 0 4px 0 var(--color-effect-shadow-soft);position:fixed;top:0;left:0;z-index:1000;transform:translate(-100%);transition:transform .33s ease-out}@media (min-width: 768px){.c-sidebar__content{width:360px;max-width:360px}}.c-sidebar--visible .c-sidebar__content{transform:translate(0)}.c-sidebar--hide .c-sidebar__content{transform:translate(-100%)}.c-sidebar__header{padding:var(--space-component-padding-lg) var(--space-container-padding-md);border-bottom:var(--size-border-width-sm) solid var(--color-core-border-soft);background:var(--color-core-background-default);display:flex;align-items:center;justify-content:space-between;gap:var(--space-container-gap-sm)}.c-sidebar__header-content{height:2rem;display:flex;align-items:center;flex:1}.c-sidebar__header-title{flex:1;color:var(--color-core-content-default);font-family:var(--typography-label-lg-default-family, Satoshi);font-size:var(--typography-label-lg-default-size);font-style:normal;font-weight:var(--typography-label-lg-default-weight);line-height:var(--typography-label-lg-default-line-height);letter-spacing:var(--typography-label-lg-default-letter-spacing)}.c-sidebar__header-navigation{display:flex;align-items:center;gap:var(--space-container-gap-xs)}.c-sidebar__body{padding:var(--space-component-padding-sm);flex:1;overflow-y:auto}@media (min-width: 768px){.c-sidebar__body{padding:var(--space-component-padding-lg) var(--space-component-padding-md)}}.c-sidebar__footer{padding:var(--space-container-padding-sm);border-top:var(--size-border-width-sm) solid var(--color-core-border-soft);flex-shrink:0}.c-sidebar__footer--hidden{display:none}.c-sidebar__footer-content{display:flex;flex-direction:column;gap:var(--space-component-gap-xs)}\n"] }]
5946
6286
  }] });
5947
6287
 
5948
6288
  class SidebarService {
5949
6289
  appRef = inject(ApplicationRef);
5950
6290
  injector = inject(Injector);
5951
6291
  open(component, config = {}) {
5952
- const sidebarRef = createComponent(SidebarComponent, {
6292
+ const sidebarRef = createComponent(SidebarProgrammaticComponent, {
5953
6293
  environmentInjector: this.appRef.injector,
5954
6294
  elementInjector: this.injector,
5955
6295
  });
@@ -5975,35 +6315,7 @@ class SidebarService {
5975
6315
  // Append all remaining content to main container
5976
6316
  setTimeout(() => {
5977
6317
  sidebarRef.instance.setVisible(true);
5978
- const contentElement = contentRef.location.nativeElement;
5979
- const contentContainer = sidebarRef.location.nativeElement.querySelector('.c-sidebar__body');
5980
- const headerContainer = sidebarRef.location.nativeElement.querySelector('.c-sidebar__header-content');
5981
- const footerContainer = sidebarRef.location.nativeElement.querySelector('.c-sidebar__footer-content');
5982
- // Handle header content
5983
- const headerContent = contentElement.querySelector('[slot="header"]');
5984
- if (headerContent && headerContainer) {
5985
- const headerItems = headerContent.children;
5986
- Array.from(headerItems).forEach(item => {
5987
- headerContainer.appendChild(item);
5988
- });
5989
- headerContent.remove();
5990
- sidebarRef.instance.hasSlotHeader.set(true);
5991
- }
5992
- // Handle footer content
5993
- const footerContent = contentElement.querySelector('[slot="footer"]');
5994
- if (footerContent && footerContainer) {
5995
- const footerItems = footerContent.children;
5996
- Array.from(footerItems).forEach(item => {
5997
- footerContainer.appendChild(item);
5998
- });
5999
- footerContent.remove();
6000
- sidebarRef.instance.hasSlotFooter.set(true);
6001
- }
6002
- // Add remaining content to body
6003
- const remainingContent = contentElement.children;
6004
- Array.from(remainingContent).forEach(item => {
6005
- contentContainer.appendChild(item);
6006
- });
6318
+ this.moveContentToSidebar(contentRef, sidebarRef);
6007
6319
  }, 50);
6008
6320
  return {
6009
6321
  close: (resultValue) => {
@@ -6012,6 +6324,9 @@ class SidebarService {
6012
6324
  },
6013
6325
  afterClosed: () => afterClosedPromise,
6014
6326
  getContentComponent: () => contentRef.instance,
6327
+ updateTitle: (title) => {
6328
+ sidebarRef.instance.updateTitle(title);
6329
+ },
6015
6330
  };
6016
6331
  }
6017
6332
  handleClose(sidebarRef, contentRef, resolvePromise, config, result) {
@@ -6028,6 +6343,47 @@ class SidebarService {
6028
6343
  this.closeSidebar(sidebarRef, contentRef, resolvePromise, result);
6029
6344
  }
6030
6345
  }
6346
+ moveHeaderToSidebar(contentElement, sidebarRef) {
6347
+ const headerContainer = sidebarRef.location.nativeElement.querySelector('.c-sidebar__header-default');
6348
+ const headerContent = contentElement.querySelector('[slot="header"]');
6349
+ if (headerContent && headerContainer) {
6350
+ const headerItems = headerContent.children;
6351
+ Array.from(headerItems).forEach(item => {
6352
+ item.setAttribute('data-custom-header', 'true');
6353
+ headerContainer.appendChild(item);
6354
+ });
6355
+ headerContent.remove();
6356
+ sidebarRef.instance.hasSlotHeader.set(true);
6357
+ }
6358
+ }
6359
+ moveFooterToSidebar(contentElement, sidebarRef) {
6360
+ const footerContainer = sidebarRef.location.nativeElement.querySelector('.c-sidebar__footer-content');
6361
+ const footerContent = contentElement.querySelector('[slot="footer"]');
6362
+ if (footerContent && footerContainer) {
6363
+ const footerItems = footerContent.children;
6364
+ Array.from(footerItems).forEach(item => {
6365
+ footerContainer.appendChild(item);
6366
+ });
6367
+ footerContent.remove();
6368
+ }
6369
+ }
6370
+ moveContentToSidebar(contentRef, sidebarRef) {
6371
+ const contentElement = contentRef.location.nativeElement;
6372
+ const contentContainer = sidebarRef.location.nativeElement.querySelector('.c-sidebar__body');
6373
+ // Handle header content
6374
+ this.moveHeaderToSidebar(contentElement, sidebarRef);
6375
+ // Handle footer content
6376
+ this.moveFooterToSidebar(contentElement, sidebarRef);
6377
+ // Add remaining content to body
6378
+ const remainingContent = contentElement.children;
6379
+ Array.from(remainingContent).forEach(item => {
6380
+ contentContainer.appendChild(item);
6381
+ });
6382
+ // If no content was moved, try to move the entire content element
6383
+ if (remainingContent.length === 0) {
6384
+ contentContainer.appendChild(contentElement);
6385
+ }
6386
+ }
6031
6387
  closeSidebar(sidebarRef, contentRef, resolvePromise, result) {
6032
6388
  sidebarRef.instance.setVisible(false);
6033
6389
  setTimeout(() => {
@@ -6050,116 +6406,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
6050
6406
 
6051
6407
  class BasicSidebarMenuComponent {
6052
6408
  selectedItem;
6053
- selectedChildId = '';
6054
6409
  sidebar;
6055
- currentIndex = 0;
6056
6410
  menuItems = [];
6411
+ isInSettingsSubLevel = false;
6057
6412
  initializeComponent() {
6058
6413
  this.initializeMenuItems();
6059
- this.selectedItem = this.menuItems[0];
6060
- this.currentIndex = 0;
6061
- this.initializeSidebarTitle();
6062
- this.setupKeyboardNavigation();
6063
- }
6064
- initializeSidebarTitle() {
6065
- if (this.sidebar && !this.sidebar.title() && this.selectedItem) {
6066
- this.sidebar.title.set(this.selectedItem.label());
6067
- }
6068
6414
  }
6069
6415
  onItemClick(menuItem) {
6070
6416
  const label = menuItem.label();
6071
6417
  this.selectedItem = menuItem;
6072
- this.selectedChildId = '';
6073
- this.currentIndex = this.menuItems.findIndex(item => item === menuItem);
6074
- // Only set title if we don't have slot header content
6075
- if (this.sidebar && !this.sidebar.hasSlotHeader()) {
6076
- this.sidebar.title.set(label);
6418
+ if (this.hasSubNavigation(menuItem)) {
6419
+ this.navigateToSubLevel(menuItem);
6077
6420
  }
6078
- this.sidebar?.state.set('default');
6079
- if (this.sidebar) {
6080
- this.sidebar.onBackNavigation = () => this.onBackNavigation();
6421
+ else {
6422
+ if (this.sidebar && !this.sidebar.hasSlotHeader()) {
6423
+ this.sidebar.updateTitle(label);
6424
+ }
6425
+ this.sidebar?.state.set('default');
6081
6426
  }
6082
- console.log('Clicked item:', {
6083
- label: label,
6084
- element: menuItem,
6085
- index: this.currentIndex
6086
- });
6087
6427
  }
6088
- onChildClick(childLabel, parentItem) {
6089
- const parent = parentItem || this.menuItems[0];
6090
- this.selectedItem = parent;
6091
- this.selectedChildId = `${parent.label().toLowerCase()}-${childLabel.toLowerCase()}`;
6092
- // Only set title and navigation state if we don't have slot header content
6093
- if (this.sidebar && !this.sidebar.hasSlotHeader()) {
6094
- this.sidebar?.title.set(childLabel);
6095
- this.sidebar?.state.set('navigation');
6096
- this.sidebar.onBackNavigation = () => this.onBackNavigation();
6097
- }
6098
- console.log('Clicked child item:', {
6099
- label: childLabel,
6100
- parent: parent.label(),
6101
- selectedItem: this.selectedItem,
6102
- selectedChildId: this.selectedChildId
6103
- });
6428
+ hasSubNavigation(menuItem) {
6429
+ // Override this method in child components to define which items have sub-navigation
6430
+ return false;
6104
6431
  }
6105
- onBackNavigation() {
6106
- this.selectedItem = this.menuItems[0];
6107
- this.selectedChildId = '';
6108
- this.currentIndex = 0;
6109
- // Only set title if we don't have slot header content
6110
- if (this.sidebar && !this.sidebar.hasSlotHeader()) {
6111
- this.sidebar.title.set(this.menuItems[0].label());
6432
+ navigateToSubLevel(menuItem) {
6433
+ this.isInSettingsSubLevel = true;
6434
+ if (this.sidebar) {
6435
+ this.sidebar.updateTitle(menuItem.label());
6436
+ this.sidebar.state.set('navigation');
6112
6437
  }
6113
- this.sidebar?.state.set('default');
6114
- console.log('Back navigation to', this.menuItems[0].label());
6438
+ }
6439
+ navigateToMainLevel() {
6440
+ this.isInSettingsSubLevel = false;
6115
6441
  }
6116
6442
  onFooterItemClick(menuItem) {
6117
6443
  const label = menuItem.label();
6118
6444
  this.selectedItem = menuItem;
6119
- this.selectedChildId = '';
6120
- this.sidebar?.title.set(label);
6121
- this.sidebar?.state.set('default');
6122
6445
  if (this.sidebar) {
6123
- this.sidebar.onBackNavigation = () => this.onBackNavigation();
6124
- }
6125
- console.log('Footer item clicked:', {
6126
- label: label,
6127
- element: menuItem
6128
- });
6129
- }
6130
- setupKeyboardNavigation() {
6131
- if (this.sidebar) {
6132
- this.sidebar.onArrowKeyNavigation = (direction) => {
6133
- this.navigateMenu(direction);
6134
- };
6135
- }
6136
- }
6137
- navigateMenu(direction) {
6138
- if (!this.menuItems.length) {
6139
- return;
6140
- }
6141
- if (direction === 'down') {
6142
- this.currentIndex = (this.currentIndex + 1) % this.menuItems.length;
6143
- }
6144
- else {
6145
- this.currentIndex = this.currentIndex === 0 ? this.menuItems.length - 1 : this.currentIndex - 1;
6146
- }
6147
- const newItem = this.menuItems[this.currentIndex];
6148
- this.selectedItem = newItem;
6149
- this.selectedChildId = '';
6150
- // Only set title if we don't have slot header content
6151
- if (this.sidebar && !this.sidebar.hasSlotHeader()) {
6152
- this.sidebar.title.set(newItem.label());
6153
- }
6154
- this.sidebar?.state.set('default');
6155
- if (this.sidebar) {
6156
- this.sidebar.onBackNavigation = () => this.onBackNavigation();
6446
+ this.sidebar.title.set(label);
6447
+ this.sidebar.state.set('default');
6157
6448
  }
6158
- console.log('Keyboard navigation:', {
6159
- direction,
6160
- newIndex: this.currentIndex,
6161
- label: newItem.label()
6162
- });
6163
6449
  }
6164
6450
  }
6165
6451
  class SidebarWithFooterComponent extends BasicSidebarMenuComponent {
@@ -6167,29 +6453,24 @@ class SidebarWithFooterComponent extends BasicSidebarMenuComponent {
6167
6453
  settingsItem;
6168
6454
  profileItem;
6169
6455
  helpItem;
6456
+ // Sub-level items
6457
+ generalSettingsItem;
6458
+ privacySettingsItem;
6459
+ notificationsSettingsItem;
6460
+ securitySettingsItem;
6461
+ selectedSubItem;
6170
6462
  ngAfterViewInit() {
6171
6463
  this.initializeComponent();
6172
6464
  }
6173
- dashboardChildren = [
6174
- {
6175
- id: 'dashboard-analytics',
6176
- label: 'Analytics',
6177
- selected: false,
6178
- onClick: () => this.onChildClick('Analytics', this.dashboardItem)
6179
- },
6180
- {
6181
- id: 'dashboard-reports',
6182
- label: 'Reports',
6183
- selected: false,
6184
- onClick: () => this.onChildClick('Reports', this.dashboardItem)
6185
- },
6186
- {
6187
- id: 'dashboard-overview',
6188
- label: 'Overview',
6189
- selected: false,
6190
- onClick: () => this.onChildClick('Overview', this.dashboardItem)
6191
- }
6192
- ];
6465
+ hasSubNavigation(menuItem) {
6466
+ return menuItem === this.settingsItem;
6467
+ }
6468
+ onSubItemClick(subItem) {
6469
+ this.selectedSubItem = subItem;
6470
+ if (this.sidebar && !this.sidebar.hasSlotHeader()) {
6471
+ this.sidebar.updateTitle(subItem.label());
6472
+ }
6473
+ }
6193
6474
  initializeMenuItems() {
6194
6475
  this.menuItems = [
6195
6476
  this.dashboardItem,
@@ -6199,13 +6480,24 @@ class SidebarWithFooterComponent extends BasicSidebarMenuComponent {
6199
6480
  ];
6200
6481
  }
6201
6482
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarWithFooterComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6202
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.7", type: SidebarWithFooterComponent, isStandalone: true, selector: "lib-sidebar-with-footer", viewQueries: [{ propertyName: "dashboardItem", first: true, predicate: ["dashboardItem"], descendants: true }, { propertyName: "settingsItem", first: true, predicate: ["settingsItem"], descendants: true }, { propertyName: "profileItem", first: true, predicate: ["profileItem"], descendants: true }, { propertyName: "helpItem", first: true, predicate: ["helpItem"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
6483
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.7", type: SidebarWithFooterComponent, isStandalone: true, selector: "lib-sidebar-with-footer", viewQueries: [{ propertyName: "dashboardItem", first: true, predicate: ["dashboardItem"], descendants: true }, { propertyName: "settingsItem", first: true, predicate: ["settingsItem"], descendants: true }, { propertyName: "profileItem", first: true, predicate: ["profileItem"], descendants: true }, { propertyName: "helpItem", first: true, predicate: ["helpItem"], descendants: true }, { propertyName: "generalSettingsItem", first: true, predicate: ["generalSettingsItem"], descendants: true }, { propertyName: "privacySettingsItem", first: true, predicate: ["privacySettingsItem"], descendants: true }, { propertyName: "notificationsSettingsItem", first: true, predicate: ["notificationsSettingsItem"], descendants: true }, { propertyName: "securitySettingsItem", first: true, predicate: ["securitySettingsItem"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
6484
+ @if (sidebar?.state() === 'default') {
6485
+ <div slot="header">
6486
+ <div style="display: flex; align-items: center; gap: 12px; padding: 16px;">
6487
+ <div style="width: 32px; height: 32px; background: #17a2b8; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold;">
6488
+ L
6489
+ </div>
6490
+ <div>
6491
+ <h3 style="margin: 0; font-size: 16px; font-weight: 600; color: var(--color-core-content-default);">My App</h3>
6492
+ <p style="margin: 0; font-size: 12px; color: var(--color-core-content-secondary);">Welcome back!</p>
6493
+ </div>
6494
+ </div>
6495
+ </div>
6203
6496
  <lib-menu-item
6204
6497
  #dashboardItem
6205
6498
  label="Dashboard"
6206
6499
  icon="home-regular"
6207
6500
  [selected]="selectedItem === dashboardItem"
6208
- [children]="dashboardChildren"
6209
6501
  (clicked)="onItemClick(dashboardItem)">
6210
6502
  </lib-menu-item>
6211
6503
  <lib-menu-item
@@ -6241,109 +6533,46 @@ class SidebarWithFooterComponent extends BasicSidebarMenuComponent {
6241
6533
  (clicked)="onFooterItemClick(logoutItem)">
6242
6534
  </lib-menu-item>
6243
6535
  </div>
6244
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: MenuItemComponent, selector: "lib-menu-item", inputs: ["label", "icon", "disabled", "selected", "showArrowIcon", "tagLabel", "children"], outputs: ["clicked"] }] });
6245
- }
6246
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarWithFooterComponent, decorators: [{
6247
- type: Component,
6248
- args: [{
6249
- selector: 'lib-sidebar-with-footer',
6250
- template: `
6536
+ }
6537
+ <!-- Settings Sub-Level -->
6538
+ @if (sidebar?.state() === 'navigation' && isInSettingsSubLevel) {
6251
6539
  <lib-menu-item
6252
- #dashboardItem
6253
- label="Dashboard"
6254
- icon="home-regular"
6255
- [selected]="selectedItem === dashboardItem"
6256
- [children]="dashboardChildren"
6257
- (clicked)="onItemClick(dashboardItem)">
6540
+ #generalSettingsItem
6541
+ label="General"
6542
+ icon="settings-regular"
6543
+ [selected]="selectedSubItem === generalSettingsItem"
6544
+ (clicked)="onSubItemClick(generalSettingsItem)">
6258
6545
  </lib-menu-item>
6259
6546
  <lib-menu-item
6260
- #settingsItem
6261
- label="Settings"
6262
- icon="settings-regular"
6263
- [selected]="selectedItem === settingsItem"
6264
- (clicked)="onItemClick(settingsItem)">
6547
+ #privacySettingsItem
6548
+ label="Privacy"
6549
+ icon="shield-regular"
6550
+ [selected]="selectedSubItem === privacySettingsItem"
6551
+ (clicked)="onSubItemClick(privacySettingsItem)">
6265
6552
  </lib-menu-item>
6266
6553
  <lib-menu-item
6267
- #profileItem
6268
- label="Profile"
6269
- icon="user-regular"
6270
- tagLabel="New"
6271
- [selected]="selectedItem === profileItem"
6272
- (clicked)="onItemClick(profileItem)">
6554
+ #notificationsSettingsItem
6555
+ label="Notifications"
6556
+ icon="bell-regular"
6557
+ [selected]="selectedSubItem === notificationsSettingsItem"
6558
+ (clicked)="onSubItemClick(notificationsSettingsItem)">
6273
6559
  </lib-menu-item>
6274
6560
  <lib-menu-item
6275
- #helpItem
6276
- label="Help"
6277
- icon="question-regular"
6278
- [selected]="selectedItem === helpItem"
6279
- (clicked)="onItemClick(helpItem)">
6561
+ #securitySettingsItem
6562
+ label="Security"
6563
+ icon="lock-regular"
6564
+ [selected]="selectedSubItem === securitySettingsItem"
6565
+ (clicked)="onSubItemClick(securitySettingsItem)">
6280
6566
  </lib-menu-item>
6281
-
6282
- <div slot="footer">
6283
- <lib-menu-item
6284
- #logoutItem
6285
- label="Logout"
6286
- icon="signout-regular"
6287
- [showArrowIcon]="false"
6288
- [selected]="selectedItem === logoutItem"
6289
- (clicked)="onFooterItemClick(logoutItem)">
6290
- </lib-menu-item>
6291
- </div>
6292
- `,
6293
- imports: [CommonModule, MenuItemComponent, MenuChildItemComponent],
6294
- standalone: true,
6295
- }]
6296
- }], propDecorators: { dashboardItem: [{
6297
- type: ViewChild,
6298
- args: ['dashboardItem']
6299
- }], settingsItem: [{
6300
- type: ViewChild,
6301
- args: ['settingsItem']
6302
- }], profileItem: [{
6303
- type: ViewChild,
6304
- args: ['profileItem']
6305
- }], helpItem: [{
6306
- type: ViewChild,
6307
- args: ['helpItem']
6308
- }] } });
6309
- class SidebarWithHeaderComponent extends BasicSidebarMenuComponent {
6310
- dashboardItem;
6311
- settingsItem;
6312
- profileItem;
6313
- helpItem;
6314
- ngAfterViewInit() {
6315
- this.initializeComponent();
6316
6567
  }
6317
- dashboardChildren = [
6318
- {
6319
- id: 'dashboard-analytics',
6320
- label: 'Analytics',
6321
- selected: false,
6322
- onClick: () => this.onChildClick('Analytics', this.dashboardItem)
6323
- },
6324
- {
6325
- id: 'dashboard-reports',
6326
- label: 'Reports',
6327
- selected: false,
6328
- onClick: () => this.onChildClick('Reports', this.dashboardItem)
6329
- },
6330
- {
6331
- id: 'dashboard-overview',
6332
- label: 'Overview',
6333
- selected: false,
6334
- onClick: () => this.onChildClick('Overview', this.dashboardItem)
6335
- }
6336
- ];
6337
- initializeMenuItems() {
6338
- this.menuItems = [
6339
- this.dashboardItem,
6340
- this.settingsItem,
6341
- this.profileItem,
6342
- this.helpItem
6343
- ];
6344
- }
6345
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarWithHeaderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
6346
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.7", type: SidebarWithHeaderComponent, isStandalone: true, selector: "lib-sidebar-with-header", viewQueries: [{ propertyName: "dashboardItem", first: true, predicate: ["dashboardItem"], descendants: true }, { propertyName: "settingsItem", first: true, predicate: ["settingsItem"], descendants: true }, { propertyName: "profileItem", first: true, predicate: ["profileItem"], descendants: true }, { propertyName: "helpItem", first: true, predicate: ["helpItem"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
6568
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: MenuItemComponent, selector: "lib-menu-item", inputs: ["label", "icon", "disabled", "selected", "showArrowIcon", "tagLabel", "children"], outputs: ["clicked"] }] });
6569
+ }
6570
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarWithFooterComponent, decorators: [{
6571
+ type: Component,
6572
+ args: [{
6573
+ selector: 'lib-sidebar-with-footer',
6574
+ template: `
6575
+ @if (sidebar?.state() === 'default') {
6347
6576
  <div slot="header">
6348
6577
  <div style="display: flex; align-items: center; gap: 12px; padding: 16px;">
6349
6578
  <div style="width: 32px; height: 32px; background: #17a2b8; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold;">
@@ -6355,13 +6584,11 @@ class SidebarWithHeaderComponent extends BasicSidebarMenuComponent {
6355
6584
  </div>
6356
6585
  </div>
6357
6586
  </div>
6358
-
6359
6587
  <lib-menu-item
6360
6588
  #dashboardItem
6361
6589
  label="Dashboard"
6362
6590
  icon="home-regular"
6363
6591
  [selected]="selectedItem === dashboardItem"
6364
- [children]="dashboardChildren"
6365
6592
  (clicked)="onItemClick(dashboardItem)">
6366
6593
  </lib-menu-item>
6367
6594
  <lib-menu-item
@@ -6386,57 +6613,51 @@ class SidebarWithHeaderComponent extends BasicSidebarMenuComponent {
6386
6613
  [selected]="selectedItem === helpItem"
6387
6614
  (clicked)="onItemClick(helpItem)">
6388
6615
  </lib-menu-item>
6389
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: MenuItemComponent, selector: "lib-menu-item", inputs: ["label", "icon", "disabled", "selected", "showArrowIcon", "tagLabel", "children"], outputs: ["clicked"] }] });
6390
- }
6391
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarWithHeaderComponent, decorators: [{
6392
- type: Component,
6393
- args: [{
6394
- selector: 'lib-sidebar-with-header',
6395
- template: `
6396
- <div slot="header">
6397
- <div style="display: flex; align-items: center; gap: 12px; padding: 16px;">
6398
- <div style="width: 32px; height: 32px; background: #17a2b8; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold;">
6399
- L
6400
- </div>
6401
- <div>
6402
- <h3 style="margin: 0; font-size: 16px; font-weight: 600; color: var(--color-core-content-default);">My App</h3>
6403
- <p style="margin: 0; font-size: 12px; color: var(--color-core-content-secondary);">Welcome back!</p>
6404
- </div>
6405
- </div>
6406
- </div>
6407
6616
 
6617
+ <div slot="footer">
6618
+ <lib-menu-item
6619
+ #logoutItem
6620
+ label="Logout"
6621
+ icon="signout-regular"
6622
+ [showArrowIcon]="false"
6623
+ [selected]="selectedItem === logoutItem"
6624
+ (clicked)="onFooterItemClick(logoutItem)">
6625
+ </lib-menu-item>
6626
+ </div>
6627
+ }
6628
+ <!-- Settings Sub-Level -->
6629
+ @if (sidebar?.state() === 'navigation' && isInSettingsSubLevel) {
6408
6630
  <lib-menu-item
6409
- #dashboardItem
6410
- label="Dashboard"
6411
- icon="home-regular"
6412
- [selected]="selectedItem === dashboardItem"
6413
- [children]="dashboardChildren"
6414
- (clicked)="onItemClick(dashboardItem)">
6631
+ #generalSettingsItem
6632
+ label="General"
6633
+ icon="settings-regular"
6634
+ [selected]="selectedSubItem === generalSettingsItem"
6635
+ (clicked)="onSubItemClick(generalSettingsItem)">
6415
6636
  </lib-menu-item>
6416
6637
  <lib-menu-item
6417
- #settingsItem
6418
- label="Settings"
6419
- icon="settings-regular"
6420
- [selected]="selectedItem === settingsItem"
6421
- (clicked)="onItemClick(settingsItem)">
6638
+ #privacySettingsItem
6639
+ label="Privacy"
6640
+ icon="shield-regular"
6641
+ [selected]="selectedSubItem === privacySettingsItem"
6642
+ (clicked)="onSubItemClick(privacySettingsItem)">
6422
6643
  </lib-menu-item>
6423
6644
  <lib-menu-item
6424
- #profileItem
6425
- label="Profile"
6426
- icon="user-regular"
6427
- tagLabel="New"
6428
- [selected]="selectedItem === profileItem"
6429
- (clicked)="onItemClick(profileItem)">
6645
+ #notificationsSettingsItem
6646
+ label="Notifications"
6647
+ icon="bell-regular"
6648
+ [selected]="selectedSubItem === notificationsSettingsItem"
6649
+ (clicked)="onSubItemClick(notificationsSettingsItem)">
6430
6650
  </lib-menu-item>
6431
6651
  <lib-menu-item
6432
- #helpItem
6433
- label="Help"
6434
- icon="question-regular"
6435
- [selected]="selectedItem === helpItem"
6436
- (clicked)="onItemClick(helpItem)">
6652
+ #securitySettingsItem
6653
+ label="Security"
6654
+ icon="lock-regular"
6655
+ [selected]="selectedSubItem === securitySettingsItem"
6656
+ (clicked)="onSubItemClick(securitySettingsItem)">
6437
6657
  </lib-menu-item>
6658
+ }
6438
6659
  `,
6439
- imports: [CommonModule, MenuItemComponent, MenuChildItemComponent],
6660
+ imports: [CommonModule, MenuItemComponent],
6440
6661
  standalone: true,
6441
6662
  }]
6442
6663
  }], propDecorators: { dashboardItem: [{
@@ -6451,8 +6672,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
6451
6672
  }], helpItem: [{
6452
6673
  type: ViewChild,
6453
6674
  args: ['helpItem']
6675
+ }], generalSettingsItem: [{
6676
+ type: ViewChild,
6677
+ args: ['generalSettingsItem']
6678
+ }], privacySettingsItem: [{
6679
+ type: ViewChild,
6680
+ args: ['privacySettingsItem']
6681
+ }], notificationsSettingsItem: [{
6682
+ type: ViewChild,
6683
+ args: ['notificationsSettingsItem']
6684
+ }], securitySettingsItem: [{
6685
+ type: ViewChild,
6686
+ args: ['securitySettingsItem']
6454
6687
  }] } });
6455
- class SidebarExamplesComponent {
6688
+ class SidebarProgrammaticExamplesComponent {
6456
6689
  sidebarService = inject(SidebarService);
6457
6690
  openSidebarWithFooter() {
6458
6691
  const sidebarRef = this.sidebarService.open(SidebarWithFooterComponent, {
@@ -6462,24 +6695,12 @@ class SidebarExamplesComponent {
6462
6695
  });
6463
6696
  sidebarRef.afterClosed().then((result) => {
6464
6697
  if (result) {
6465
- console.log('Sidebar result:', result);
6698
+ console.log('Sidebar closed with result:', result);
6466
6699
  }
6467
6700
  });
6468
6701
  }
6469
- openSidebarWithHeader() {
6470
- const sidebarRef = this.sidebarService.open(SidebarWithHeaderComponent, {
6471
- onClose: (closeSidebar) => {
6472
- closeSidebar({ message: 'Sidebar closed successfully' });
6473
- }
6474
- });
6475
- sidebarRef.afterClosed().then((result) => {
6476
- if (result) {
6477
- console.log('✅ Sidebar result:', result);
6478
- }
6479
- });
6480
- }
6481
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarExamplesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6482
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.7", type: SidebarExamplesComponent, isStandalone: true, selector: "lib-sidebar-examples", ngImport: i0, template: `
6702
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarProgrammaticExamplesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6703
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.7", type: SidebarProgrammaticExamplesComponent, isStandalone: true, selector: "lib-sidebar-examples", ngImport: i0, template: `
6483
6704
  <div
6484
6705
  style="height: 90vh; padding: 24px; font-family: var(--typography-body-md-family), sans-serif;
6485
6706
  font-weight: var(--typography-body-md-weight);
@@ -6490,8 +6711,8 @@ class SidebarExamplesComponent {
6490
6711
  >
6491
6712
  <h2>Sidebar Service Examples</h2>
6492
6713
  <p>
6493
- This demonstrates how to use the Sidebar Service for programmatic sidebar
6494
- opening with dynamic component content.
6714
+ This demonstrates how to use the Sidebar Service with two-level navigation.
6715
+ Click on "Settings" to see the sub-navigation level.
6495
6716
  </p>
6496
6717
 
6497
6718
  <div style="margin: 24px 0;">
@@ -6510,127 +6731,17 @@ class SidebarExamplesComponent {
6510
6731
  font-size: 14px;
6511
6732
  font-weight: 500;
6512
6733
  ">
6513
- Open Sidebar with Footer
6514
- </button>
6515
- <button
6516
- (click)="openSidebarWithHeader()"
6517
- style="
6518
- background: #17a2b8;
6519
- color: white;
6520
- border: none;
6521
- padding: 12px 24px;
6522
- border-radius: 6px;
6523
- cursor: pointer;
6524
- font-size: 14px;
6525
- font-weight: 500;
6526
- ">
6527
- Open Sidebar with custom Header
6734
+ Open Sidebar with Two-Level Navigation
6528
6735
  </button>
6529
6736
  </div>
6530
6737
  </div>
6531
-
6532
- <div
6533
- style="margin-top: 24px; padding: 20px; background: #e3f2fd; border-radius: 8px; border: 1px solid #2196f3;"
6534
- >
6535
- <h3>Configuration Options Available:</h3>
6536
- <ul style="margin: 0; padding-left: 20px;">
6537
- <li><strong>title</strong>: string - Sidebar header title (if not provided, uses slot="header")</li>
6538
- <li><strong>state</strong>: 'default' | 'navigation' - Sidebar state (default: 'default')</li>
6539
- <li><strong>collapsible</strong>: boolean - Whether sidebar can be opened/closed (default: true)</li>
6540
- <li><strong>onClose</strong>: function - Close event handler with result parameter</li>
6541
- </ul>
6542
- </div>
6543
-
6544
- <div
6545
- style="margin-top: 24px; padding: 20px; background: #f8f9fa; border-radius: 8px; border: 1px solid #6c757d;"
6546
- >
6547
- <h3>Header Content Options:</h3>
6548
- <ul style="margin: 0; padding-left: 20px;">
6549
- <li><strong>With title</strong>: Pass <code>title: "My Title"</code> in config</li>
6550
- <li><strong>Custom HTML</strong>: Use slot="header" for any custom header content</li>
6551
- </ul>
6552
-
6553
- <pre style="background: #e9ecef; padding: 12px; border-radius: 4px; font-size: 12px; overflow-x: auto; margin-top: 8px;">
6554
- // In your component template:
6555
- &lt;div slot="header"&gt;
6556
- &lt;a class="logo" [routerLink]="state.language()" tabindex="0"&gt;
6557
- &lt;img
6558
- class="logo-full"
6559
- ngSrc="{{ '{' }}{{ 'img/branding/logo_full.svg' }}{{ '}' }}"
6560
- alt="logo"
6561
- width="130"
6562
- height="32" /&gt;
6563
- &lt;/a&gt;
6564
- &lt;/div&gt;
6565
-
6566
- &lt;lib-menu-item
6567
- label="Dashboard"
6568
- icon="home-regular"
6569
- [selected]="selectedItem === dashboardItem"
6570
- [children]="dashboardChildren"
6571
- (clicked)="onItemClick(dashboardItem)"&gt;
6572
- &lt;/lib-menu-item&gt;
6573
- &lt;lib-menu-item
6574
- label="Settings"
6575
- icon="settings-regular"
6576
- [selected]="selectedItem === settingsItem"
6577
- [children]="settingsChildren"
6578
- (clicked)="onItemClick(settingsItem)"&gt;
6579
- &lt;/lib-menu-item&gt;
6580
- </pre>
6581
- </div>
6582
-
6583
- <div
6584
- style="margin-top: 24px; padding: 20px; background: #f3e5f5; border-radius: 8px; border: 1px solid #9c27b0;"
6585
- >
6586
- <h3>Footer Content:</h3>
6587
- <p style="margin: 0 0 12px 0;">Use <code>[slot="footer"]</code> to add footer content:</p>
6588
- <pre style="background: #e9ecef; padding: 12px; border-radius: 4px; font-size: 12px; overflow-x: auto; margin-top: 8px;">
6589
- // In your component template:
6590
- &lt;lib-menu-item label="Dashboard" icon="home-regular"&gt;&lt;/lib-menu-item&gt;
6591
- &lt;lib-menu-item label="Settings" icon="settings-regular"&gt;&lt;/lib-menu-item&gt;
6592
-
6593
- &lt;!-- Footer content --&gt;
6594
- &lt;div slot="footer"&gt;
6595
- &lt;lib-menu-item
6596
- label="Logout"
6597
- icon="signout-regular"
6598
- [showArrowIcon]="false"&gt;
6599
- &lt;/lib-menu-item&gt;
6600
- &lt;/div&gt;
6601
- </pre>
6602
- </div>
6603
-
6604
- <div
6605
- style="margin-top: 24px; padding: 20px; background: #e8f5e8; border-radius: 8px; border: 1px solid #4caf50;"
6606
- >
6607
- <h3>Keyboard Navigation:</h3>
6608
- <ul style="margin: 0; padding-left: 20px;">
6609
- <li><strong>Arrow Down (↓)</strong>: Navigate to next item or first child</li>
6610
- <li><strong>Arrow Up (↑)</strong>: Navigate to previous item or parent</li>
6611
- <li><strong>Escape</strong>: Close sidebar</li>
6612
- <li><strong>Click outside</strong>: Close sidebar</li>
6613
- </ul>
6614
- </div>
6615
-
6616
- <div
6617
- style="margin-top: 24px; padding: 20px; background: #d1ecf1; border-radius: 8px; border: 1px solid #17a2b8;"
6618
- >
6619
- <h3>Check Console for Results:</h3>
6620
- <p>
6621
- Open your browser's developer console to see the callback results and
6622
- sidebar interactions.
6623
- </p>
6624
- </div>
6738
+
6625
6739
  </div>
6626
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
6740
+ `, isInline: true, styles: [".sidebar-content{display:flex;flex-direction:column;height:100%;padding:24px;font-family:var(--typography-body-md-family)}.sidebar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px;padding-bottom:16px;border-bottom:1px solid var(--color-core-border-default)}.sidebar-header h2{margin:0;font-size:var(--typography-heading-md-size);font-weight:var(--typography-heading-md-weight);color:var(--color-core-content-default)}.sidebar-body{flex:1;display:flex;flex-direction:column;gap:24px}.user-info{display:flex;align-items:center;gap:16px}.avatar{width:48px;height:48px;border-radius:50%;background:var(--color-core-background-secondary);display:flex;align-items:center;justify-content:center}.avatar-placeholder{font-weight:600;font-size:18px;color:var(--color-core-content-default)}.user-details h3{margin:0 0 4px;font-size:var(--typography-body-lg-size);font-weight:var(--typography-body-lg-weight);color:var(--color-core-content-default)}.user-details p{margin:0;font-size:var(--typography-body-sm-size);color:var(--color-core-content-secondary)}.role{font-weight:500;color:var(--color-core-content-default)!important}.actions-section h4,.stats-section h4{margin:0 0 12px;font-size:var(--typography-body-md-size);font-weight:600;color:var(--color-core-content-default)}.action-buttons{display:flex;flex-direction:column;gap:8px}.stats-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.stat-item{text-align:center;padding:12px;background:var(--color-core-background-secondary);border-radius:8px}.stat-value{display:block;font-size:var(--typography-heading-sm-size);font-weight:var(--typography-heading-sm-weight);color:var(--color-core-content-default)}.stat-label{display:block;font-size:var(--typography-body-xs-size);color:var(--color-core-content-secondary);margin-top:4px}.sidebar-footer{padding-top:16px;border-top:1px solid var(--color-core-border-default)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
6627
6741
  }
6628
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarExamplesComponent, decorators: [{
6742
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarProgrammaticExamplesComponent, decorators: [{
6629
6743
  type: Component,
6630
- args: [{
6631
- selector: 'lib-sidebar-examples',
6632
- imports: [CommonModule],
6633
- template: `
6744
+ args: [{ selector: 'lib-sidebar-examples', imports: [CommonModule], template: `
6634
6745
  <div
6635
6746
  style="height: 90vh; padding: 24px; font-family: var(--typography-body-md-family), sans-serif;
6636
6747
  font-weight: var(--typography-body-md-weight);
@@ -6641,8 +6752,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
6641
6752
  >
6642
6753
  <h2>Sidebar Service Examples</h2>
6643
6754
  <p>
6644
- This demonstrates how to use the Sidebar Service for programmatic sidebar
6645
- opening with dynamic component content.
6755
+ This demonstrates how to use the Sidebar Service with two-level navigation.
6756
+ Click on "Settings" to see the sub-navigation level.
6646
6757
  </p>
6647
6758
 
6648
6759
  <div style="margin: 24px 0;">
@@ -6661,121 +6772,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
6661
6772
  font-size: 14px;
6662
6773
  font-weight: 500;
6663
6774
  ">
6664
- Open Sidebar with Footer
6665
- </button>
6666
- <button
6667
- (click)="openSidebarWithHeader()"
6668
- style="
6669
- background: #17a2b8;
6670
- color: white;
6671
- border: none;
6672
- padding: 12px 24px;
6673
- border-radius: 6px;
6674
- cursor: pointer;
6675
- font-size: 14px;
6676
- font-weight: 500;
6677
- ">
6678
- Open Sidebar with custom Header
6775
+ Open Sidebar with Two-Level Navigation
6679
6776
  </button>
6680
6777
  </div>
6681
6778
  </div>
6682
-
6683
- <div
6684
- style="margin-top: 24px; padding: 20px; background: #e3f2fd; border-radius: 8px; border: 1px solid #2196f3;"
6685
- >
6686
- <h3>Configuration Options Available:</h3>
6687
- <ul style="margin: 0; padding-left: 20px;">
6688
- <li><strong>title</strong>: string - Sidebar header title (if not provided, uses slot="header")</li>
6689
- <li><strong>state</strong>: 'default' | 'navigation' - Sidebar state (default: 'default')</li>
6690
- <li><strong>collapsible</strong>: boolean - Whether sidebar can be opened/closed (default: true)</li>
6691
- <li><strong>onClose</strong>: function - Close event handler with result parameter</li>
6692
- </ul>
6693
- </div>
6694
-
6695
- <div
6696
- style="margin-top: 24px; padding: 20px; background: #f8f9fa; border-radius: 8px; border: 1px solid #6c757d;"
6697
- >
6698
- <h3>Header Content Options:</h3>
6699
- <ul style="margin: 0; padding-left: 20px;">
6700
- <li><strong>With title</strong>: Pass <code>title: "My Title"</code> in config</li>
6701
- <li><strong>Custom HTML</strong>: Use slot="header" for any custom header content</li>
6702
- </ul>
6703
-
6704
- <pre style="background: #e9ecef; padding: 12px; border-radius: 4px; font-size: 12px; overflow-x: auto; margin-top: 8px;">
6705
- // In your component template:
6706
- &lt;div slot="header"&gt;
6707
- &lt;a class="logo" [routerLink]="state.language()" tabindex="0"&gt;
6708
- &lt;img
6709
- class="logo-full"
6710
- ngSrc="{{ '{' }}{{ 'img/branding/logo_full.svg' }}{{ '}' }}"
6711
- alt="logo"
6712
- width="130"
6713
- height="32" /&gt;
6714
- &lt;/a&gt;
6715
- &lt;/div&gt;
6716
-
6717
- &lt;lib-menu-item
6718
- label="Dashboard"
6719
- icon="home-regular"
6720
- [selected]="selectedItem === dashboardItem"
6721
- [children]="dashboardChildren"
6722
- (clicked)="onItemClick(dashboardItem)"&gt;
6723
- &lt;/lib-menu-item&gt;
6724
- &lt;lib-menu-item
6725
- label="Settings"
6726
- icon="settings-regular"
6727
- [selected]="selectedItem === settingsItem"
6728
- [children]="settingsChildren"
6729
- (clicked)="onItemClick(settingsItem)"&gt;
6730
- &lt;/lib-menu-item&gt;
6731
- </pre>
6732
- </div>
6733
-
6734
- <div
6735
- style="margin-top: 24px; padding: 20px; background: #f3e5f5; border-radius: 8px; border: 1px solid #9c27b0;"
6736
- >
6737
- <h3>Footer Content:</h3>
6738
- <p style="margin: 0 0 12px 0;">Use <code>[slot="footer"]</code> to add footer content:</p>
6739
- <pre style="background: #e9ecef; padding: 12px; border-radius: 4px; font-size: 12px; overflow-x: auto; margin-top: 8px;">
6740
- // In your component template:
6741
- &lt;lib-menu-item label="Dashboard" icon="home-regular"&gt;&lt;/lib-menu-item&gt;
6742
- &lt;lib-menu-item label="Settings" icon="settings-regular"&gt;&lt;/lib-menu-item&gt;
6743
-
6744
- &lt;!-- Footer content --&gt;
6745
- &lt;div slot="footer"&gt;
6746
- &lt;lib-menu-item
6747
- label="Logout"
6748
- icon="signout-regular"
6749
- [showArrowIcon]="false"&gt;
6750
- &lt;/lib-menu-item&gt;
6751
- &lt;/div&gt;
6752
- </pre>
6753
- </div>
6754
-
6755
- <div
6756
- style="margin-top: 24px; padding: 20px; background: #e8f5e8; border-radius: 8px; border: 1px solid #4caf50;"
6757
- >
6758
- <h3>Keyboard Navigation:</h3>
6759
- <ul style="margin: 0; padding-left: 20px;">
6760
- <li><strong>Arrow Down (↓)</strong>: Navigate to next item or first child</li>
6761
- <li><strong>Arrow Up (↑)</strong>: Navigate to previous item or parent</li>
6762
- <li><strong>Escape</strong>: Close sidebar</li>
6763
- <li><strong>Click outside</strong>: Close sidebar</li>
6764
- </ul>
6765
- </div>
6766
-
6767
- <div
6768
- style="margin-top: 24px; padding: 20px; background: #d1ecf1; border-radius: 8px; border: 1px solid #17a2b8;"
6769
- >
6770
- <h3>Check Console for Results:</h3>
6771
- <p>
6772
- Open your browser's developer console to see the callback results and
6773
- sidebar interactions.
6774
- </p>
6775
- </div>
6779
+
6776
6780
  </div>
6777
- `,
6778
- }]
6781
+ `, standalone: true, styles: [".sidebar-content{display:flex;flex-direction:column;height:100%;padding:24px;font-family:var(--typography-body-md-family)}.sidebar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px;padding-bottom:16px;border-bottom:1px solid var(--color-core-border-default)}.sidebar-header h2{margin:0;font-size:var(--typography-heading-md-size);font-weight:var(--typography-heading-md-weight);color:var(--color-core-content-default)}.sidebar-body{flex:1;display:flex;flex-direction:column;gap:24px}.user-info{display:flex;align-items:center;gap:16px}.avatar{width:48px;height:48px;border-radius:50%;background:var(--color-core-background-secondary);display:flex;align-items:center;justify-content:center}.avatar-placeholder{font-weight:600;font-size:18px;color:var(--color-core-content-default)}.user-details h3{margin:0 0 4px;font-size:var(--typography-body-lg-size);font-weight:var(--typography-body-lg-weight);color:var(--color-core-content-default)}.user-details p{margin:0;font-size:var(--typography-body-sm-size);color:var(--color-core-content-secondary)}.role{font-weight:500;color:var(--color-core-content-default)!important}.actions-section h4,.stats-section h4{margin:0 0 12px;font-size:var(--typography-body-md-size);font-weight:600;color:var(--color-core-content-default)}.action-buttons{display:flex;flex-direction:column;gap:8px}.stats-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.stat-item{text-align:center;padding:12px;background:var(--color-core-background-secondary);border-radius:8px}.stat-value{display:block;font-size:var(--typography-heading-sm-size);font-weight:var(--typography-heading-sm-weight);color:var(--color-core-content-default)}.stat-label{display:block;font-size:var(--typography-body-xs-size);color:var(--color-core-content-secondary);margin-top:4px}.sidebar-footer{padding-top:16px;border-top:1px solid var(--color-core-border-default)}\n"] }]
6782
+ }] });
6783
+
6784
+ /**
6785
+ * A flexible sidebar container that can be populated with any component content.
6786
+ * The sidebar acts as an empty container that gets filled with dynamic content.
6787
+ *
6788
+ * @inputs
6789
+ * - **visible**: Controls sidebar visibility (boolean)
6790
+ *
6791
+ * @outputs
6792
+ * - **closed**: Emitted when sidebar is closed
6793
+ */
6794
+ class SidebarComponent {
6795
+ visible = input(false);
6796
+ closed = output();
6797
+ close() {
6798
+ this.closed.emit();
6799
+ }
6800
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6801
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.7", type: SidebarComponent, isStandalone: true, selector: "lib-sidebar", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<div class=\"c-sidebar\" [ngClass]=\"visible() ? 'c-sidebar--visible' : 'c-sidebar--hide'\">\n <!-- Backdrop -->\n <div\n class=\"c-sidebar__backdrop\"\n [ngClass]=\"{'c-sidebar__backdrop--open': visible()}\"\n (click)=\"close()\"\n (keydown.escape)=\"close()\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Close sidebar\"\n ></div>\n\n <!-- Sidebar Content -->\n <aside\n class=\"c-sidebar__content\"\n (keydown.escape)=\"close()\"\n role=\"dialog\"\n tabindex=\"-1\"\n >\n <!-- Content Container -->\n <div class=\"c-sidebar__body\">\n <ng-content></ng-content>\n </div>\n </aside>\n</div>\n", styles: [".c-sidebar{position:fixed;top:0;left:0;width:100%;height:100vh;z-index:1000}.c-sidebar--hide{pointer-events:none;transition:visibility 0s .33s;visibility:hidden}.c-sidebar--hide .c-sidebar__backdrop{opacity:0}.c-sidebar__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:var(--color-effect-overlay);opacity:0;transition:opacity .33s ease-in-out;z-index:999}.c-sidebar__backdrop--open{opacity:1}.c-sidebar__content{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--color-core-background-surface-floating);border-right:var(--size-border-width-sm) solid var(--color-core-border-soft);box-shadow:0 4px 8px 0 var(--color-effect-shadow-soft),0 0 4px 0 var(--color-effect-shadow-soft);position:fixed;top:0;left:0;z-index:1000;transform:translate(-100%);transition:transform .33s ease-out}@media (min-width: 768px){.c-sidebar__content{width:360px;max-width:360px}}.c-sidebar--visible .c-sidebar__content{transform:translate(0)}.c-sidebar--hide .c-sidebar__content{transform:translate(-100%)}.c-sidebar__body{padding:var(--space-component-padding-sm);flex:1;overflow-y:auto}@media (min-width: 768px){.c-sidebar__body{padding:var(--space-component-padding-lg) var(--space-component-padding-md)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
6802
+ }
6803
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImport: i0, type: SidebarComponent, decorators: [{
6804
+ type: Component,
6805
+ args: [{ selector: 'lib-sidebar', imports: [CommonModule, NgClass], template: "<div class=\"c-sidebar\" [ngClass]=\"visible() ? 'c-sidebar--visible' : 'c-sidebar--hide'\">\n <!-- Backdrop -->\n <div\n class=\"c-sidebar__backdrop\"\n [ngClass]=\"{'c-sidebar__backdrop--open': visible()}\"\n (click)=\"close()\"\n (keydown.escape)=\"close()\"\n tabindex=\"0\"\n role=\"button\"\n aria-label=\"Close sidebar\"\n ></div>\n\n <!-- Sidebar Content -->\n <aside\n class=\"c-sidebar__content\"\n (keydown.escape)=\"close()\"\n role=\"dialog\"\n tabindex=\"-1\"\n >\n <!-- Content Container -->\n <div class=\"c-sidebar__body\">\n <ng-content></ng-content>\n </div>\n </aside>\n</div>\n", styles: [".c-sidebar{position:fixed;top:0;left:0;width:100%;height:100vh;z-index:1000}.c-sidebar--hide{pointer-events:none;transition:visibility 0s .33s;visibility:hidden}.c-sidebar--hide .c-sidebar__backdrop{opacity:0}.c-sidebar__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background-color:var(--color-effect-overlay);opacity:0;transition:opacity .33s ease-in-out;z-index:999}.c-sidebar__backdrop--open{opacity:1}.c-sidebar__content{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--color-core-background-surface-floating);border-right:var(--size-border-width-sm) solid var(--color-core-border-soft);box-shadow:0 4px 8px 0 var(--color-effect-shadow-soft),0 0 4px 0 var(--color-effect-shadow-soft);position:fixed;top:0;left:0;z-index:1000;transform:translate(-100%);transition:transform .33s ease-out}@media (min-width: 768px){.c-sidebar__content{width:360px;max-width:360px}}.c-sidebar--visible .c-sidebar__content{transform:translate(0)}.c-sidebar--hide .c-sidebar__content{transform:translate(-100%)}.c-sidebar__body{padding:var(--space-component-padding-sm);flex:1;overflow-y:auto}@media (min-width: 768px){.c-sidebar__body{padding:var(--space-component-padding-lg) var(--space-component-padding-md)}}\n"] }]
6779
6806
  }] });
6780
6807
 
6781
6808
  class SocialLoginComponent {
@@ -7393,5 +7420,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.7", ngImpor
7393
7420
  * Generated bundle index. Do not edit.
7394
7421
  */
7395
7422
 
7396
- export { AccordionComponent, AlertComponent, ArrowsComponent, AvatarComponent, BadgeComponent, BasicSidebarMenuComponent, BreadcrumbComponent, ButtonComponent, ButtonIconComponent, ButtonSetComponent, CheckboxComponent, CheckboxGroupComponent, ChipsComponent, DesignTokensComponent, DropdownActionComponent, DropdownActionTriggerDirective, DropdownSelectComponent, DropdownSelectTriggerDirective, HelperTextComponent, IconComponent, InputDateComponent, InputLabelComponent, InputNumberComponent, InputPaymentComponent, InputSearchComponent, InputUploadComponent, LinkActionComponent, LinkComponent, MenuChildItemComponent, MenuItemComponent, ModalComponent, ModalService, OverlayComponent, OverlayTriggerDirective, PaginationComponent, PasswordInputComponent, RadioComponent, RadioGroupComponent, SegmentedControlComponent, SelectComponent, SidebarComponent, SidebarExamplesComponent, SidebarService, SidebarWithFooterComponent, SidebarWithHeaderComponent, SocialLoginComponent, SpinnerComponent, SwitchComponent, TabsComponent, TagComponent, TextInputComponent, TextareaComponent, ThumbnailComponent, TileComponent, ToastComponent, TooltipComponent, TooltipDirective, TooltipPosition };
7423
+ export { AccordionComponent, AlertComponent, ArrowsComponent, AvatarComponent, BadgeComponent, BasicSidebarMenuComponent, BreadcrumbComponent, ButtonComponent, ButtonIconComponent, ButtonSetComponent, CheckboxComponent, CheckboxGroupComponent, ChipsComponent, DesignTokensComponent, DropdownActionComponent, DropdownActionTriggerDirective, DropdownSelectComponent, DropdownSelectTriggerDirective, HelperTextComponent, IconComponent, InputDateComponent, InputLabelComponent, InputNumberComponent, InputPaymentComponent, InputSearchComponent, InputUploadComponent, LinkActionComponent, LinkComponent, MenuChildItemComponent, MenuItemComponent, ModalComponent, ModalService, OverlayComponent, OverlayTriggerDirective, PaginationComponent, PasswordInputComponent, RadioComponent, RadioGroupComponent, SegmentedControlComponent, SelectComponent, SidebarComponent, SidebarProgrammaticComponent, SidebarProgrammaticExamplesComponent, SidebarService, SidebarWithFooterComponent, SocialLoginComponent, SpinnerComponent, SwitchComponent, TabsComponent, TagComponent, TextInputComponent, TextareaComponent, ThumbnailComponent, TileComponent, ToastComponent, TooltipComponent, TooltipDirective, TooltipPosition };
7397
7424
  //# sourceMappingURL=crowdfarming-oliva-ds.mjs.map