@kksdev/ds-angular 1.3.0 → 1.4.0

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,11 +6,11 @@ import * as i1$1 from '@fortawesome/angular-fontawesome';
6
6
  import { FaIconComponent, FontAwesomeModule } from '@fortawesome/angular-fontawesome';
7
7
  import * as i1$4 from '@angular/forms';
8
8
  import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
9
- import { faInfoCircle, faTimesCircle, faExclamationTriangle, faCheckCircle, faTimes, faEye, faEyeSlash, faClose, faCircleInfo, faCircleXmark, faCircleExclamation, faCircleCheck, faChevronDown, faChevronLeft, faChevronRight, faAnglesLeft, faAnglesRight, faCheck, faSearch, faXmark, faSpinner, faCalendar, faCloudArrowUp, faFile, faFileImage, faFilePdf, faFileWord, faFileExcel } from '@fortawesome/free-solid-svg-icons';
9
+ import { faInfoCircle, faTimesCircle, faExclamationTriangle, faCheckCircle, faTimes, faEye, faEyeSlash, faClose, faCircleInfo, faCircleXmark, faCircleExclamation, faCircleCheck, faChevronDown, faChevronLeft, faChevronRight, faAnglesLeft, faAnglesRight, faCheck, faSearch, faXmark, faSpinner, faCalendar, faCloudArrowUp, faFile, faFileImage, faFilePdf, faFileWord, faFileExcel, faInbox, faStar, faStarHalfStroke, faClock, faChevronUp, faFolder, faFolderOpen } from '@fortawesome/free-solid-svg-icons';
10
10
  import * as i1$2 from '@angular/router';
11
11
  import { RouterModule } from '@angular/router';
12
12
  import * as i1$3 from '@angular/cdk/overlay';
13
- import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
13
+ import { CdkConnectedOverlay, CdkOverlayOrigin, OverlayModule } from '@angular/cdk/overlay';
14
14
  import { FocusTrapFactory } from '@angular/cdk/a11y';
15
15
  import { TemplatePortal, ComponentPortal } from '@angular/cdk/portal';
16
16
  import { Subject, debounceTime, distinctUntilChanged, takeUntil } from 'rxjs';
@@ -2349,11 +2349,11 @@ class DsAlert {
2349
2349
  this.closed.emit();
2350
2350
  }
2351
2351
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
2352
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsAlert, isStandalone: true, selector: "ds-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<div\n [class]=\"alertClasses.join(' ')\"\n role=\"alert\"\n [attr.aria-hidden]=\"hidden() ? 'true' : null\"\n>\n @if (showIcon()) {\n <div class=\"ds-alert__icon\" aria-hidden=\"true\">\n <fa-icon [icon]=\"currentIcon\"></fa-icon>\n </div>\n }\n\n <div class=\"ds-alert__content\">\n <ng-content></ng-content>\n </div>\n\n @if (closable()) {\n <button\n class=\"ds-alert__close\"\n type=\"button\"\n aria-label=\"Fermer l'alerte\"\n (click)=\"handleClose()\"\n >\n <fa-icon [icon]=\"closeIcon\"></fa-icon>\n </button>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.ds-alert{display:flex;align-items:flex-start;gap:var(--alert-gap, var(--space-3));border-radius:var(--alert-radius, var(--radius-2));border-width:1px;border-style:solid;transition:all var(--duration-fast, .15s) ease}.ds-alert--success{background-color:var(--alert-success-bg, var(--bg-success));border-color:var(--alert-success-border, var(--success));color:var(--alert-success-text, var(--text-success))}.ds-alert--success .ds-alert__icon{color:var(--alert-success-icon, var(--success))}.ds-alert--warning{background-color:var(--alert-warning-bg, var(--bg-warning));border-color:var(--alert-warning-border, var(--warning));color:var(--alert-warning-text, var(--text-warning))}.ds-alert--warning .ds-alert__icon{color:var(--alert-warning-icon, var(--warning))}.ds-alert--error{background-color:var(--alert-error-bg, var(--bg-error));border-color:var(--alert-error-border, var(--error));color:var(--alert-error-text, var(--text-error))}.ds-alert--error .ds-alert__icon{color:var(--alert-error-icon, var(--error))}.ds-alert--info{background-color:var(--alert-info-bg, var(--bg-info));border-color:var(--alert-info-border, var(--info));color:var(--alert-info-text, var(--text-info))}.ds-alert--info .ds-alert__icon{color:var(--alert-info-icon, var(--info))}.ds-alert--sm{padding:var(--alert-padding-sm, var(--space-2));font-size:var(--alert-font-size-sm, var(--font-size-2))}.ds-alert--sm .ds-alert__icon{font-size:var(--alert-icon-size-sm, 16px)}.ds-alert--sm .ds-alert__close{width:20px;height:20px;font-size:12px}.ds-alert--md{padding:var(--alert-padding-md, var(--space-3));font-size:var(--alert-font-size-md, var(--font-size-3))}.ds-alert--md .ds-alert__icon{font-size:var(--alert-icon-size-md, 20px)}.ds-alert--md .ds-alert__close{width:24px;height:24px;font-size:14px}.ds-alert--lg{padding:var(--alert-padding-lg, var(--space-4));font-size:var(--alert-font-size-lg, var(--font-size-4))}.ds-alert--lg .ds-alert__icon{font-size:var(--alert-icon-size-lg, 24px)}.ds-alert--lg .ds-alert__close{width:28px;height:28px;font-size:16px}.ds-alert--hidden{display:none}.ds-alert__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;line-height:1}.ds-alert__content{flex:1;min-width:0}.ds-alert__content>:first-child{margin-top:0}.ds-alert__content>:last-child{margin-bottom:0}.ds-alert__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;background:transparent;border:none;border-radius:var(--radius-1, 4px);cursor:pointer;transition:all var(--duration-fast, .15s) ease;color:currentColor;opacity:.7}.ds-alert__close:hover{opacity:1;background-color:var(--hover-bg, rgba(0, 0, 0, .05))}.ds-alert__close:active{transform:scale(.95)}.ds-alert__close:focus-visible{outline:2px solid currentColor;outline-offset:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i1$1.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }] });
2352
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsAlert, isStandalone: true, selector: "ds-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, ngImport: i0, template: "<div\n [class]=\"alertClasses.join(' ')\"\n role=\"alert\"\n [attr.aria-hidden]=\"hidden() ? 'true' : null\"\n>\n @if (showIcon()) {\n <div class=\"ds-alert__icon\" aria-hidden=\"true\">\n <fa-icon [icon]=\"currentIcon\"></fa-icon>\n </div>\n }\n\n <div class=\"ds-alert__content\">\n <ng-content></ng-content>\n </div>\n\n @if (closable()) {\n <button\n class=\"ds-alert__close\"\n type=\"button\"\n aria-label=\"Fermer l'alerte\"\n (click)=\"handleClose()\"\n >\n <fa-icon [icon]=\"closeIcon\"></fa-icon>\n </button>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.ds-alert{display:flex;align-items:flex-start;gap:var(--alert-gap, var(--space-3));border-radius:var(--alert-radius, var(--radius-2));border-width:1px;border-style:solid;transition:all var(--duration-fast, .15s) ease}.ds-alert--success{background-color:var(--alert-success-bg, var(--bg-success));border-color:var(--alert-success-border, var(--success));color:var(--alert-success-text, var(--text-success))}.ds-alert--success .ds-alert__icon{color:var(--alert-success-icon, var(--success))}.ds-alert--warning{background-color:var(--alert-warning-bg, var(--bg-warning));border-color:var(--alert-warning-border, var(--warning));color:var(--alert-warning-text, var(--text-warning))}.ds-alert--warning .ds-alert__icon{color:var(--alert-warning-icon, var(--warning))}.ds-alert--error{background-color:var(--alert-error-bg, var(--bg-error));border-color:var(--alert-error-border, var(--error));color:var(--alert-error-text, var(--text-error))}.ds-alert--error .ds-alert__icon{color:var(--alert-error-icon, var(--error))}.ds-alert--info{background-color:var(--alert-info-bg, var(--bg-info));border-color:var(--alert-info-border, var(--info));color:var(--alert-info-text, var(--text-info))}.ds-alert--info .ds-alert__icon{color:var(--alert-info-icon, var(--info))}.ds-alert--sm{padding:var(--alert-padding-sm, var(--space-2));font-size:var(--alert-font-size-sm, var(--font-size-2))}.ds-alert--sm .ds-alert__icon{font-size:var(--alert-icon-size-sm, 16px)}.ds-alert--sm .ds-alert__close{width:20px;height:20px;font-size:12px}.ds-alert--md{padding:var(--alert-padding-md, var(--space-3));font-size:var(--alert-font-size-md, var(--font-size-3))}.ds-alert--md .ds-alert__icon{font-size:var(--alert-icon-size-md, 20px)}.ds-alert--md .ds-alert__close{width:24px;height:24px;font-size:14px}.ds-alert--lg{padding:var(--alert-padding-lg, var(--space-4));font-size:var(--alert-font-size-lg, var(--font-size-4))}.ds-alert--lg .ds-alert__icon{font-size:var(--alert-icon-size-lg, 24px)}.ds-alert--lg .ds-alert__close{width:28px;height:28px;font-size:16px}.ds-alert--hidden{display:none}.ds-alert__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;line-height:1}.ds-alert__content{flex:1;min-width:0}.ds-alert__content>:first-child{margin-top:0}.ds-alert__content>:last-child{margin-bottom:0}.ds-alert__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;background:transparent;border:none;border-radius:var(--radius-1, 4px);cursor:pointer;transition:all var(--duration-fast, .15s) ease;color:currentColor;opacity:.7}.ds-alert__close:hover{opacity:1;background-color:var(--hover-bg, rgba(var(--black-rgb), .05))}.ds-alert__close:active{transform:scale(.95)}.ds-alert__close:focus-visible{outline:2px solid currentColor;outline-offset:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i1$1.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }] });
2353
2353
  }
2354
2354
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsAlert, decorators: [{
2355
2355
  type: Component,
2356
- args: [{ selector: 'ds-alert', imports: [CommonModule, FontAwesomeModule], template: "<div\n [class]=\"alertClasses.join(' ')\"\n role=\"alert\"\n [attr.aria-hidden]=\"hidden() ? 'true' : null\"\n>\n @if (showIcon()) {\n <div class=\"ds-alert__icon\" aria-hidden=\"true\">\n <fa-icon [icon]=\"currentIcon\"></fa-icon>\n </div>\n }\n\n <div class=\"ds-alert__content\">\n <ng-content></ng-content>\n </div>\n\n @if (closable()) {\n <button\n class=\"ds-alert__close\"\n type=\"button\"\n aria-label=\"Fermer l'alerte\"\n (click)=\"handleClose()\"\n >\n <fa-icon [icon]=\"closeIcon\"></fa-icon>\n </button>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.ds-alert{display:flex;align-items:flex-start;gap:var(--alert-gap, var(--space-3));border-radius:var(--alert-radius, var(--radius-2));border-width:1px;border-style:solid;transition:all var(--duration-fast, .15s) ease}.ds-alert--success{background-color:var(--alert-success-bg, var(--bg-success));border-color:var(--alert-success-border, var(--success));color:var(--alert-success-text, var(--text-success))}.ds-alert--success .ds-alert__icon{color:var(--alert-success-icon, var(--success))}.ds-alert--warning{background-color:var(--alert-warning-bg, var(--bg-warning));border-color:var(--alert-warning-border, var(--warning));color:var(--alert-warning-text, var(--text-warning))}.ds-alert--warning .ds-alert__icon{color:var(--alert-warning-icon, var(--warning))}.ds-alert--error{background-color:var(--alert-error-bg, var(--bg-error));border-color:var(--alert-error-border, var(--error));color:var(--alert-error-text, var(--text-error))}.ds-alert--error .ds-alert__icon{color:var(--alert-error-icon, var(--error))}.ds-alert--info{background-color:var(--alert-info-bg, var(--bg-info));border-color:var(--alert-info-border, var(--info));color:var(--alert-info-text, var(--text-info))}.ds-alert--info .ds-alert__icon{color:var(--alert-info-icon, var(--info))}.ds-alert--sm{padding:var(--alert-padding-sm, var(--space-2));font-size:var(--alert-font-size-sm, var(--font-size-2))}.ds-alert--sm .ds-alert__icon{font-size:var(--alert-icon-size-sm, 16px)}.ds-alert--sm .ds-alert__close{width:20px;height:20px;font-size:12px}.ds-alert--md{padding:var(--alert-padding-md, var(--space-3));font-size:var(--alert-font-size-md, var(--font-size-3))}.ds-alert--md .ds-alert__icon{font-size:var(--alert-icon-size-md, 20px)}.ds-alert--md .ds-alert__close{width:24px;height:24px;font-size:14px}.ds-alert--lg{padding:var(--alert-padding-lg, var(--space-4));font-size:var(--alert-font-size-lg, var(--font-size-4))}.ds-alert--lg .ds-alert__icon{font-size:var(--alert-icon-size-lg, 24px)}.ds-alert--lg .ds-alert__close{width:28px;height:28px;font-size:16px}.ds-alert--hidden{display:none}.ds-alert__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;line-height:1}.ds-alert__content{flex:1;min-width:0}.ds-alert__content>:first-child{margin-top:0}.ds-alert__content>:last-child{margin-bottom:0}.ds-alert__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;background:transparent;border:none;border-radius:var(--radius-1, 4px);cursor:pointer;transition:all var(--duration-fast, .15s) ease;color:currentColor;opacity:.7}.ds-alert__close:hover{opacity:1;background-color:var(--hover-bg, rgba(0, 0, 0, .05))}.ds-alert__close:active{transform:scale(.95)}.ds-alert__close:focus-visible{outline:2px solid currentColor;outline-offset:2px}\n"] }]
2356
+ args: [{ selector: 'ds-alert', imports: [CommonModule, FontAwesomeModule], template: "<div\n [class]=\"alertClasses.join(' ')\"\n role=\"alert\"\n [attr.aria-hidden]=\"hidden() ? 'true' : null\"\n>\n @if (showIcon()) {\n <div class=\"ds-alert__icon\" aria-hidden=\"true\">\n <fa-icon [icon]=\"currentIcon\"></fa-icon>\n </div>\n }\n\n <div class=\"ds-alert__content\">\n <ng-content></ng-content>\n </div>\n\n @if (closable()) {\n <button\n class=\"ds-alert__close\"\n type=\"button\"\n aria-label=\"Fermer l'alerte\"\n (click)=\"handleClose()\"\n >\n <fa-icon [icon]=\"closeIcon\"></fa-icon>\n </button>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.ds-alert{display:flex;align-items:flex-start;gap:var(--alert-gap, var(--space-3));border-radius:var(--alert-radius, var(--radius-2));border-width:1px;border-style:solid;transition:all var(--duration-fast, .15s) ease}.ds-alert--success{background-color:var(--alert-success-bg, var(--bg-success));border-color:var(--alert-success-border, var(--success));color:var(--alert-success-text, var(--text-success))}.ds-alert--success .ds-alert__icon{color:var(--alert-success-icon, var(--success))}.ds-alert--warning{background-color:var(--alert-warning-bg, var(--bg-warning));border-color:var(--alert-warning-border, var(--warning));color:var(--alert-warning-text, var(--text-warning))}.ds-alert--warning .ds-alert__icon{color:var(--alert-warning-icon, var(--warning))}.ds-alert--error{background-color:var(--alert-error-bg, var(--bg-error));border-color:var(--alert-error-border, var(--error));color:var(--alert-error-text, var(--text-error))}.ds-alert--error .ds-alert__icon{color:var(--alert-error-icon, var(--error))}.ds-alert--info{background-color:var(--alert-info-bg, var(--bg-info));border-color:var(--alert-info-border, var(--info));color:var(--alert-info-text, var(--text-info))}.ds-alert--info .ds-alert__icon{color:var(--alert-info-icon, var(--info))}.ds-alert--sm{padding:var(--alert-padding-sm, var(--space-2));font-size:var(--alert-font-size-sm, var(--font-size-2))}.ds-alert--sm .ds-alert__icon{font-size:var(--alert-icon-size-sm, 16px)}.ds-alert--sm .ds-alert__close{width:20px;height:20px;font-size:12px}.ds-alert--md{padding:var(--alert-padding-md, var(--space-3));font-size:var(--alert-font-size-md, var(--font-size-3))}.ds-alert--md .ds-alert__icon{font-size:var(--alert-icon-size-md, 20px)}.ds-alert--md .ds-alert__close{width:24px;height:24px;font-size:14px}.ds-alert--lg{padding:var(--alert-padding-lg, var(--space-4));font-size:var(--alert-font-size-lg, var(--font-size-4))}.ds-alert--lg .ds-alert__icon{font-size:var(--alert-icon-size-lg, 24px)}.ds-alert--lg .ds-alert__close{width:28px;height:28px;font-size:16px}.ds-alert--hidden{display:none}.ds-alert__icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;line-height:1}.ds-alert__content{flex:1;min-width:0}.ds-alert__content>:first-child{margin-top:0}.ds-alert__content>:last-child{margin-bottom:0}.ds-alert__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;background:transparent;border:none;border-radius:var(--radius-1, 4px);cursor:pointer;transition:all var(--duration-fast, .15s) ease;color:currentColor;opacity:.7}.ds-alert__close:hover{opacity:1;background-color:var(--hover-bg, rgba(var(--black-rgb), .05))}.ds-alert__close:active{transform:scale(.95)}.ds-alert__close:focus-visible{outline:2px solid currentColor;outline-offset:2px}\n"] }]
2357
2357
  }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
2358
2358
 
2359
2359
  class DsBadge {
@@ -3767,7 +3767,7 @@ class DsModalComponent {
3767
3767
  body.classList.remove('modal-open');
3768
3768
  }
3769
3769
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3770
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsModalComponent, isStandalone: true, selector: "ds-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "document:keydown.escape": "handleEscape($event)" } }, queries: [{ propertyName: "projectedIcon", first: true, predicate: ["icon"], descendants: true }], viewQueries: [{ propertyName: "modalContainer", first: true, predicate: ["modalContainer"], descendants: true }, { propertyName: "closeButton", first: true, predicate: ["closeButton"], descendants: true, read: ElementRef }], ngImport: i0, template: "@if (shouldRenderOverlay()) {\n <div class=\"overlay\" role=\"presentation\" (click)=\"onBackdropClick()\"></div>\n}\n@if (open()) {\n <div #modalContainer\n class=\"modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"modalTitleId\"\n [attr.aria-describedby]=\"modalDescId\"\n [ngClass]=\"modalClasses()\"\n >\n <header class=\"modal-header\">\n @if (showIcon()) {\n <div class=\"modal-icon\">\n <ng-content select=\"[icon]\"></ng-content>\n @if (shouldRenderDefaultIcon() && resolvedIcon()) {\n <fa-icon [icon]=\"resolvedIcon()!\"></fa-icon>\n }\n </div>\n }\n <h3 [id]=\"modalTitleId\">{{ title() }}</h3>\n @if (closable()) {\n <primitive-button\n #closeButton\n class=\"close-btn\"\n variant=\"ghost\"\n appearance=\"outline\"\n size=\"sm\"\n (clicked)=\"close()\"\n aria-label=\"Fermer la fen\u00EAtre\"\n >\u2715</primitive-button>\n }\n </header>\n <div class=\"modal-content\" (scroll)=\"onScroll($event)\">\n <section [id]=\"modalDescId\"><ng-content></ng-content></section>\n </div>\n <footer class=\"modal-footer\" [class.with-shadow]=\"isScrolled()\">\n <ng-content select=\"[footer]\"></ng-content>\n </footer>\n </div>\n}\n", styles: [".overlay{position:fixed;inset:0;background:var(--modal-backdrop);-webkit-backdrop-filter:blur(var(--modal-overlay-blur));backdrop-filter:blur(var(--modal-overlay-blur));z-index:var(--modal-overlay-z-index)}.modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--modal-bg);color:var(--modal-text);padding:var(--modal-padding);border-radius:var(--modal-radius);box-shadow:var(--modal-shadow-depth);max-height:var(--modal-max-height);border:1px solid var(--modal-border-color);z-index:var(--modal-overlay-z-index);width:min(95vw,var(--modal-size-md));display:flex;flex-direction:column;overflow:hidden;animation:scaleIn .25s var(--easing-default)}.modal-sm{width:min(95vw,var(--modal-size-sm))}.modal-md{width:min(95vw,var(--modal-size-md))}.modal-lg{width:min(95vw,var(--modal-size-lg))}.modal-header{display:flex;align-items:center;gap:var(--modal-section-gap);position:relative;padding-bottom:var(--modal-section-gap);margin-bottom:var(--modal-section-gap);border-bottom:1px solid var(--modal-divider)}.modal-header h3{margin:0;font-size:var(--font-size-5);font-weight:var(--font-weight-semibold)}.modal-header .modal-icon{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0;background:var(--color-primary);color:var(--gray-50);animation:popIn .3s var(--easing-default)}.modal-header .close-btn{position:absolute;top:0;right:0}.modal-header .close-btn button{background:transparent;border:none;font-size:var(--font-size-4);cursor:pointer;color:var(--text-muted);padding:0;line-height:var(--line-height-tight);transition:color var(--duration-fast) var(--easing-default)}.modal-header .close-btn button:hover{color:var(--text-default)}.modal-success .modal-header h3{color:var(--modal-type-success-color)}.modal-warning .modal-header h3{color:var(--modal-type-warning-color)}.modal-error .modal-header h3{color:var(--modal-type-error-color)}.modal-info .modal-header h3{color:var(--modal-type-info-color)}.modal-success .modal-icon{background:var(--modal-type-success-color);color:var(--modal-type-success-contrast)}.modal-warning .modal-icon{background:var(--modal-type-warning-color);color:var(--modal-type-warning-contrast)}.modal-error .modal-icon{background:var(--modal-type-error-color);color:var(--modal-type-error-contrast)}.modal-info .modal-icon{background:var(--modal-type-info-color);color:var(--modal-type-info-contrast)}.modal-content{flex:1;overflow-y:auto;font-size:var(--font-size-2);display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--modal-section-gap)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding-top:var(--space-2);padding-bottom:var(--modal-footer-padding);padding-inline:0;border-top:1px solid var(--modal-divider);flex-wrap:wrap}@media (max-width: 480px){.modal-footer{flex-direction:column;align-items:stretch;justify-content:center}.modal-footer ds-button{width:100%}}.modal-footer.with-shadow{box-shadow:var(--modal-footer-shadow, inset 0 1px 0 var(--modal-divider))}@keyframes scaleIn{0%{opacity:0;transform:translate(-50%,-50%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}@keyframes popIn{0%{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "component", type: PrimitiveButton, selector: "primitive-button", inputs: ["type", "variant", "size", "disabled", "iconStart", "iconEnd", "appearance", "block"], outputs: ["clicked"] }] });
3770
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsModalComponent, isStandalone: true, selector: "ds-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "document:keydown.escape": "handleEscape($event)" } }, queries: [{ propertyName: "projectedIcon", first: true, predicate: ["icon"], descendants: true }], viewQueries: [{ propertyName: "modalContainer", first: true, predicate: ["modalContainer"], descendants: true }, { propertyName: "closeButton", first: true, predicate: ["closeButton"], descendants: true, read: ElementRef }], ngImport: i0, template: "@if (shouldRenderOverlay()) {\n <div class=\"overlay\" role=\"presentation\" (click)=\"onBackdropClick()\"></div>\n}\n@if (open()) {\n <div #modalContainer\n class=\"modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"modalTitleId\"\n [attr.aria-describedby]=\"modalDescId\"\n [ngClass]=\"modalClasses()\"\n >\n <header class=\"modal-header\">\n @if (showIcon()) {\n <div class=\"modal-icon\">\n <ng-content select=\"[icon]\"></ng-content>\n @if (shouldRenderDefaultIcon() && resolvedIcon()) {\n <fa-icon [icon]=\"resolvedIcon()!\"></fa-icon>\n }\n </div>\n }\n <h3 [id]=\"modalTitleId\">{{ title() }}</h3>\n @if (closable()) {\n <primitive-button\n #closeButton\n class=\"close-btn\"\n variant=\"ghost\"\n appearance=\"outline\"\n size=\"sm\"\n (clicked)=\"close()\"\n aria-label=\"Fermer la fen\u00EAtre\"\n >\u2715</primitive-button>\n }\n </header>\n <div class=\"modal-content\" (scroll)=\"onScroll($event)\">\n <section [id]=\"modalDescId\"><ng-content></ng-content></section>\n </div>\n <footer class=\"modal-footer\" [class.with-shadow]=\"isScrolled()\">\n <ng-content select=\"[footer]\"></ng-content>\n </footer>\n </div>\n}\n", styles: [".overlay{position:fixed;inset:0;background:var(--modal-backdrop);-webkit-backdrop-filter:blur(var(--modal-overlay-blur));backdrop-filter:blur(var(--modal-overlay-blur));z-index:var(--modal-overlay-z-index)}.modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--modal-bg);color:var(--modal-text);padding:var(--modal-padding);border-radius:var(--modal-radius);box-shadow:var(--modal-shadow-depth);max-height:var(--modal-max-height);border:1px solid var(--modal-border-color);z-index:var(--modal-overlay-z-index);width:min(95vw,var(--modal-size-md));display:flex;flex-direction:column;overflow:hidden;animation:scaleIn .25s var(--easing-default)}.modal-sm{width:min(95vw,var(--modal-size-sm))}.modal-md{width:min(95vw,var(--modal-size-md))}.modal-lg{width:min(95vw,var(--modal-size-lg))}.modal-header{display:flex;align-items:center;gap:var(--modal-section-gap);position:relative;padding-bottom:var(--modal-section-gap);margin-bottom:var(--modal-section-gap);border-bottom:1px solid var(--modal-divider)}.modal-header h3{margin:0;font-size:var(--font-size-5);font-weight:var(--font-weight-semibold)}.modal-header .modal-icon{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0;background:var(--color-primary);color:var(--gray-50);animation:popIn .3s var(--easing-default)}.modal-header .close-btn{position:absolute;top:0;right:0}.modal-header .close-btn button{background:transparent;border:none;font-size:var(--font-size-4);cursor:pointer;color:var(--text-muted);padding:0;line-height:var(--line-height-tight);transition:color var(--duration-fast) var(--easing-default)}.modal-header .close-btn button:hover{color:var(--text-default)}.modal-success .modal-header h3{color:var(--modal-type-success-color)}.modal-warning .modal-header h3{color:var(--modal-type-warning-color)}.modal-error .modal-header h3{color:var(--modal-type-error-color)}.modal-info .modal-header h3{color:var(--modal-type-info-color)}.modal-success .modal-icon{background:var(--modal-type-success-color);color:var(--modal-type-success-contrast)}.modal-warning .modal-icon{background:var(--modal-type-warning-color);color:var(--modal-type-warning-contrast)}.modal-error .modal-icon{background:var(--modal-type-error-color);color:var(--modal-type-error-contrast)}.modal-info .modal-icon{background:var(--modal-type-info-color);color:var(--modal-type-info-contrast)}.modal-content{flex:1;overflow-y:auto;font-size:var(--font-size-2);display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--modal-section-gap)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding-top:var(--space-2);padding-bottom:var(--modal-footer-padding);padding-inline:0;border-top:1px solid var(--modal-divider);flex-wrap:wrap}@media (max-width: 576px){.modal-footer{flex-direction:column;align-items:stretch;justify-content:center}.modal-footer ds-button{width:100%}}.modal-footer.with-shadow{box-shadow:var(--modal-footer-shadow, inset 0 1px 0 var(--modal-divider))}@keyframes scaleIn{0%{opacity:0;transform:translate(-50%,-50%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}@keyframes popIn{0%{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "component", type: PrimitiveButton, selector: "primitive-button", inputs: ["type", "variant", "size", "disabled", "iconStart", "iconEnd", "appearance", "block"], outputs: ["clicked"] }] });
3771
3771
  }
3772
3772
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsModalComponent, decorators: [{
3773
3773
  type: Component,
@@ -3775,7 +3775,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
3775
3775
  NgClass,
3776
3776
  FaIconComponent,
3777
3777
  PrimitiveButton
3778
- ], template: "@if (shouldRenderOverlay()) {\n <div class=\"overlay\" role=\"presentation\" (click)=\"onBackdropClick()\"></div>\n}\n@if (open()) {\n <div #modalContainer\n class=\"modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"modalTitleId\"\n [attr.aria-describedby]=\"modalDescId\"\n [ngClass]=\"modalClasses()\"\n >\n <header class=\"modal-header\">\n @if (showIcon()) {\n <div class=\"modal-icon\">\n <ng-content select=\"[icon]\"></ng-content>\n @if (shouldRenderDefaultIcon() && resolvedIcon()) {\n <fa-icon [icon]=\"resolvedIcon()!\"></fa-icon>\n }\n </div>\n }\n <h3 [id]=\"modalTitleId\">{{ title() }}</h3>\n @if (closable()) {\n <primitive-button\n #closeButton\n class=\"close-btn\"\n variant=\"ghost\"\n appearance=\"outline\"\n size=\"sm\"\n (clicked)=\"close()\"\n aria-label=\"Fermer la fen\u00EAtre\"\n >\u2715</primitive-button>\n }\n </header>\n <div class=\"modal-content\" (scroll)=\"onScroll($event)\">\n <section [id]=\"modalDescId\"><ng-content></ng-content></section>\n </div>\n <footer class=\"modal-footer\" [class.with-shadow]=\"isScrolled()\">\n <ng-content select=\"[footer]\"></ng-content>\n </footer>\n </div>\n}\n", styles: [".overlay{position:fixed;inset:0;background:var(--modal-backdrop);-webkit-backdrop-filter:blur(var(--modal-overlay-blur));backdrop-filter:blur(var(--modal-overlay-blur));z-index:var(--modal-overlay-z-index)}.modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--modal-bg);color:var(--modal-text);padding:var(--modal-padding);border-radius:var(--modal-radius);box-shadow:var(--modal-shadow-depth);max-height:var(--modal-max-height);border:1px solid var(--modal-border-color);z-index:var(--modal-overlay-z-index);width:min(95vw,var(--modal-size-md));display:flex;flex-direction:column;overflow:hidden;animation:scaleIn .25s var(--easing-default)}.modal-sm{width:min(95vw,var(--modal-size-sm))}.modal-md{width:min(95vw,var(--modal-size-md))}.modal-lg{width:min(95vw,var(--modal-size-lg))}.modal-header{display:flex;align-items:center;gap:var(--modal-section-gap);position:relative;padding-bottom:var(--modal-section-gap);margin-bottom:var(--modal-section-gap);border-bottom:1px solid var(--modal-divider)}.modal-header h3{margin:0;font-size:var(--font-size-5);font-weight:var(--font-weight-semibold)}.modal-header .modal-icon{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0;background:var(--color-primary);color:var(--gray-50);animation:popIn .3s var(--easing-default)}.modal-header .close-btn{position:absolute;top:0;right:0}.modal-header .close-btn button{background:transparent;border:none;font-size:var(--font-size-4);cursor:pointer;color:var(--text-muted);padding:0;line-height:var(--line-height-tight);transition:color var(--duration-fast) var(--easing-default)}.modal-header .close-btn button:hover{color:var(--text-default)}.modal-success .modal-header h3{color:var(--modal-type-success-color)}.modal-warning .modal-header h3{color:var(--modal-type-warning-color)}.modal-error .modal-header h3{color:var(--modal-type-error-color)}.modal-info .modal-header h3{color:var(--modal-type-info-color)}.modal-success .modal-icon{background:var(--modal-type-success-color);color:var(--modal-type-success-contrast)}.modal-warning .modal-icon{background:var(--modal-type-warning-color);color:var(--modal-type-warning-contrast)}.modal-error .modal-icon{background:var(--modal-type-error-color);color:var(--modal-type-error-contrast)}.modal-info .modal-icon{background:var(--modal-type-info-color);color:var(--modal-type-info-contrast)}.modal-content{flex:1;overflow-y:auto;font-size:var(--font-size-2);display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--modal-section-gap)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding-top:var(--space-2);padding-bottom:var(--modal-footer-padding);padding-inline:0;border-top:1px solid var(--modal-divider);flex-wrap:wrap}@media (max-width: 480px){.modal-footer{flex-direction:column;align-items:stretch;justify-content:center}.modal-footer ds-button{width:100%}}.modal-footer.with-shadow{box-shadow:var(--modal-footer-shadow, inset 0 1px 0 var(--modal-divider))}@keyframes scaleIn{0%{opacity:0;transform:translate(-50%,-50%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}@keyframes popIn{0%{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}\n"] }]
3778
+ ], template: "@if (shouldRenderOverlay()) {\n <div class=\"overlay\" role=\"presentation\" (click)=\"onBackdropClick()\"></div>\n}\n@if (open()) {\n <div #modalContainer\n class=\"modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"modalTitleId\"\n [attr.aria-describedby]=\"modalDescId\"\n [ngClass]=\"modalClasses()\"\n >\n <header class=\"modal-header\">\n @if (showIcon()) {\n <div class=\"modal-icon\">\n <ng-content select=\"[icon]\"></ng-content>\n @if (shouldRenderDefaultIcon() && resolvedIcon()) {\n <fa-icon [icon]=\"resolvedIcon()!\"></fa-icon>\n }\n </div>\n }\n <h3 [id]=\"modalTitleId\">{{ title() }}</h3>\n @if (closable()) {\n <primitive-button\n #closeButton\n class=\"close-btn\"\n variant=\"ghost\"\n appearance=\"outline\"\n size=\"sm\"\n (clicked)=\"close()\"\n aria-label=\"Fermer la fen\u00EAtre\"\n >\u2715</primitive-button>\n }\n </header>\n <div class=\"modal-content\" (scroll)=\"onScroll($event)\">\n <section [id]=\"modalDescId\"><ng-content></ng-content></section>\n </div>\n <footer class=\"modal-footer\" [class.with-shadow]=\"isScrolled()\">\n <ng-content select=\"[footer]\"></ng-content>\n </footer>\n </div>\n}\n", styles: [".overlay{position:fixed;inset:0;background:var(--modal-backdrop);-webkit-backdrop-filter:blur(var(--modal-overlay-blur));backdrop-filter:blur(var(--modal-overlay-blur));z-index:var(--modal-overlay-z-index)}.modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background:var(--modal-bg);color:var(--modal-text);padding:var(--modal-padding);border-radius:var(--modal-radius);box-shadow:var(--modal-shadow-depth);max-height:var(--modal-max-height);border:1px solid var(--modal-border-color);z-index:var(--modal-overlay-z-index);width:min(95vw,var(--modal-size-md));display:flex;flex-direction:column;overflow:hidden;animation:scaleIn .25s var(--easing-default)}.modal-sm{width:min(95vw,var(--modal-size-sm))}.modal-md{width:min(95vw,var(--modal-size-md))}.modal-lg{width:min(95vw,var(--modal-size-lg))}.modal-header{display:flex;align-items:center;gap:var(--modal-section-gap);position:relative;padding-bottom:var(--modal-section-gap);margin-bottom:var(--modal-section-gap);border-bottom:1px solid var(--modal-divider)}.modal-header h3{margin:0;font-size:var(--font-size-5);font-weight:var(--font-weight-semibold)}.modal-header .modal-icon{width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;border-radius:50%;flex-shrink:0;background:var(--color-primary);color:var(--gray-50);animation:popIn .3s var(--easing-default)}.modal-header .close-btn{position:absolute;top:0;right:0}.modal-header .close-btn button{background:transparent;border:none;font-size:var(--font-size-4);cursor:pointer;color:var(--text-muted);padding:0;line-height:var(--line-height-tight);transition:color var(--duration-fast) var(--easing-default)}.modal-header .close-btn button:hover{color:var(--text-default)}.modal-success .modal-header h3{color:var(--modal-type-success-color)}.modal-warning .modal-header h3{color:var(--modal-type-warning-color)}.modal-error .modal-header h3{color:var(--modal-type-error-color)}.modal-info .modal-header h3{color:var(--modal-type-info-color)}.modal-success .modal-icon{background:var(--modal-type-success-color);color:var(--modal-type-success-contrast)}.modal-warning .modal-icon{background:var(--modal-type-warning-color);color:var(--modal-type-warning-contrast)}.modal-error .modal-icon{background:var(--modal-type-error-color);color:var(--modal-type-error-contrast)}.modal-info .modal-icon{background:var(--modal-type-info-color);color:var(--modal-type-info-contrast)}.modal-content{flex:1;overflow-y:auto;font-size:var(--font-size-2);display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--modal-section-gap)}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding-top:var(--space-2);padding-bottom:var(--modal-footer-padding);padding-inline:0;border-top:1px solid var(--modal-divider);flex-wrap:wrap}@media (max-width: 576px){.modal-footer{flex-direction:column;align-items:stretch;justify-content:center}.modal-footer ds-button{width:100%}}.modal-footer.with-shadow{box-shadow:var(--modal-footer-shadow, inset 0 1px 0 var(--modal-divider))}@keyframes scaleIn{0%{opacity:0;transform:translate(-50%,-50%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}@keyframes popIn{0%{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}\n"] }]
3779
3779
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], opened: [{
3780
3780
  type: Output
3781
3781
  }], closed: [{
@@ -5771,7 +5771,7 @@ class DsSelect {
5771
5771
  useExisting: forwardRef(() => DsSelect),
5772
5772
  multi: true,
5773
5773
  },
5774
- ], viewQueries: [{ propertyName: "selectTrigger", first: true, predicate: ["selectTrigger"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "listbox", first: true, predicate: ["listbox"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-select__label\" [attr.for]=\"name()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-select__required\">*</span>\n }\n </label>\n }\n\n <!-- Trigger -->\n <button\n #selectTrigger\n type=\"button\"\n [ngClass]=\"triggerClasses()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-label]=\"label() || placeholder()\"\n (click)=\"toggle()\">\n <span class=\"ds-select__value\">{{ displayValue() }}</span>\n\n <span class=\"ds-select__icons\">\n @if (clearable() && selectedOption()) {\n <button\n type=\"button\"\n class=\"ds-select__clear\"\n aria-label=\"Effacer la s\u00E9lection\"\n (click)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ds-select__arrow\"\n [class.ds-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </button>\n\n <!-- Dropdown -->\n @if (isOpen()) {\n <div class=\"ds-select__dropdown\" role=\"presentation\">\n <!-- Search -->\n @if (searchable()) {\n <div class=\"ds-select__search\">\n <input\n #searchInput\n type=\"text\"\n class=\"ds-select__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n aria-label=\"Rechercher une option\" />\n </div>\n }\n\n <!-- Options list -->\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-select__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-select__option\"\n [class.ds-select__option--focused]=\"isOptionFocused(i)\"\n [class.ds-select__option--selected]=\"isOptionSelected(option)\"\n [class.ds-select__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\">\n <span class=\"ds-select__option-label\">{{ option.label }}</span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-select__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-select__empty\" role=\"option\" aria-disabled=\"true\">\n Aucun r\u00E9sultat\n </li>\n }\n </ul>\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-select__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-select__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-select{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-select__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-select__required{color:var(--error);margin-left:var(--space-1)}.ds-select__trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--select-padding-md, var(--space-2) var(--space-3));background-color:var(--select-bg, var(--background-main));border:1px solid var(--select-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));font-family:inherit;font-size:var(--select-font-size-md, var(--font-size-3));color:var(--select-text, var(--text-default));cursor:pointer;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-select__trigger:hover:not(:disabled){border-color:var(--select-hover-border, var(--color-primary))}.ds-select__trigger:focus{outline:none;border-color:var(--select-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--select-focus-shadow, rgba(125, 75, 192, .2))}.ds-select__trigger:disabled{opacity:.5;cursor:not-allowed;background-color:var(--select-disabled-bg, var(--background-secondary))}.ds-select__trigger--placeholder{color:var(--select-placeholder, var(--text-muted))}.ds-select__value{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__icons{display:flex;align-items:center;gap:var(--space-1);margin-left:var(--space-2);color:var(--text-muted)}.ds-select__clear{display:flex;align-items:center;justify-content:center;padding:0;background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease}.ds-select__clear:hover{color:var(--error)}.ds-select__arrow{transition:transform var(--duration-fast) ease}.ds-select__arrow--open{transform:rotate(180deg)}.ds-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--select-dropdown-bg, var(--surface-overlay));border:1px solid var(--select-dropdown-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));box-shadow:var(--select-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-select__search{padding:var(--space-2);border-bottom:1px solid var(--border-color)}.ds-select__search-input{width:100%;padding:var(--space-2);border:1px solid var(--border-color);border-radius:var(--radius-1);font-family:inherit;font-size:var(--font-size-2);background-color:var(--background-main);color:var(--text-default)}.ds-select__search-input:focus{outline:none;border-color:var(--color-primary)}.ds-select__search-input::placeholder{color:var(--text-muted)}.ds-select__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--select-max-height, 200px);overflow-y:auto}.ds-select__option{display:flex;align-items:center;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-select__option:hover:not(.ds-select__option--disabled){background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--focused{background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--selected{background-color:var(--select-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--select-option-selected-text, var(--color-primary));font-weight:var(--font-weight-medium)}.ds-select__option--disabled{opacity:.5;cursor:not-allowed}.ds-select__option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__check{flex-shrink:0;color:var(--color-primary)}.ds-select__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-select__helper,.ds-select__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-select__helper{color:var(--text-muted)}.ds-select__error{color:var(--error)}.ds-select--sm .ds-select__trigger{padding:var(--select-padding-sm, var(--space-1) var(--space-2));font-size:var(--select-font-size-sm, var(--font-size-2))}.ds-select--sm .ds-select__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-select--lg .ds-select__trigger{padding:var(--select-padding-lg, var(--space-3) var(--space-4));font-size:var(--select-font-size-lg, var(--font-size-4))}.ds-select--lg .ds-select__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-select--error .ds-select__trigger{border-color:var(--error)}.ds-select--error .ds-select__trigger:focus{box-shadow:0 0 0 3px #f4433633}.ds-select--disabled .ds-select__label{opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
5774
+ ], viewQueries: [{ propertyName: "selectTrigger", first: true, predicate: ["selectTrigger"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "listbox", first: true, predicate: ["listbox"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-select__label\" [attr.for]=\"name()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-select__required\">*</span>\n }\n </label>\n }\n\n <!-- Trigger -->\n <button\n #selectTrigger\n type=\"button\"\n [ngClass]=\"triggerClasses()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-label]=\"label() || placeholder()\"\n (click)=\"toggle()\">\n <span class=\"ds-select__value\">{{ displayValue() }}</span>\n\n <span class=\"ds-select__icons\">\n @if (clearable() && selectedOption()) {\n <button\n type=\"button\"\n class=\"ds-select__clear\"\n aria-label=\"Effacer la s\u00E9lection\"\n (click)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ds-select__arrow\"\n [class.ds-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </button>\n\n <!-- Dropdown -->\n @if (isOpen()) {\n <div class=\"ds-select__dropdown\" role=\"presentation\">\n <!-- Search -->\n @if (searchable()) {\n <div class=\"ds-select__search\">\n <input\n #searchInput\n type=\"text\"\n class=\"ds-select__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n aria-label=\"Rechercher une option\" />\n </div>\n }\n\n <!-- Options list -->\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-select__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-select__option\"\n [class.ds-select__option--focused]=\"isOptionFocused(i)\"\n [class.ds-select__option--selected]=\"isOptionSelected(option)\"\n [class.ds-select__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\">\n <span class=\"ds-select__option-label\">{{ option.label }}</span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-select__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-select__empty\" role=\"option\" aria-disabled=\"true\">\n Aucun r\u00E9sultat\n </li>\n }\n </ul>\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-select__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-select__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-select{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-select__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-select__required{color:var(--error);margin-left:var(--space-1)}.ds-select__trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--select-padding-md, var(--space-2) var(--space-3));background-color:var(--select-bg, var(--background-main));border:1px solid var(--select-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));font-family:inherit;font-size:var(--select-font-size-md, var(--font-size-3));color:var(--select-text, var(--text-default));cursor:pointer;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-select__trigger:hover:not(:disabled){border-color:var(--select-hover-border, var(--color-primary))}.ds-select__trigger:focus{outline:none;border-color:var(--select-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--select-focus-shadow, rgba(var(--color-primary-rgb), .2))}.ds-select__trigger:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.ds-select__trigger:disabled{opacity:.5;cursor:not-allowed;background-color:var(--select-disabled-bg, var(--background-secondary))}.ds-select__trigger--placeholder{color:var(--select-placeholder, var(--text-muted))}.ds-select__value{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__icons{display:flex;align-items:center;gap:var(--space-1);margin-left:var(--space-2);color:var(--text-muted)}.ds-select__clear{display:flex;align-items:center;justify-content:center;padding:0;background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease}.ds-select__clear:hover{color:var(--error)}.ds-select__arrow{transition:transform var(--duration-fast) ease}.ds-select__arrow--open{transform:rotate(180deg)}.ds-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--select-dropdown-bg, var(--surface-overlay));border:1px solid var(--select-dropdown-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));box-shadow:var(--select-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-select__search{padding:var(--space-2);border-bottom:1px solid var(--border-color)}.ds-select__search-input{width:100%;padding:var(--space-2);border:1px solid var(--border-color);border-radius:var(--radius-1);font-family:inherit;font-size:var(--font-size-2);background-color:var(--background-main);color:var(--text-default)}.ds-select__search-input:focus{outline:none;border-color:var(--color-primary)}.ds-select__search-input::placeholder{color:var(--text-muted)}.ds-select__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--select-max-height, 200px);overflow-y:auto}.ds-select__option{display:flex;align-items:center;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-select__option:hover:not(.ds-select__option--disabled){background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--focused{background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--selected{background-color:var(--select-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--select-option-selected-text, var(--color-primary));font-weight:var(--font-weight-medium)}.ds-select__option--disabled{opacity:.5;cursor:not-allowed}.ds-select__option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__check{flex-shrink:0;color:var(--color-primary)}.ds-select__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-select__helper,.ds-select__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-select__helper{color:var(--text-muted)}.ds-select__error{color:var(--error)}.ds-select--sm .ds-select__trigger{padding:var(--select-padding-sm, var(--space-1) var(--space-2));font-size:var(--select-font-size-sm, var(--font-size-2))}.ds-select--sm .ds-select__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-select--lg .ds-select__trigger{padding:var(--select-padding-lg, var(--space-3) var(--space-4));font-size:var(--select-font-size-lg, var(--font-size-4))}.ds-select--lg .ds-select__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-select--error .ds-select__trigger{border-color:var(--error)}.ds-select--error .ds-select__trigger:focus{box-shadow:0 0 0 3px rgba(var(--error-rgb),.2)}.ds-select--disabled .ds-select__label{opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
5775
5775
  }
5776
5776
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsSelect, decorators: [{
5777
5777
  type: Component,
@@ -5781,7 +5781,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
5781
5781
  useExisting: forwardRef(() => DsSelect),
5782
5782
  multi: true,
5783
5783
  },
5784
- ], template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-select__label\" [attr.for]=\"name()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-select__required\">*</span>\n }\n </label>\n }\n\n <!-- Trigger -->\n <button\n #selectTrigger\n type=\"button\"\n [ngClass]=\"triggerClasses()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-label]=\"label() || placeholder()\"\n (click)=\"toggle()\">\n <span class=\"ds-select__value\">{{ displayValue() }}</span>\n\n <span class=\"ds-select__icons\">\n @if (clearable() && selectedOption()) {\n <button\n type=\"button\"\n class=\"ds-select__clear\"\n aria-label=\"Effacer la s\u00E9lection\"\n (click)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ds-select__arrow\"\n [class.ds-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </button>\n\n <!-- Dropdown -->\n @if (isOpen()) {\n <div class=\"ds-select__dropdown\" role=\"presentation\">\n <!-- Search -->\n @if (searchable()) {\n <div class=\"ds-select__search\">\n <input\n #searchInput\n type=\"text\"\n class=\"ds-select__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n aria-label=\"Rechercher une option\" />\n </div>\n }\n\n <!-- Options list -->\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-select__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-select__option\"\n [class.ds-select__option--focused]=\"isOptionFocused(i)\"\n [class.ds-select__option--selected]=\"isOptionSelected(option)\"\n [class.ds-select__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\">\n <span class=\"ds-select__option-label\">{{ option.label }}</span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-select__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-select__empty\" role=\"option\" aria-disabled=\"true\">\n Aucun r\u00E9sultat\n </li>\n }\n </ul>\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-select__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-select__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-select{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-select__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-select__required{color:var(--error);margin-left:var(--space-1)}.ds-select__trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--select-padding-md, var(--space-2) var(--space-3));background-color:var(--select-bg, var(--background-main));border:1px solid var(--select-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));font-family:inherit;font-size:var(--select-font-size-md, var(--font-size-3));color:var(--select-text, var(--text-default));cursor:pointer;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-select__trigger:hover:not(:disabled){border-color:var(--select-hover-border, var(--color-primary))}.ds-select__trigger:focus{outline:none;border-color:var(--select-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--select-focus-shadow, rgba(125, 75, 192, .2))}.ds-select__trigger:disabled{opacity:.5;cursor:not-allowed;background-color:var(--select-disabled-bg, var(--background-secondary))}.ds-select__trigger--placeholder{color:var(--select-placeholder, var(--text-muted))}.ds-select__value{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__icons{display:flex;align-items:center;gap:var(--space-1);margin-left:var(--space-2);color:var(--text-muted)}.ds-select__clear{display:flex;align-items:center;justify-content:center;padding:0;background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease}.ds-select__clear:hover{color:var(--error)}.ds-select__arrow{transition:transform var(--duration-fast) ease}.ds-select__arrow--open{transform:rotate(180deg)}.ds-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--select-dropdown-bg, var(--surface-overlay));border:1px solid var(--select-dropdown-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));box-shadow:var(--select-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-select__search{padding:var(--space-2);border-bottom:1px solid var(--border-color)}.ds-select__search-input{width:100%;padding:var(--space-2);border:1px solid var(--border-color);border-radius:var(--radius-1);font-family:inherit;font-size:var(--font-size-2);background-color:var(--background-main);color:var(--text-default)}.ds-select__search-input:focus{outline:none;border-color:var(--color-primary)}.ds-select__search-input::placeholder{color:var(--text-muted)}.ds-select__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--select-max-height, 200px);overflow-y:auto}.ds-select__option{display:flex;align-items:center;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-select__option:hover:not(.ds-select__option--disabled){background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--focused{background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--selected{background-color:var(--select-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--select-option-selected-text, var(--color-primary));font-weight:var(--font-weight-medium)}.ds-select__option--disabled{opacity:.5;cursor:not-allowed}.ds-select__option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__check{flex-shrink:0;color:var(--color-primary)}.ds-select__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-select__helper,.ds-select__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-select__helper{color:var(--text-muted)}.ds-select__error{color:var(--error)}.ds-select--sm .ds-select__trigger{padding:var(--select-padding-sm, var(--space-1) var(--space-2));font-size:var(--select-font-size-sm, var(--font-size-2))}.ds-select--sm .ds-select__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-select--lg .ds-select__trigger{padding:var(--select-padding-lg, var(--space-3) var(--space-4));font-size:var(--select-font-size-lg, var(--font-size-4))}.ds-select--lg .ds-select__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-select--error .ds-select__trigger{border-color:var(--error)}.ds-select--error .ds-select__trigger:focus{box-shadow:0 0 0 3px #f4433633}.ds-select--disabled .ds-select__label{opacity:.5}\n"] }]
5784
+ ], template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-select__label\" [attr.for]=\"name()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-select__required\">*</span>\n }\n </label>\n }\n\n <!-- Trigger -->\n <button\n #selectTrigger\n type=\"button\"\n [ngClass]=\"triggerClasses()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-label]=\"label() || placeholder()\"\n (click)=\"toggle()\">\n <span class=\"ds-select__value\">{{ displayValue() }}</span>\n\n <span class=\"ds-select__icons\">\n @if (clearable() && selectedOption()) {\n <button\n type=\"button\"\n class=\"ds-select__clear\"\n aria-label=\"Effacer la s\u00E9lection\"\n (click)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ds-select__arrow\"\n [class.ds-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </button>\n\n <!-- Dropdown -->\n @if (isOpen()) {\n <div class=\"ds-select__dropdown\" role=\"presentation\">\n <!-- Search -->\n @if (searchable()) {\n <div class=\"ds-select__search\">\n <input\n #searchInput\n type=\"text\"\n class=\"ds-select__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n aria-label=\"Rechercher une option\" />\n </div>\n }\n\n <!-- Options list -->\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-select__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-select__option\"\n [class.ds-select__option--focused]=\"isOptionFocused(i)\"\n [class.ds-select__option--selected]=\"isOptionSelected(option)\"\n [class.ds-select__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\">\n <span class=\"ds-select__option-label\">{{ option.label }}</span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-select__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-select__empty\" role=\"option\" aria-disabled=\"true\">\n Aucun r\u00E9sultat\n </li>\n }\n </ul>\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-select__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-select__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-select{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-select__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-select__required{color:var(--error);margin-left:var(--space-1)}.ds-select__trigger{display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--select-padding-md, var(--space-2) var(--space-3));background-color:var(--select-bg, var(--background-main));border:1px solid var(--select-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));font-family:inherit;font-size:var(--select-font-size-md, var(--font-size-3));color:var(--select-text, var(--text-default));cursor:pointer;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-select__trigger:hover:not(:disabled){border-color:var(--select-hover-border, var(--color-primary))}.ds-select__trigger:focus{outline:none;border-color:var(--select-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--select-focus-shadow, rgba(var(--color-primary-rgb), .2))}.ds-select__trigger:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.ds-select__trigger:disabled{opacity:.5;cursor:not-allowed;background-color:var(--select-disabled-bg, var(--background-secondary))}.ds-select__trigger--placeholder{color:var(--select-placeholder, var(--text-muted))}.ds-select__value{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__icons{display:flex;align-items:center;gap:var(--space-1);margin-left:var(--space-2);color:var(--text-muted)}.ds-select__clear{display:flex;align-items:center;justify-content:center;padding:0;background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease}.ds-select__clear:hover{color:var(--error)}.ds-select__arrow{transition:transform var(--duration-fast) ease}.ds-select__arrow--open{transform:rotate(180deg)}.ds-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--select-dropdown-bg, var(--surface-overlay));border:1px solid var(--select-dropdown-border, var(--border-color));border-radius:var(--select-radius, var(--radius-2));box-shadow:var(--select-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-select__search{padding:var(--space-2);border-bottom:1px solid var(--border-color)}.ds-select__search-input{width:100%;padding:var(--space-2);border:1px solid var(--border-color);border-radius:var(--radius-1);font-family:inherit;font-size:var(--font-size-2);background-color:var(--background-main);color:var(--text-default)}.ds-select__search-input:focus{outline:none;border-color:var(--color-primary)}.ds-select__search-input::placeholder{color:var(--text-muted)}.ds-select__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--select-max-height, 200px);overflow-y:auto}.ds-select__option{display:flex;align-items:center;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-select__option:hover:not(.ds-select__option--disabled){background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--focused{background-color:var(--select-option-hover-bg, var(--surface-hover))}.ds-select__option--selected{background-color:var(--select-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--select-option-selected-text, var(--color-primary));font-weight:var(--font-weight-medium)}.ds-select__option--disabled{opacity:.5;cursor:not-allowed}.ds-select__option-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-select__check{flex-shrink:0;color:var(--color-primary)}.ds-select__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-select__helper,.ds-select__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-select__helper{color:var(--text-muted)}.ds-select__error{color:var(--error)}.ds-select--sm .ds-select__trigger{padding:var(--select-padding-sm, var(--space-1) var(--space-2));font-size:var(--select-font-size-sm, var(--font-size-2))}.ds-select--sm .ds-select__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-select--lg .ds-select__trigger{padding:var(--select-padding-lg, var(--space-3) var(--space-4));font-size:var(--select-font-size-lg, var(--font-size-4))}.ds-select--lg .ds-select__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-select--error .ds-select__trigger{border-color:var(--error)}.ds-select--error .ds-select__trigger:focus{box-shadow:0 0 0 3px rgba(var(--error-rgb),.2)}.ds-select--disabled .ds-select__label{opacity:.5}\n"] }]
5785
5785
  }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], helper: [{ type: i0.Input, args: [{ isSignal: true, alias: "helper", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], selectTrigger: [{
5786
5786
  type: ViewChild,
5787
5787
  args: ['selectTrigger']
@@ -6240,7 +6240,7 @@ class DsCombobox {
6240
6240
  useExisting: forwardRef(() => DsCombobox),
6241
6241
  multi: true,
6242
6242
  },
6243
- ], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }, { propertyName: "listbox", first: true, predicate: ["listbox"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-combobox__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-combobox__required\">*</span>\n }\n </label>\n }\n\n <!-- Input wrapper -->\n <div class=\"ds-combobox__input-wrapper\">\n <input\n #inputElement\n type=\"text\"\n [id]=\"inputId()\"\n [ngClass]=\"inputClasses()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"inputValue()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-activedescendant]=\"focusedIndex() >= 0 ? getOptionId(focusedIndex()) : null\"\n role=\"combobox\"\n autocomplete=\"off\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (input)=\"onInput($event)\" />\n\n <span class=\"ds-combobox__icons\">\n @if (clearable() && inputValue()) {\n <button\n type=\"button\"\n class=\"ds-combobox__clear\"\n aria-label=\"Effacer\"\n tabindex=\"-1\"\n (mousedown)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <span class=\"ds-combobox__arrow\" [class.ds-combobox__arrow--open]=\"isOpen()\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </span>\n </div>\n\n <!-- Dropdown -->\n @if (shouldShowDropdown()) {\n <div class=\"ds-combobox__dropdown\" role=\"presentation\">\n @if (loading()) {\n <div class=\"ds-combobox__loading\">\n <span class=\"ds-combobox__loading-spinner\"></span>\n <span>{{ loadingText() }}</span>\n </div>\n } @else {\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-combobox__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-combobox__option\"\n [class.ds-combobox__option--focused]=\"isOptionFocused(i)\"\n [class.ds-combobox__option--selected]=\"isOptionSelected(option)\"\n [class.ds-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (mousedown)=\"selectOption(option)\">\n <span class=\"ds-combobox__option-content\">\n <span class=\"ds-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"ds-combobox__option-description\">{{ option.description }}</span>\n }\n </span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-combobox__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-combobox__empty\" role=\"option\" aria-disabled=\"true\">\n {{ noResultsText() }}\n </li>\n }\n </ul>\n }\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-combobox__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-combobox__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-combobox{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-combobox__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-combobox__required{color:var(--error);margin-left:var(--space-1)}.ds-combobox__input-wrapper{position:relative;display:flex;align-items:center}.ds-combobox__input{width:100%;padding:var(--combobox-padding-md, var(--space-2) var(--space-3));padding-right:var(--space-10);background-color:var(--combobox-bg, var(--background-main));border:1px solid var(--combobox-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));font-family:inherit;font-size:var(--combobox-font-size-md, var(--font-size-3));color:var(--combobox-text, var(--text-default));transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-combobox__input::placeholder{color:var(--combobox-placeholder, var(--text-muted))}.ds-combobox__input:hover:not(:disabled){border-color:var(--combobox-hover-border, var(--color-primary))}.ds-combobox__input:focus{outline:none;border-color:var(--combobox-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--combobox-focus-shadow, rgba(125, 75, 192, .2))}.ds-combobox__input:disabled{opacity:.5;cursor:not-allowed;background-color:var(--combobox-disabled-bg, var(--background-secondary))}.ds-combobox__icons{position:absolute;right:var(--space-2);display:flex;align-items:center;gap:var(--space-1);color:var(--text-muted);pointer-events:none}.ds-combobox__clear{display:flex;align-items:center;justify-content:center;padding:var(--space-1);background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease;pointer-events:auto}.ds-combobox__clear:hover{color:var(--error)}.ds-combobox__arrow{display:flex;align-items:center;transition:transform var(--duration-fast) ease}.ds-combobox__arrow--open{transform:rotate(180deg)}.ds-combobox__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--combobox-dropdown-bg, var(--surface-overlay));border:1px solid var(--combobox-dropdown-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));box-shadow:var(--combobox-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-combobox__loading{display:flex;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);color:var(--text-muted);font-style:italic}.ds-combobox__loading-spinner{width:16px;height:16px;border:2px solid var(--border-color);border-top-color:var(--color-primary);border-radius:50%;animation:ds-combobox-spin .8s linear infinite}.ds-combobox__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--combobox-max-height, 250px);overflow-y:auto}.ds-combobox__option{display:flex;align-items:flex-start;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-combobox__option:hover:not(.ds-combobox__option--disabled){background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--focused{background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--selected{background-color:var(--combobox-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--combobox-option-selected-text, var(--color-primary))}.ds-combobox__option--disabled{opacity:.5;cursor:not-allowed}.ds-combobox__option-content{display:flex;flex-direction:column;flex:1;min-width:0}.ds-combobox__option-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-combobox__option-description{font-size:var(--font-size-1);color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:var(--space-1)}.ds-combobox__check{flex-shrink:0;color:var(--color-primary);margin-left:var(--space-2);margin-top:var(--space-1)}.ds-combobox__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-combobox__helper,.ds-combobox__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-combobox__helper{color:var(--text-muted)}.ds-combobox__error{color:var(--error)}.ds-combobox--sm .ds-combobox__input{padding:var(--combobox-padding-sm, var(--space-1) var(--space-2));padding-right:var(--space-8);font-size:var(--combobox-font-size-sm, var(--font-size-2))}.ds-combobox--sm .ds-combobox__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-combobox--lg .ds-combobox__input{padding:var(--combobox-padding-lg, var(--space-3) var(--space-4));padding-right:var(--space-12);font-size:var(--combobox-font-size-lg, var(--font-size-4))}.ds-combobox--lg .ds-combobox__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-combobox--error .ds-combobox__input{border-color:var(--error)}.ds-combobox--error .ds-combobox__input:focus{box-shadow:0 0 0 3px #f4433633}.ds-combobox--disabled .ds-combobox__label{opacity:.5}@keyframes ds-combobox-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
6243
+ ], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }, { propertyName: "listbox", first: true, predicate: ["listbox"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-combobox__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-combobox__required\">*</span>\n }\n </label>\n }\n\n <!-- Input wrapper -->\n <div class=\"ds-combobox__input-wrapper\">\n <input\n #inputElement\n type=\"text\"\n [id]=\"inputId()\"\n [ngClass]=\"inputClasses()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"inputValue()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-activedescendant]=\"focusedIndex() >= 0 ? getOptionId(focusedIndex()) : null\"\n role=\"combobox\"\n autocomplete=\"off\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (input)=\"onInput($event)\" />\n\n <span class=\"ds-combobox__icons\">\n @if (clearable() && inputValue()) {\n <button\n type=\"button\"\n class=\"ds-combobox__clear\"\n aria-label=\"Effacer\"\n tabindex=\"-1\"\n (mousedown)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <span class=\"ds-combobox__arrow\" [class.ds-combobox__arrow--open]=\"isOpen()\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </span>\n </div>\n\n <!-- Dropdown -->\n @if (shouldShowDropdown()) {\n <div class=\"ds-combobox__dropdown\" role=\"presentation\">\n @if (loading()) {\n <div class=\"ds-combobox__loading\">\n <span class=\"ds-combobox__loading-spinner\"></span>\n <span>{{ loadingText() }}</span>\n </div>\n } @else {\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-combobox__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-combobox__option\"\n [class.ds-combobox__option--focused]=\"isOptionFocused(i)\"\n [class.ds-combobox__option--selected]=\"isOptionSelected(option)\"\n [class.ds-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (mousedown)=\"selectOption(option)\">\n <span class=\"ds-combobox__option-content\">\n <span class=\"ds-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"ds-combobox__option-description\">{{ option.description }}</span>\n }\n </span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-combobox__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-combobox__empty\" role=\"option\" aria-disabled=\"true\">\n {{ noResultsText() }}\n </li>\n }\n </ul>\n }\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-combobox__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-combobox__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-combobox{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-combobox__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-combobox__required{color:var(--error);margin-left:var(--space-1)}.ds-combobox__input-wrapper{position:relative;display:flex;align-items:center}.ds-combobox__input{width:100%;padding:var(--combobox-padding-md, var(--space-2) var(--space-3));padding-right:var(--space-10);background-color:var(--combobox-bg, var(--background-main));border:1px solid var(--combobox-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));font-family:inherit;font-size:var(--combobox-font-size-md, var(--font-size-3));color:var(--combobox-text, var(--text-default));transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-combobox__input::placeholder{color:var(--combobox-placeholder, var(--text-muted))}.ds-combobox__input:hover:not(:disabled){border-color:var(--combobox-hover-border, var(--color-primary))}.ds-combobox__input:focus{outline:none;border-color:var(--combobox-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--combobox-focus-shadow, rgba(var(--color-primary-rgb), .2))}.ds-combobox__input:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.ds-combobox__input:disabled{opacity:.5;cursor:not-allowed;background-color:var(--combobox-disabled-bg, var(--background-secondary))}.ds-combobox__icons{position:absolute;right:var(--space-2);display:flex;align-items:center;gap:var(--space-1);color:var(--text-muted);pointer-events:none}.ds-combobox__clear{display:flex;align-items:center;justify-content:center;padding:var(--space-1);background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease;pointer-events:auto}.ds-combobox__clear:hover{color:var(--error)}.ds-combobox__arrow{display:flex;align-items:center;transition:transform var(--duration-fast) ease}.ds-combobox__arrow--open{transform:rotate(180deg)}.ds-combobox__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--combobox-dropdown-bg, var(--surface-overlay));border:1px solid var(--combobox-dropdown-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));box-shadow:var(--combobox-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-combobox__loading{display:flex;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);color:var(--text-muted);font-style:italic}.ds-combobox__loading-spinner{width:16px;height:16px;border:2px solid var(--border-color);border-top-color:var(--color-primary);border-radius:50%;animation:ds-combobox-spin .8s linear infinite}.ds-combobox__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--combobox-max-height, 250px);overflow-y:auto}.ds-combobox__option{display:flex;align-items:flex-start;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-combobox__option:hover:not(.ds-combobox__option--disabled){background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--focused{background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--selected{background-color:var(--combobox-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--combobox-option-selected-text, var(--color-primary))}.ds-combobox__option--disabled{opacity:.5;cursor:not-allowed}.ds-combobox__option-content{display:flex;flex-direction:column;flex:1;min-width:0}.ds-combobox__option-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-combobox__option-description{font-size:var(--font-size-1);color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:var(--space-1)}.ds-combobox__check{flex-shrink:0;color:var(--color-primary);margin-left:var(--space-2);margin-top:var(--space-1)}.ds-combobox__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-combobox__helper,.ds-combobox__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-combobox__helper{color:var(--text-muted)}.ds-combobox__error{color:var(--error)}.ds-combobox--sm .ds-combobox__input{padding:var(--combobox-padding-sm, var(--space-1) var(--space-2));padding-right:var(--space-8);font-size:var(--combobox-font-size-sm, var(--font-size-2))}.ds-combobox--sm .ds-combobox__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-combobox--lg .ds-combobox__input{padding:var(--combobox-padding-lg, var(--space-3) var(--space-4));padding-right:var(--space-12);font-size:var(--combobox-font-size-lg, var(--font-size-4))}.ds-combobox--lg .ds-combobox__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-combobox--error .ds-combobox__input{border-color:var(--error)}.ds-combobox--error .ds-combobox__input:focus{box-shadow:0 0 0 3px rgba(var(--error-rgb),.2)}.ds-combobox--disabled .ds-combobox__label{opacity:.5}@keyframes ds-combobox-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
6244
6244
  }
6245
6245
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsCombobox, decorators: [{
6246
6246
  type: Component,
@@ -6250,7 +6250,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
6250
6250
  useExisting: forwardRef(() => DsCombobox),
6251
6251
  multi: true,
6252
6252
  },
6253
- ], template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-combobox__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-combobox__required\">*</span>\n }\n </label>\n }\n\n <!-- Input wrapper -->\n <div class=\"ds-combobox__input-wrapper\">\n <input\n #inputElement\n type=\"text\"\n [id]=\"inputId()\"\n [ngClass]=\"inputClasses()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"inputValue()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-activedescendant]=\"focusedIndex() >= 0 ? getOptionId(focusedIndex()) : null\"\n role=\"combobox\"\n autocomplete=\"off\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (input)=\"onInput($event)\" />\n\n <span class=\"ds-combobox__icons\">\n @if (clearable() && inputValue()) {\n <button\n type=\"button\"\n class=\"ds-combobox__clear\"\n aria-label=\"Effacer\"\n tabindex=\"-1\"\n (mousedown)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <span class=\"ds-combobox__arrow\" [class.ds-combobox__arrow--open]=\"isOpen()\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </span>\n </div>\n\n <!-- Dropdown -->\n @if (shouldShowDropdown()) {\n <div class=\"ds-combobox__dropdown\" role=\"presentation\">\n @if (loading()) {\n <div class=\"ds-combobox__loading\">\n <span class=\"ds-combobox__loading-spinner\"></span>\n <span>{{ loadingText() }}</span>\n </div>\n } @else {\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-combobox__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-combobox__option\"\n [class.ds-combobox__option--focused]=\"isOptionFocused(i)\"\n [class.ds-combobox__option--selected]=\"isOptionSelected(option)\"\n [class.ds-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (mousedown)=\"selectOption(option)\">\n <span class=\"ds-combobox__option-content\">\n <span class=\"ds-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"ds-combobox__option-description\">{{ option.description }}</span>\n }\n </span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-combobox__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-combobox__empty\" role=\"option\" aria-disabled=\"true\">\n {{ noResultsText() }}\n </li>\n }\n </ul>\n }\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-combobox__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-combobox__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-combobox{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-combobox__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-combobox__required{color:var(--error);margin-left:var(--space-1)}.ds-combobox__input-wrapper{position:relative;display:flex;align-items:center}.ds-combobox__input{width:100%;padding:var(--combobox-padding-md, var(--space-2) var(--space-3));padding-right:var(--space-10);background-color:var(--combobox-bg, var(--background-main));border:1px solid var(--combobox-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));font-family:inherit;font-size:var(--combobox-font-size-md, var(--font-size-3));color:var(--combobox-text, var(--text-default));transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-combobox__input::placeholder{color:var(--combobox-placeholder, var(--text-muted))}.ds-combobox__input:hover:not(:disabled){border-color:var(--combobox-hover-border, var(--color-primary))}.ds-combobox__input:focus{outline:none;border-color:var(--combobox-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--combobox-focus-shadow, rgba(125, 75, 192, .2))}.ds-combobox__input:disabled{opacity:.5;cursor:not-allowed;background-color:var(--combobox-disabled-bg, var(--background-secondary))}.ds-combobox__icons{position:absolute;right:var(--space-2);display:flex;align-items:center;gap:var(--space-1);color:var(--text-muted);pointer-events:none}.ds-combobox__clear{display:flex;align-items:center;justify-content:center;padding:var(--space-1);background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease;pointer-events:auto}.ds-combobox__clear:hover{color:var(--error)}.ds-combobox__arrow{display:flex;align-items:center;transition:transform var(--duration-fast) ease}.ds-combobox__arrow--open{transform:rotate(180deg)}.ds-combobox__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--combobox-dropdown-bg, var(--surface-overlay));border:1px solid var(--combobox-dropdown-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));box-shadow:var(--combobox-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-combobox__loading{display:flex;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);color:var(--text-muted);font-style:italic}.ds-combobox__loading-spinner{width:16px;height:16px;border:2px solid var(--border-color);border-top-color:var(--color-primary);border-radius:50%;animation:ds-combobox-spin .8s linear infinite}.ds-combobox__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--combobox-max-height, 250px);overflow-y:auto}.ds-combobox__option{display:flex;align-items:flex-start;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-combobox__option:hover:not(.ds-combobox__option--disabled){background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--focused{background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--selected{background-color:var(--combobox-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--combobox-option-selected-text, var(--color-primary))}.ds-combobox__option--disabled{opacity:.5;cursor:not-allowed}.ds-combobox__option-content{display:flex;flex-direction:column;flex:1;min-width:0}.ds-combobox__option-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-combobox__option-description{font-size:var(--font-size-1);color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:var(--space-1)}.ds-combobox__check{flex-shrink:0;color:var(--color-primary);margin-left:var(--space-2);margin-top:var(--space-1)}.ds-combobox__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-combobox__helper,.ds-combobox__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-combobox__helper{color:var(--text-muted)}.ds-combobox__error{color:var(--error)}.ds-combobox--sm .ds-combobox__input{padding:var(--combobox-padding-sm, var(--space-1) var(--space-2));padding-right:var(--space-8);font-size:var(--combobox-font-size-sm, var(--font-size-2))}.ds-combobox--sm .ds-combobox__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-combobox--lg .ds-combobox__input{padding:var(--combobox-padding-lg, var(--space-3) var(--space-4));padding-right:var(--space-12);font-size:var(--combobox-font-size-lg, var(--font-size-4))}.ds-combobox--lg .ds-combobox__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-combobox--error .ds-combobox__input{border-color:var(--error)}.ds-combobox--error .ds-combobox__input:focus{box-shadow:0 0 0 3px #f4433633}.ds-combobox--disabled .ds-combobox__label{opacity:.5}@keyframes ds-combobox-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
6253
+ ], template: "<div [ngClass]=\"containerClasses()\">\n <!-- Label -->\n @if (label()) {\n <label class=\"ds-combobox__label\" [attr.for]=\"inputId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"ds-combobox__required\">*</span>\n }\n </label>\n }\n\n <!-- Input wrapper -->\n <div class=\"ds-combobox__input-wrapper\">\n <input\n #inputElement\n type=\"text\"\n [id]=\"inputId()\"\n [ngClass]=\"inputClasses()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"inputValue()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-activedescendant]=\"focusedIndex() >= 0 ? getOptionId(focusedIndex()) : null\"\n role=\"combobox\"\n autocomplete=\"off\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (input)=\"onInput($event)\" />\n\n <span class=\"ds-combobox__icons\">\n @if (clearable() && inputValue()) {\n <button\n type=\"button\"\n class=\"ds-combobox__clear\"\n aria-label=\"Effacer\"\n tabindex=\"-1\"\n (mousedown)=\"clear($event)\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <span class=\"ds-combobox__arrow\" [class.ds-combobox__arrow--open]=\"isOpen()\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </span>\n </span>\n </div>\n\n <!-- Dropdown -->\n @if (shouldShowDropdown()) {\n <div class=\"ds-combobox__dropdown\" role=\"presentation\">\n @if (loading()) {\n <div class=\"ds-combobox__loading\">\n <span class=\"ds-combobox__loading-spinner\"></span>\n <span>{{ loadingText() }}</span>\n </div>\n } @else {\n <ul\n #listbox\n [id]=\"listboxId()\"\n class=\"ds-combobox__listbox\"\n role=\"listbox\"\n [attr.aria-label]=\"label() || 'Options'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n [id]=\"getOptionId(i)\"\n class=\"ds-combobox__option\"\n [class.ds-combobox__option--focused]=\"isOptionFocused(i)\"\n [class.ds-combobox__option--selected]=\"isOptionSelected(option)\"\n [class.ds-combobox__option--disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (mousedown)=\"selectOption(option)\">\n <span class=\"ds-combobox__option-content\">\n <span class=\"ds-combobox__option-label\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"ds-combobox__option-description\">{{ option.description }}</span>\n }\n </span>\n @if (isOptionSelected(option)) {\n <svg\n class=\"ds-combobox__check\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n </li>\n } @empty {\n <li class=\"ds-combobox__empty\" role=\"option\" aria-disabled=\"true\">\n {{ noResultsText() }}\n </li>\n }\n </ul>\n }\n </div>\n }\n\n <!-- Helper / Error -->\n @if (error()) {\n <span class=\"ds-combobox__error\" role=\"alert\">{{ error() }}</span>\n } @else if (helper()) {\n <span class=\"ds-combobox__helper\">{{ helper() }}</span>\n }\n</div>\n", styles: [".ds-combobox{position:relative;display:inline-flex;flex-direction:column;width:100%;font-family:var(--font-family-base)}.ds-combobox__label{display:block;margin-bottom:var(--space-1);font-size:var(--font-size-2);font-weight:var(--font-weight-medium);color:var(--text-default)}.ds-combobox__required{color:var(--error);margin-left:var(--space-1)}.ds-combobox__input-wrapper{position:relative;display:flex;align-items:center}.ds-combobox__input{width:100%;padding:var(--combobox-padding-md, var(--space-2) var(--space-3));padding-right:var(--space-10);background-color:var(--combobox-bg, var(--background-main));border:1px solid var(--combobox-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));font-family:inherit;font-size:var(--combobox-font-size-md, var(--font-size-3));color:var(--combobox-text, var(--text-default));transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.ds-combobox__input::placeholder{color:var(--combobox-placeholder, var(--text-muted))}.ds-combobox__input:hover:not(:disabled){border-color:var(--combobox-hover-border, var(--color-primary))}.ds-combobox__input:focus{outline:none;border-color:var(--combobox-focus-border, var(--color-primary));box-shadow:0 0 0 3px var(--combobox-focus-shadow, rgba(var(--color-primary-rgb), .2))}.ds-combobox__input:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.ds-combobox__input:disabled{opacity:.5;cursor:not-allowed;background-color:var(--combobox-disabled-bg, var(--background-secondary))}.ds-combobox__icons{position:absolute;right:var(--space-2);display:flex;align-items:center;gap:var(--space-1);color:var(--text-muted);pointer-events:none}.ds-combobox__clear{display:flex;align-items:center;justify-content:center;padding:var(--space-1);background:none;border:none;color:var(--text-muted);cursor:pointer;border-radius:var(--radius-round);transition:color var(--duration-fast) ease;pointer-events:auto}.ds-combobox__clear:hover{color:var(--error)}.ds-combobox__arrow{display:flex;align-items:center;transition:transform var(--duration-fast) ease}.ds-combobox__arrow--open{transform:rotate(180deg)}.ds-combobox__dropdown{position:absolute;top:100%;left:0;right:0;z-index:var(--z-dropdown, 1000);margin-top:var(--space-1);background-color:var(--combobox-dropdown-bg, var(--surface-overlay));border:1px solid var(--combobox-dropdown-border, var(--border-color));border-radius:var(--combobox-radius, var(--radius-2));box-shadow:var(--combobox-dropdown-shadow, var(--shadow-2));overflow:hidden}.ds-combobox__loading{display:flex;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);color:var(--text-muted);font-style:italic}.ds-combobox__loading-spinner{width:16px;height:16px;border:2px solid var(--border-color);border-top-color:var(--color-primary);border-radius:50%;animation:ds-combobox-spin .8s linear infinite}.ds-combobox__listbox{list-style:none;margin:0;padding:var(--space-1) 0;max-height:var(--combobox-max-height, 250px);overflow-y:auto}.ds-combobox__option{display:flex;align-items:flex-start;justify-content:space-between;padding:var(--space-2) var(--space-3);cursor:pointer;transition:background-color var(--duration-fast) ease}.ds-combobox__option:hover:not(.ds-combobox__option--disabled){background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--focused{background-color:var(--combobox-option-hover-bg, var(--surface-hover))}.ds-combobox__option--selected{background-color:var(--combobox-option-selected-bg, color-mix(in oklab, var(--color-primary) 10%, transparent));color:var(--combobox-option-selected-text, var(--color-primary))}.ds-combobox__option--disabled{opacity:.5;cursor:not-allowed}.ds-combobox__option-content{display:flex;flex-direction:column;flex:1;min-width:0}.ds-combobox__option-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-combobox__option-description{font-size:var(--font-size-1);color:var(--text-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:var(--space-1)}.ds-combobox__check{flex-shrink:0;color:var(--color-primary);margin-left:var(--space-2);margin-top:var(--space-1)}.ds-combobox__empty{padding:var(--space-4);text-align:center;color:var(--text-muted);font-style:italic}.ds-combobox__helper,.ds-combobox__error{margin-top:var(--space-1);font-size:var(--font-size-1)}.ds-combobox__helper{color:var(--text-muted)}.ds-combobox__error{color:var(--error)}.ds-combobox--sm .ds-combobox__input{padding:var(--combobox-padding-sm, var(--space-1) var(--space-2));padding-right:var(--space-8);font-size:var(--combobox-font-size-sm, var(--font-size-2))}.ds-combobox--sm .ds-combobox__option{padding:var(--space-1) var(--space-2);font-size:var(--font-size-2)}.ds-combobox--lg .ds-combobox__input{padding:var(--combobox-padding-lg, var(--space-3) var(--space-4));padding-right:var(--space-12);font-size:var(--combobox-font-size-lg, var(--font-size-4))}.ds-combobox--lg .ds-combobox__option{padding:var(--space-3) var(--space-4);font-size:var(--font-size-4)}.ds-combobox--error .ds-combobox__input{border-color:var(--error)}.ds-combobox--error .ds-combobox__input:focus{box-shadow:0 0 0 3px rgba(var(--error-rgb),.2)}.ds-combobox--disabled .ds-combobox__label{opacity:.5}@keyframes ds-combobox-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
6254
6254
  }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], helper: [{ type: i0.Input, args: [{ isSignal: true, alias: "helper", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], allowCustom: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowCustom", required: false }] }], minChars: [{ type: i0.Input, args: [{ isSignal: true, alias: "minChars", required: false }] }], maxResults: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxResults", required: false }] }], noResultsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsText", required: false }] }], loadingText: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingText", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], inputChange: [{ type: i0.Output, args: ["inputChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], inputElement: [{
6255
6255
  type: ViewChild,
6256
6256
  args: ['inputElement']
@@ -8119,7 +8119,7 @@ class DsSlider {
8119
8119
  useExisting: forwardRef(() => DsSlider),
8120
8120
  multi: true,
8121
8121
  },
8122
- ], viewQueries: [{ propertyName: "trackElement", first: true, predicate: ["track"], descendants: true }, { propertyName: "thumb1Element", first: true, predicate: ["thumb1"], descendants: true }, { propertyName: "thumb2Element", first: true, predicate: ["thumb2"], descendants: true }], ngImport: i0, template: "<div [class]=\"containerClasses()\">\n <!-- Min label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--min\">\n {{ getTickLabel(min()) }}\n </span>\n }\n\n <!-- Track container -->\n <div class=\"ds-slider__track-container\">\n <!-- Track background -->\n <div\n #track\n class=\"ds-slider__track\"\n (click)=\"onTrackClick($event)\"\n role=\"presentation\">\n <!-- Fill -->\n <div\n class=\"ds-slider__fill\"\n [ngStyle]=\"fillStyle()\">\n </div>\n\n <!-- Ticks -->\n @if (showTicks()) {\n <div class=\"ds-slider__ticks\">\n @for (tick of ticks(); track tick) {\n <div\n class=\"ds-slider__tick\"\n [ngStyle]=\"isVertical() ? { bottom: getTickPosition(tick) + '%' } : { left: getTickPosition(tick) + '%' }\">\n </div>\n }\n </div>\n }\n\n <!-- Thumb 1 (always present) -->\n <div\n #thumb1\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 0 || dragging() === 0\"\n [ngStyle]=\"thumb1Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"isRange() ? value2() : max()\"\n [attr.aria-valuenow]=\"value1()\"\n [attr.aria-valuetext]=\"getAriaValueText(0)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 0)\"\n (mousedown)=\"onThumbMouseDown($event, 0)\"\n (focus)=\"onThumbFocus(0)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label1() }}</span>\n }\n </div>\n\n <!-- Thumb 2 (only for range mode) -->\n @if (isRange()) {\n <div\n #thumb2\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 1 || dragging() === 1\"\n [ngStyle]=\"thumb2Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"value1()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"value2()\"\n [attr.aria-valuetext]=\"getAriaValueText(1)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 1)\"\n (mousedown)=\"onThumbMouseDown($event, 1)\"\n (focus)=\"onThumbFocus(1)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label2() }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Max label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--max\">\n {{ getTickLabel(max()) }}\n </span>\n }\n</div>\n", styles: [".ds-slider{display:flex;align-items:center;gap:var(--slider-label-gap, var(--space-3, .75rem));-webkit-user-select:none;user-select:none}.ds-slider__label{flex-shrink:0;font-size:var(--slider-label-font-size, var(--font-size-2, .875rem));color:var(--slider-label-color, var(--gray-700, #374151));font-weight:500}.ds-slider__label--min{order:1}.ds-slider__label--max{order:3}.ds-slider__track-container{flex:1;order:2;position:relative;display:flex;align-items:center}.ds-slider__track{position:relative;width:100%;height:var(--slider-track-height-md, 6px);background-color:var(--slider-track-bg, var(--gray-200, #e5e7eb));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));cursor:pointer}.ds-slider__fill{position:absolute;background-color:var(--slider-fill-bg, var(--color-primary, #3b82f6));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));height:100%;transition:all .15s ease;pointer-events:none}.ds-slider__ticks{position:absolute;width:100%;height:100%;pointer-events:none}.ds-slider__tick{position:absolute;width:var(--slider-tick-size, 2px);height:var(--slider-tick-size, 2px);background-color:var(--slider-tick-color, var(--gray-400, #9ca3af));border-radius:50%;transform:translate(-50%,-50%);top:50%}.ds-slider__thumb{position:absolute;width:var(--slider-thumb-size-md, 20px);height:var(--slider-thumb-size-md, 20px);background-color:var(--slider-thumb-bg, var(--white, #ffffff));border:var(--slider-thumb-border-width, 2px) solid var(--slider-thumb-border-color, var(--color-primary, #3b82f6));border-radius:50%;box-shadow:var(--slider-thumb-shadow, 0 1px 3px rgba(0, 0, 0, .1));cursor:grab;transform:translate(-50%,-50%);top:50%;transition:transform .15s ease,box-shadow .15s ease;outline:none}.ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,-50%) scale(1.1);box-shadow:var(--slider-thumb-shadow-hover, 0 2px 8px rgba(0, 0, 0, .15))}.ds-slider__thumb:focus-visible{box-shadow:var(--slider-thumb-shadow-focus, 0 0 0 3px rgba(59, 130, 246, .3))}.ds-slider__thumb--active{cursor:grabbing;transform:translate(-50%,-50%) scale(1.15);box-shadow:var(--slider-thumb-shadow-active, 0 0 0 4px rgba(59, 130, 246, .2))}.ds-slider__thumb[aria-disabled=true]{cursor:not-allowed;opacity:.5}.ds-slider__thumb-label{position:absolute;top:-32px;left:50%;transform:translate(-50%);background-color:var(--slider-thumb-label-bg, var(--gray-900, #111827));color:var(--slider-thumb-label-color, var(--white, #ffffff));font-size:var(--font-size-1, .75rem);padding:var(--space-1, .25rem) var(--space-2, .5rem);border-radius:var(--radius-1, .25rem);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.ds-slider__thumb:hover .ds-slider__thumb-label,.ds-slider__thumb:focus .ds-slider__thumb-label,.ds-slider__thumb--active .ds-slider__thumb-label{opacity:1}.ds-slider--sm .ds-slider__track{height:var(--slider-track-height-sm, 4px)}.ds-slider--sm .ds-slider__thumb{width:var(--slider-thumb-size-sm, 16px);height:var(--slider-thumb-size-sm, 16px)}.ds-slider--sm .ds-slider__label{font-size:var(--font-size-1, .75rem)}.ds-slider--lg .ds-slider__track{height:var(--slider-track-height-lg, 8px)}.ds-slider--lg .ds-slider__thumb{width:var(--slider-thumb-size-lg, 24px);height:var(--slider-thumb-size-lg, 24px)}.ds-slider--lg .ds-slider__label{font-size:var(--font-size-3, 1rem)}.ds-slider--disabled{opacity:.6;pointer-events:none}.ds-slider--disabled .ds-slider__track{cursor:not-allowed}.ds-slider--vertical{flex-direction:column;height:200px;width:auto}.ds-slider--vertical .ds-slider__label--min{order:3}.ds-slider--vertical .ds-slider__label--max{order:1}.ds-slider--vertical .ds-slider__track-container{flex:1;width:auto;height:100%;display:flex;justify-content:center}.ds-slider--vertical .ds-slider__track{width:var(--slider-track-height-md, 6px);height:100%}.ds-slider--vertical .ds-slider__fill{width:100%;height:auto}.ds-slider--vertical .ds-slider__thumb{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical .ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,50%) scale(1.1)}.ds-slider--vertical .ds-slider__thumb--active{transform:translate(-50%,50%) scale(1.15)}.ds-slider--vertical .ds-slider__thumb-label{top:50%;left:32px;transform:translateY(-50%)}.ds-slider--vertical .ds-slider__tick{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical.ds-slider--sm .ds-slider__track{width:var(--slider-track-height-sm, 4px)}.ds-slider--vertical.ds-slider--lg .ds-slider__track{width:var(--slider-track-height-lg, 8px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
8122
+ ], viewQueries: [{ propertyName: "trackElement", first: true, predicate: ["track"], descendants: true }, { propertyName: "thumb1Element", first: true, predicate: ["thumb1"], descendants: true }, { propertyName: "thumb2Element", first: true, predicate: ["thumb2"], descendants: true }], ngImport: i0, template: "<div [class]=\"containerClasses()\">\n <!-- Min label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--min\">\n {{ getTickLabel(min()) }}\n </span>\n }\n\n <!-- Track container -->\n <div class=\"ds-slider__track-container\">\n <!-- Track background -->\n <div\n #track\n class=\"ds-slider__track\"\n (click)=\"onTrackClick($event)\"\n role=\"presentation\">\n <!-- Fill -->\n <div\n class=\"ds-slider__fill\"\n [ngStyle]=\"fillStyle()\">\n </div>\n\n <!-- Ticks -->\n @if (showTicks()) {\n <div class=\"ds-slider__ticks\">\n @for (tick of ticks(); track tick) {\n <div\n class=\"ds-slider__tick\"\n [ngStyle]=\"isVertical() ? { bottom: getTickPosition(tick) + '%' } : { left: getTickPosition(tick) + '%' }\">\n </div>\n }\n </div>\n }\n\n <!-- Thumb 1 (always present) -->\n <div\n #thumb1\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 0 || dragging() === 0\"\n [ngStyle]=\"thumb1Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"isRange() ? value2() : max()\"\n [attr.aria-valuenow]=\"value1()\"\n [attr.aria-valuetext]=\"getAriaValueText(0)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 0)\"\n (mousedown)=\"onThumbMouseDown($event, 0)\"\n (focus)=\"onThumbFocus(0)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label1() }}</span>\n }\n </div>\n\n <!-- Thumb 2 (only for range mode) -->\n @if (isRange()) {\n <div\n #thumb2\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 1 || dragging() === 1\"\n [ngStyle]=\"thumb2Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"value1()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"value2()\"\n [attr.aria-valuetext]=\"getAriaValueText(1)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 1)\"\n (mousedown)=\"onThumbMouseDown($event, 1)\"\n (focus)=\"onThumbFocus(1)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label2() }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Max label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--max\">\n {{ getTickLabel(max()) }}\n </span>\n }\n</div>\n", styles: [".ds-slider{display:flex;align-items:center;gap:var(--slider-label-gap, var(--space-3, .75rem));-webkit-user-select:none;user-select:none}.ds-slider__label{flex-shrink:0;font-size:var(--slider-label-font-size, var(--font-size-2, .875rem));color:var(--slider-label-color, var(--gray-700, #374151));font-weight:500}.ds-slider__label--min{order:1}.ds-slider__label--max{order:3}.ds-slider__track-container{flex:1;order:2;position:relative;display:flex;align-items:center}.ds-slider__track{position:relative;width:100%;height:var(--slider-track-height-md, 6px);background-color:var(--slider-track-bg, var(--gray-200, #e5e7eb));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));cursor:pointer}.ds-slider__fill{position:absolute;background-color:var(--slider-fill-bg, var(--color-primary, #3b82f6));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));height:100%;transition:all .15s ease;pointer-events:none}.ds-slider__ticks{position:absolute;width:100%;height:100%;pointer-events:none}.ds-slider__tick{position:absolute;width:var(--slider-tick-size, 2px);height:var(--slider-tick-size, 2px);background-color:var(--slider-tick-color, var(--gray-400, #9ca3af));border-radius:50%;transform:translate(-50%,-50%);top:50%}.ds-slider__thumb{position:absolute;width:var(--slider-thumb-size-md, 20px);height:var(--slider-thumb-size-md, 20px);background-color:var(--slider-thumb-bg, var(--white, #ffffff));border:var(--slider-thumb-border-width, 2px) solid var(--slider-thumb-border-color, var(--color-primary, #3b82f6));border-radius:50%;box-shadow:var(--slider-thumb-shadow, 0 1px 3px rgba(var(--black-rgb), .1));cursor:grab;transform:translate(-50%,-50%);top:50%;transition:transform .15s ease,box-shadow .15s ease;outline:none}.ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,-50%) scale(1.1);box-shadow:var(--slider-thumb-shadow-hover, 0 2px 8px rgba(var(--black-rgb), .15))}.ds-slider__thumb:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;box-shadow:var(--slider-thumb-shadow-focus, 0 0 0 3px rgba(var(--color-primary-rgb), .3))}.ds-slider__thumb--active{cursor:grabbing;transform:translate(-50%,-50%) scale(1.15);box-shadow:var(--slider-thumb-shadow-active, 0 0 0 4px rgba(var(--color-primary-rgb), .2))}.ds-slider__thumb[aria-disabled=true]{cursor:not-allowed;opacity:.5}.ds-slider__thumb-label{position:absolute;top:-32px;left:50%;transform:translate(-50%);background-color:var(--slider-thumb-label-bg, var(--gray-900, #111827));color:var(--slider-thumb-label-color, var(--white, #ffffff));font-size:var(--font-size-1, .75rem);padding:var(--space-1, .25rem) var(--space-2, .5rem);border-radius:var(--radius-1, .25rem);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.ds-slider__thumb:hover .ds-slider__thumb-label,.ds-slider__thumb:focus .ds-slider__thumb-label,.ds-slider__thumb--active .ds-slider__thumb-label{opacity:1}.ds-slider--sm .ds-slider__track{height:var(--slider-track-height-sm, 4px)}.ds-slider--sm .ds-slider__thumb{width:var(--slider-thumb-size-sm, 16px);height:var(--slider-thumb-size-sm, 16px)}.ds-slider--sm .ds-slider__label{font-size:var(--font-size-1, .75rem)}.ds-slider--lg .ds-slider__track{height:var(--slider-track-height-lg, 8px)}.ds-slider--lg .ds-slider__thumb{width:var(--slider-thumb-size-lg, 24px);height:var(--slider-thumb-size-lg, 24px)}.ds-slider--lg .ds-slider__label{font-size:var(--font-size-3, 1rem)}.ds-slider--disabled{opacity:.6;pointer-events:none}.ds-slider--disabled .ds-slider__track{cursor:not-allowed}.ds-slider--vertical{flex-direction:column;height:200px;width:auto}.ds-slider--vertical .ds-slider__label--min{order:3}.ds-slider--vertical .ds-slider__label--max{order:1}.ds-slider--vertical .ds-slider__track-container{flex:1;width:auto;height:100%;display:flex;justify-content:center}.ds-slider--vertical .ds-slider__track{width:var(--slider-track-height-md, 6px);height:100%}.ds-slider--vertical .ds-slider__fill{width:100%;height:auto}.ds-slider--vertical .ds-slider__thumb{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical .ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,50%) scale(1.1)}.ds-slider--vertical .ds-slider__thumb--active{transform:translate(-50%,50%) scale(1.15)}.ds-slider--vertical .ds-slider__thumb-label{top:50%;left:32px;transform:translateY(-50%)}.ds-slider--vertical .ds-slider__tick{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical.ds-slider--sm .ds-slider__track{width:var(--slider-track-height-sm, 4px)}.ds-slider--vertical.ds-slider--lg .ds-slider__track{width:var(--slider-track-height-lg, 8px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
8123
8123
  }
8124
8124
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsSlider, decorators: [{
8125
8125
  type: Component,
@@ -8129,7 +8129,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
8129
8129
  useExisting: forwardRef(() => DsSlider),
8130
8130
  multi: true,
8131
8131
  },
8132
- ], template: "<div [class]=\"containerClasses()\">\n <!-- Min label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--min\">\n {{ getTickLabel(min()) }}\n </span>\n }\n\n <!-- Track container -->\n <div class=\"ds-slider__track-container\">\n <!-- Track background -->\n <div\n #track\n class=\"ds-slider__track\"\n (click)=\"onTrackClick($event)\"\n role=\"presentation\">\n <!-- Fill -->\n <div\n class=\"ds-slider__fill\"\n [ngStyle]=\"fillStyle()\">\n </div>\n\n <!-- Ticks -->\n @if (showTicks()) {\n <div class=\"ds-slider__ticks\">\n @for (tick of ticks(); track tick) {\n <div\n class=\"ds-slider__tick\"\n [ngStyle]=\"isVertical() ? { bottom: getTickPosition(tick) + '%' } : { left: getTickPosition(tick) + '%' }\">\n </div>\n }\n </div>\n }\n\n <!-- Thumb 1 (always present) -->\n <div\n #thumb1\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 0 || dragging() === 0\"\n [ngStyle]=\"thumb1Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"isRange() ? value2() : max()\"\n [attr.aria-valuenow]=\"value1()\"\n [attr.aria-valuetext]=\"getAriaValueText(0)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 0)\"\n (mousedown)=\"onThumbMouseDown($event, 0)\"\n (focus)=\"onThumbFocus(0)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label1() }}</span>\n }\n </div>\n\n <!-- Thumb 2 (only for range mode) -->\n @if (isRange()) {\n <div\n #thumb2\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 1 || dragging() === 1\"\n [ngStyle]=\"thumb2Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"value1()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"value2()\"\n [attr.aria-valuetext]=\"getAriaValueText(1)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 1)\"\n (mousedown)=\"onThumbMouseDown($event, 1)\"\n (focus)=\"onThumbFocus(1)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label2() }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Max label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--max\">\n {{ getTickLabel(max()) }}\n </span>\n }\n</div>\n", styles: [".ds-slider{display:flex;align-items:center;gap:var(--slider-label-gap, var(--space-3, .75rem));-webkit-user-select:none;user-select:none}.ds-slider__label{flex-shrink:0;font-size:var(--slider-label-font-size, var(--font-size-2, .875rem));color:var(--slider-label-color, var(--gray-700, #374151));font-weight:500}.ds-slider__label--min{order:1}.ds-slider__label--max{order:3}.ds-slider__track-container{flex:1;order:2;position:relative;display:flex;align-items:center}.ds-slider__track{position:relative;width:100%;height:var(--slider-track-height-md, 6px);background-color:var(--slider-track-bg, var(--gray-200, #e5e7eb));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));cursor:pointer}.ds-slider__fill{position:absolute;background-color:var(--slider-fill-bg, var(--color-primary, #3b82f6));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));height:100%;transition:all .15s ease;pointer-events:none}.ds-slider__ticks{position:absolute;width:100%;height:100%;pointer-events:none}.ds-slider__tick{position:absolute;width:var(--slider-tick-size, 2px);height:var(--slider-tick-size, 2px);background-color:var(--slider-tick-color, var(--gray-400, #9ca3af));border-radius:50%;transform:translate(-50%,-50%);top:50%}.ds-slider__thumb{position:absolute;width:var(--slider-thumb-size-md, 20px);height:var(--slider-thumb-size-md, 20px);background-color:var(--slider-thumb-bg, var(--white, #ffffff));border:var(--slider-thumb-border-width, 2px) solid var(--slider-thumb-border-color, var(--color-primary, #3b82f6));border-radius:50%;box-shadow:var(--slider-thumb-shadow, 0 1px 3px rgba(0, 0, 0, .1));cursor:grab;transform:translate(-50%,-50%);top:50%;transition:transform .15s ease,box-shadow .15s ease;outline:none}.ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,-50%) scale(1.1);box-shadow:var(--slider-thumb-shadow-hover, 0 2px 8px rgba(0, 0, 0, .15))}.ds-slider__thumb:focus-visible{box-shadow:var(--slider-thumb-shadow-focus, 0 0 0 3px rgba(59, 130, 246, .3))}.ds-slider__thumb--active{cursor:grabbing;transform:translate(-50%,-50%) scale(1.15);box-shadow:var(--slider-thumb-shadow-active, 0 0 0 4px rgba(59, 130, 246, .2))}.ds-slider__thumb[aria-disabled=true]{cursor:not-allowed;opacity:.5}.ds-slider__thumb-label{position:absolute;top:-32px;left:50%;transform:translate(-50%);background-color:var(--slider-thumb-label-bg, var(--gray-900, #111827));color:var(--slider-thumb-label-color, var(--white, #ffffff));font-size:var(--font-size-1, .75rem);padding:var(--space-1, .25rem) var(--space-2, .5rem);border-radius:var(--radius-1, .25rem);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.ds-slider__thumb:hover .ds-slider__thumb-label,.ds-slider__thumb:focus .ds-slider__thumb-label,.ds-slider__thumb--active .ds-slider__thumb-label{opacity:1}.ds-slider--sm .ds-slider__track{height:var(--slider-track-height-sm, 4px)}.ds-slider--sm .ds-slider__thumb{width:var(--slider-thumb-size-sm, 16px);height:var(--slider-thumb-size-sm, 16px)}.ds-slider--sm .ds-slider__label{font-size:var(--font-size-1, .75rem)}.ds-slider--lg .ds-slider__track{height:var(--slider-track-height-lg, 8px)}.ds-slider--lg .ds-slider__thumb{width:var(--slider-thumb-size-lg, 24px);height:var(--slider-thumb-size-lg, 24px)}.ds-slider--lg .ds-slider__label{font-size:var(--font-size-3, 1rem)}.ds-slider--disabled{opacity:.6;pointer-events:none}.ds-slider--disabled .ds-slider__track{cursor:not-allowed}.ds-slider--vertical{flex-direction:column;height:200px;width:auto}.ds-slider--vertical .ds-slider__label--min{order:3}.ds-slider--vertical .ds-slider__label--max{order:1}.ds-slider--vertical .ds-slider__track-container{flex:1;width:auto;height:100%;display:flex;justify-content:center}.ds-slider--vertical .ds-slider__track{width:var(--slider-track-height-md, 6px);height:100%}.ds-slider--vertical .ds-slider__fill{width:100%;height:auto}.ds-slider--vertical .ds-slider__thumb{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical .ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,50%) scale(1.1)}.ds-slider--vertical .ds-slider__thumb--active{transform:translate(-50%,50%) scale(1.15)}.ds-slider--vertical .ds-slider__thumb-label{top:50%;left:32px;transform:translateY(-50%)}.ds-slider--vertical .ds-slider__tick{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical.ds-slider--sm .ds-slider__track{width:var(--slider-track-height-sm, 4px)}.ds-slider--vertical.ds-slider--lg .ds-slider__track{width:var(--slider-track-height-lg, 8px)}\n"] }]
8132
+ ], template: "<div [class]=\"containerClasses()\">\n <!-- Min label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--min\">\n {{ getTickLabel(min()) }}\n </span>\n }\n\n <!-- Track container -->\n <div class=\"ds-slider__track-container\">\n <!-- Track background -->\n <div\n #track\n class=\"ds-slider__track\"\n (click)=\"onTrackClick($event)\"\n role=\"presentation\">\n <!-- Fill -->\n <div\n class=\"ds-slider__fill\"\n [ngStyle]=\"fillStyle()\">\n </div>\n\n <!-- Ticks -->\n @if (showTicks()) {\n <div class=\"ds-slider__ticks\">\n @for (tick of ticks(); track tick) {\n <div\n class=\"ds-slider__tick\"\n [ngStyle]=\"isVertical() ? { bottom: getTickPosition(tick) + '%' } : { left: getTickPosition(tick) + '%' }\">\n </div>\n }\n </div>\n }\n\n <!-- Thumb 1 (always present) -->\n <div\n #thumb1\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 0 || dragging() === 0\"\n [ngStyle]=\"thumb1Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"isRange() ? value2() : max()\"\n [attr.aria-valuenow]=\"value1()\"\n [attr.aria-valuetext]=\"getAriaValueText(0)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 0)\"\n (mousedown)=\"onThumbMouseDown($event, 0)\"\n (focus)=\"onThumbFocus(0)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label1() }}</span>\n }\n </div>\n\n <!-- Thumb 2 (only for range mode) -->\n @if (isRange()) {\n <div\n #thumb2\n class=\"ds-slider__thumb\"\n [class.ds-slider__thumb--active]=\"focusedThumb() === 1 || dragging() === 1\"\n [ngStyle]=\"thumb2Style()\"\n [attr.role]=\"'slider'\"\n [attr.aria-valuemin]=\"value1()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"value2()\"\n [attr.aria-valuetext]=\"getAriaValueText(1)\"\n [attr.aria-orientation]=\"orientation()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (keydown)=\"onKeyDown($event, 1)\"\n (mousedown)=\"onThumbMouseDown($event, 1)\"\n (focus)=\"onThumbFocus(1)\"\n (blur)=\"onThumbBlur()\">\n @if (showLabels()) {\n <span class=\"ds-slider__thumb-label\">{{ label2() }}</span>\n }\n </div>\n }\n </div>\n </div>\n\n <!-- Max label -->\n @if (showLabels()) {\n <span class=\"ds-slider__label ds-slider__label--max\">\n {{ getTickLabel(max()) }}\n </span>\n }\n</div>\n", styles: [".ds-slider{display:flex;align-items:center;gap:var(--slider-label-gap, var(--space-3, .75rem));-webkit-user-select:none;user-select:none}.ds-slider__label{flex-shrink:0;font-size:var(--slider-label-font-size, var(--font-size-2, .875rem));color:var(--slider-label-color, var(--gray-700, #374151));font-weight:500}.ds-slider__label--min{order:1}.ds-slider__label--max{order:3}.ds-slider__track-container{flex:1;order:2;position:relative;display:flex;align-items:center}.ds-slider__track{position:relative;width:100%;height:var(--slider-track-height-md, 6px);background-color:var(--slider-track-bg, var(--gray-200, #e5e7eb));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));cursor:pointer}.ds-slider__fill{position:absolute;background-color:var(--slider-fill-bg, var(--color-primary, #3b82f6));border-radius:var(--slider-track-radius, var(--radius-full, 9999px));height:100%;transition:all .15s ease;pointer-events:none}.ds-slider__ticks{position:absolute;width:100%;height:100%;pointer-events:none}.ds-slider__tick{position:absolute;width:var(--slider-tick-size, 2px);height:var(--slider-tick-size, 2px);background-color:var(--slider-tick-color, var(--gray-400, #9ca3af));border-radius:50%;transform:translate(-50%,-50%);top:50%}.ds-slider__thumb{position:absolute;width:var(--slider-thumb-size-md, 20px);height:var(--slider-thumb-size-md, 20px);background-color:var(--slider-thumb-bg, var(--white, #ffffff));border:var(--slider-thumb-border-width, 2px) solid var(--slider-thumb-border-color, var(--color-primary, #3b82f6));border-radius:50%;box-shadow:var(--slider-thumb-shadow, 0 1px 3px rgba(var(--black-rgb), .1));cursor:grab;transform:translate(-50%,-50%);top:50%;transition:transform .15s ease,box-shadow .15s ease;outline:none}.ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,-50%) scale(1.1);box-shadow:var(--slider-thumb-shadow-hover, 0 2px 8px rgba(var(--black-rgb), .15))}.ds-slider__thumb:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;box-shadow:var(--slider-thumb-shadow-focus, 0 0 0 3px rgba(var(--color-primary-rgb), .3))}.ds-slider__thumb--active{cursor:grabbing;transform:translate(-50%,-50%) scale(1.15);box-shadow:var(--slider-thumb-shadow-active, 0 0 0 4px rgba(var(--color-primary-rgb), .2))}.ds-slider__thumb[aria-disabled=true]{cursor:not-allowed;opacity:.5}.ds-slider__thumb-label{position:absolute;top:-32px;left:50%;transform:translate(-50%);background-color:var(--slider-thumb-label-bg, var(--gray-900, #111827));color:var(--slider-thumb-label-color, var(--white, #ffffff));font-size:var(--font-size-1, .75rem);padding:var(--space-1, .25rem) var(--space-2, .5rem);border-radius:var(--radius-1, .25rem);white-space:nowrap;pointer-events:none;opacity:0;transition:opacity .15s ease}.ds-slider__thumb:hover .ds-slider__thumb-label,.ds-slider__thumb:focus .ds-slider__thumb-label,.ds-slider__thumb--active .ds-slider__thumb-label{opacity:1}.ds-slider--sm .ds-slider__track{height:var(--slider-track-height-sm, 4px)}.ds-slider--sm .ds-slider__thumb{width:var(--slider-thumb-size-sm, 16px);height:var(--slider-thumb-size-sm, 16px)}.ds-slider--sm .ds-slider__label{font-size:var(--font-size-1, .75rem)}.ds-slider--lg .ds-slider__track{height:var(--slider-track-height-lg, 8px)}.ds-slider--lg .ds-slider__thumb{width:var(--slider-thumb-size-lg, 24px);height:var(--slider-thumb-size-lg, 24px)}.ds-slider--lg .ds-slider__label{font-size:var(--font-size-3, 1rem)}.ds-slider--disabled{opacity:.6;pointer-events:none}.ds-slider--disabled .ds-slider__track{cursor:not-allowed}.ds-slider--vertical{flex-direction:column;height:200px;width:auto}.ds-slider--vertical .ds-slider__label--min{order:3}.ds-slider--vertical .ds-slider__label--max{order:1}.ds-slider--vertical .ds-slider__track-container{flex:1;width:auto;height:100%;display:flex;justify-content:center}.ds-slider--vertical .ds-slider__track{width:var(--slider-track-height-md, 6px);height:100%}.ds-slider--vertical .ds-slider__fill{width:100%;height:auto}.ds-slider--vertical .ds-slider__thumb{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical .ds-slider__thumb:hover:not([aria-disabled=true]){transform:translate(-50%,50%) scale(1.1)}.ds-slider--vertical .ds-slider__thumb--active{transform:translate(-50%,50%) scale(1.15)}.ds-slider--vertical .ds-slider__thumb-label{top:50%;left:32px;transform:translateY(-50%)}.ds-slider--vertical .ds-slider__tick{left:50%;top:auto;transform:translate(-50%,50%)}.ds-slider--vertical.ds-slider--sm .ds-slider__track{width:var(--slider-track-height-sm, 4px)}.ds-slider--vertical.ds-slider--lg .ds-slider__track{width:var(--slider-track-height-lg, 8px)}\n"] }]
8133
8133
  }], ctorParameters: () => [], propDecorators: { min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], range: [{ type: i0.Input, args: [{ isSignal: true, alias: "range", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], showLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabels", required: false }] }], showTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTicks", required: false }] }], tickInterval: [{ type: i0.Input, args: [{ isSignal: true, alias: "tickInterval", required: false }] }], formatLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatLabel", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], trackElement: [{
8134
8134
  type: ViewChild,
8135
8135
  args: ['track', { static: false }]
@@ -8556,6 +8556,1613 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
8556
8556
  ], template: "<div\n [ngClass]=\"containerClasses()\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <!-- Zone de drop -->\n <div\n class=\"ds-file-upload__dropzone\"\n [class.ds-file-upload__dropzone--active]=\"isDragging()\"\n (click)=\"openFileSelector()\"\n [attr.tabindex]=\"disabled() ? null : 0\"\n [attr.aria-label]=\"label()\"\n role=\"button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"ds-file-upload__input\"\n [accept]=\"accept()\"\n [multiple]=\"multiple()\"\n [disabled]=\"disabled() || isMaxFilesReached()\"\n (change)=\"onFileSelect($event)\"\n aria-hidden=\"true\"\n tabindex=\"-1\"\n />\n\n <!-- Ic\u00F4ne et texte -->\n <div class=\"ds-file-upload__icon\">\n <fa-icon [icon]=\"faCloudArrowUp\" size=\"2x\"></fa-icon>\n </div>\n <div class=\"ds-file-upload__text\">\n <span class=\"ds-file-upload__label\">{{ label() }}</span>\n @if (!disabled() && !isMaxFilesReached()) {\n <span class=\"ds-file-upload__help\">{{ dragHelpText() }}</span>\n }\n @if (isMaxFilesReached()) {\n <span class=\"ds-file-upload__limit\">Limite atteinte ({{ maxFiles() }} fichier{{ maxFiles() > 1 ? 's' : '' }})</span>\n }\n </div>\n\n <!-- Message d'erreur global -->\n @if (errorMessage()) {\n <div class=\"ds-file-upload__error\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n }\n\n <!-- Indications -->\n @if (!errorMessage() && accept() !== '*') {\n <div class=\"ds-file-upload__hint\">\n Types accept\u00E9s : {{ accept() }}\n </div>\n }\n @if (!errorMessage() && maxFileSize()) {\n <div class=\"ds-file-upload__hint\">\n Taille max : {{ formatFileSize(maxFileSize()) }}\n </div>\n }\n </div>\n\n <!-- Liste des fichiers -->\n @if (fileCount() > 0) {\n <div class=\"ds-file-upload__files\">\n @for (uploadFile of files(); track uploadFile.file.name) {\n <div class=\"ds-file-upload__file\">\n <!-- Preview image -->\n @if (showPreview() && uploadFile.preview) {\n <div class=\"ds-file-upload__preview\">\n <img [src]=\"uploadFile.preview\" [alt]=\"uploadFile.file.name\" />\n </div>\n } @else {\n <div class=\"ds-file-upload__file-icon\">\n <fa-icon [icon]=\"getFileIcon(uploadFile.file)\"></fa-icon>\n </div>\n }\n\n <!-- Infos fichier -->\n <div class=\"ds-file-upload__file-info\">\n <div class=\"ds-file-upload__file-name\" [title]=\"uploadFile.file.name\">\n {{ uploadFile.file.name }}\n </div>\n <div class=\"ds-file-upload__file-size\">\n {{ formatFileSize(uploadFile.file.size) }}\n </div>\n\n <!-- Barre de progression -->\n @if (uploadFile.progress < 100) {\n <ds-progress-bar\n [value]=\"uploadFile.progress\"\n size=\"sm\"\n variant=\"default\"\n [showLabel]=\"true\"\n ></ds-progress-bar>\n }\n\n <!-- Message d'erreur fichier -->\n @if (uploadFile.error) {\n <div class=\"ds-file-upload__file-error\" role=\"alert\">\n {{ uploadFile.error }}\n </div>\n }\n </div>\n\n <!-- Bouton supprimer -->\n <button\n type=\"button\"\n class=\"ds-file-upload__remove\"\n (click)=\"removeFile(uploadFile)\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"'Supprimer ' + uploadFile.file.name\"\n >\n <fa-icon [icon]=\"faXmark\"></fa-icon>\n </button>\n </div>\n }\n </div>\n }\n</div>\n", styles: [".ds-file-upload{display:block;font-family:var(--font-family-base)}.ds-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--space-8);border:2px dashed var(--file-upload-border, var(--gray-300));border-radius:var(--file-upload-radius, var(--radius-2));background:var(--file-upload-bg, var(--white));cursor:pointer;transition:all .2s ease;position:relative;min-height:200px}.ds-file-upload__dropzone:hover:not(.ds-file-upload--disabled .ds-file-upload__dropzone){border-color:var(--file-upload-border-hover, var(--color-primary));background:var(--file-upload-bg-hover, var(--gray-50))}.ds-file-upload__dropzone:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.ds-file-upload__dropzone--active{border-color:var(--file-upload-border-active, var(--color-primary));background:var(--file-upload-bg-active, var(--blue-50))}.ds-file-upload__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ds-file-upload__icon{color:var(--file-upload-icon-color, var(--gray-400));margin-bottom:var(--space-3);transition:color .2s ease}.ds-file-upload__dropzone:hover .ds-file-upload__icon{color:var(--file-upload-icon-color-hover, var(--color-primary))}.ds-file-upload__dropzone--active .ds-file-upload__icon{color:var(--file-upload-icon-color-active, var(--color-primary));transform:scale(1.1)}.ds-file-upload__text{text-align:center;color:var(--file-upload-text-color, var(--gray-700))}.ds-file-upload__label{display:block;font-size:var(--font-size-base, var(--font-size-3));font-weight:500;margin-bottom:var(--space-1);color:var(--file-upload-label-color, var(--gray-900))}.ds-file-upload__help{display:block;font-size:var(--font-size-sm, var(--font-size-2));color:var(--file-upload-help-color, var(--gray-500))}.ds-file-upload__limit{display:block;font-size:var(--font-size-sm, var(--font-size-2));color:var(--warning);font-weight:500}.ds-file-upload__error{margin-top:var(--space-2);padding:var(--space-2) var(--space-3);background:var(--error-bg, var(--red-50));color:var(--error);border-radius:var(--radius-1);font-size:var(--font-size-sm, var(--font-size-2));text-align:center}.ds-file-upload__hint{margin-top:var(--space-1);font-size:var(--font-size-xs, var(--font-size-1));color:var(--file-upload-hint-color, var(--gray-500));text-align:center}.ds-file-upload__files{margin-top:var(--space-4);display:flex;flex-direction:column;gap:var(--space-3)}.ds-file-upload__file{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-3);border:1px solid var(--file-upload-file-border, var(--gray-200));border-radius:var(--radius-2);background:var(--file-upload-file-bg, var(--white));transition:all .2s ease}.ds-file-upload__file:hover{background:var(--file-upload-file-bg-hover, var(--gray-50))}.ds-file-upload__preview{flex-shrink:0;width:60px;height:60px;border-radius:var(--radius-1);overflow:hidden;border:1px solid var(--gray-200)}.ds-file-upload__preview img{width:100%;height:100%;object-fit:cover}.ds-file-upload__file-icon{flex-shrink:0;width:60px;height:60px;display:flex;align-items:center;justify-content:center;background:var(--gray-50);border-radius:var(--radius-1);color:var(--gray-400);font-size:var(--font-size-5)}.ds-file-upload__file-info{flex:1;min-width:0}.ds-file-upload__file-name{font-size:var(--font-size-sm, var(--font-size-2));font-weight:500;color:var(--gray-900);margin-bottom:var(--space-1);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-file-upload__file-size{font-size:var(--font-size-xs, var(--font-size-1));color:var(--gray-500);margin-bottom:var(--space-2)}.ds-file-upload__file-error{margin-top:var(--space-2);padding:var(--space-1) var(--space-2);background:var(--error-bg, var(--red-50));color:var(--error);border-radius:var(--radius-1);font-size:var(--font-size-xs, var(--font-size-1))}.ds-file-upload__remove{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;color:var(--gray-400);border-radius:var(--radius-1);cursor:pointer;transition:all .2s ease}.ds-file-upload__remove:hover:not(:disabled){background:var(--gray-100);color:var(--error)}.ds-file-upload__remove:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.ds-file-upload__remove:disabled{opacity:.5;cursor:not-allowed}.ds-file-upload--sm .ds-file-upload__dropzone{min-height:150px;padding:var(--space-6)}.ds-file-upload--sm .ds-file-upload__label{font-size:var(--font-size-sm, var(--font-size-2))}.ds-file-upload--sm .ds-file-upload__preview,.ds-file-upload--sm .ds-file-upload__file-icon{width:48px;height:48px}.ds-file-upload--lg .ds-file-upload__dropzone{min-height:250px;padding:var(--space-10)}.ds-file-upload--lg .ds-file-upload__label{font-size:var(--font-size-lg, var(--font-size-4))}.ds-file-upload--lg .ds-file-upload__preview,.ds-file-upload--lg .ds-file-upload__file-icon{width:80px;height:80px}.ds-file-upload--disabled{opacity:.6;cursor:not-allowed}.ds-file-upload--disabled .ds-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.ds-file-upload--error .ds-file-upload__dropzone{border-color:var(--error)}\n"] }]
8557
8557
  }], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreview", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], dragHelpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "dragHelpText", required: false }] }], filesChange: [{ type: i0.Output, args: ["filesChange"] }], fileRemoved: [{ type: i0.Output, args: ["fileRemoved"] }], uploadProgress: [{ type: i0.Output, args: ["uploadProgress"] }], fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
8558
8558
 
8559
+ /**
8560
+ * # DsEmpty
8561
+ *
8562
+ * Composant d'état vide standardisé permettant d'afficher un message
8563
+ * lorsqu'aucune donnée n'est disponible, avec une illustration optionnelle.
8564
+ *
8565
+ * ## Usage
8566
+ *
8567
+ * ```html
8568
+ * <ds-empty
8569
+ * title="Aucun résultat"
8570
+ * description="Essayez de modifier vos filtres"
8571
+ * [icon]="faSearch">
8572
+ * <button ds-button (click)="resetFilters()">Réinitialiser</button>
8573
+ * </ds-empty>
8574
+ * ```
8575
+ *
8576
+ * ## Accessibilité
8577
+ *
8578
+ * - Utilise `role="region"` avec `aria-label` descriptif
8579
+ * - Icônes décoratives avec `aria-hidden="true"`
8580
+ * - Support des actions via content projection
8581
+ *
8582
+ * @component
8583
+ */
8584
+ class DsEmpty {
8585
+ /**
8586
+ * Titre principal de l'état vide.
8587
+ * @default 'Aucune donnée'
8588
+ */
8589
+ title = input('Aucune donnée', ...(ngDevMode ? [{ debugName: "title" }] : []));
8590
+ /**
8591
+ * Description complémentaire optionnelle.
8592
+ */
8593
+ description = input('', ...(ngDevMode ? [{ debugName: "description" }] : []));
8594
+ /**
8595
+ * Icône FontAwesome à afficher.
8596
+ * @default faInbox
8597
+ */
8598
+ icon = input(faInbox, ...(ngDevMode ? [{ debugName: "icon" }] : []));
8599
+ /**
8600
+ * URL d'une image personnalisée (illustration ou SVG).
8601
+ * Si fournie, prend le pas sur l'icône FontAwesome.
8602
+ */
8603
+ imageUrl = input('', ...(ngDevMode ? [{ debugName: "imageUrl" }] : []));
8604
+ /**
8605
+ * Taille du composant (affecte l'icône et les espacements).
8606
+ * @default 'md'
8607
+ */
8608
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
8609
+ /**
8610
+ * Classes CSS calculées pour le conteneur.
8611
+ */
8612
+ containerClasses = computed(() => {
8613
+ return [
8614
+ 'ds-empty',
8615
+ `ds-empty--${this.size()}`,
8616
+ ].join(' ');
8617
+ }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
8618
+ /**
8619
+ * Classes CSS calculées pour l'icône.
8620
+ */
8621
+ iconClasses = computed(() => {
8622
+ const baseClass = 'ds-empty__icon';
8623
+ return `${baseClass} ${baseClass}--${this.size()}`;
8624
+ }, ...(ngDevMode ? [{ debugName: "iconClasses" }] : []));
8625
+ /**
8626
+ * Classes CSS calculées pour l'image.
8627
+ */
8628
+ imageClasses = computed(() => {
8629
+ const baseClass = 'ds-empty__image';
8630
+ return `${baseClass} ${baseClass}--${this.size()}`;
8631
+ }, ...(ngDevMode ? [{ debugName: "imageClasses" }] : []));
8632
+ /**
8633
+ * Détermine si une image doit être affichée.
8634
+ */
8635
+ hasImage = computed(() => !!this.imageUrl(), ...(ngDevMode ? [{ debugName: "hasImage" }] : []));
8636
+ /**
8637
+ * Détermine si une description est fournie.
8638
+ */
8639
+ hasDescription = computed(() => !!this.description(), ...(ngDevMode ? [{ debugName: "hasDescription" }] : []));
8640
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsEmpty, deps: [], target: i0.ɵɵFactoryTarget.Component });
8641
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsEmpty, isStandalone: true, selector: "ds-empty", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, imageUrl: { classPropertyName: "imageUrl", publicName: "imageUrl", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n [class]=\"containerClasses()\"\n role=\"region\"\n [attr.aria-label]=\"'\u00C9tat vide : ' + title()\">\n\n <!-- Image personnalis\u00E9e -->\n @if (hasImage()) {\n <div [class]=\"imageClasses()\">\n <img\n [src]=\"imageUrl()\"\n [alt]=\"title()\"\n class=\"ds-empty__image-element\" />\n </div>\n }\n\n <!-- Ic\u00F4ne FontAwesome par d\u00E9faut -->\n @if (!hasImage()) {\n <div [class]=\"iconClasses()\">\n <fa-icon\n [icon]=\"icon()\"\n aria-hidden=\"true\" />\n </div>\n }\n\n <!-- Contenu texte -->\n <div class=\"ds-empty__content\">\n <h3 class=\"ds-empty__title\">{{ title() }}</h3>\n\n @if (hasDescription()) {\n <p class=\"ds-empty__description\">{{ description() }}</p>\n }\n </div>\n\n <!-- Slot pour action button personnalis\u00E9 -->\n <div class=\"ds-empty__actions\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [".ds-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:var(--empty-padding, var(--space-8));color:var(--empty-text, var(--text-muted))}.ds-empty--sm{padding:var(--empty-padding-sm, var(--space-6))}.ds-empty--md{padding:var(--empty-padding-md, var(--space-8))}.ds-empty--lg{padding:var(--empty-padding-lg, var(--space-10))}.ds-empty__icon{display:flex;align-items:center;justify-content:center;margin-bottom:var(--empty-icon-margin, var(--space-4));color:var(--empty-icon-color, var(--text-disabled))}.ds-empty__icon--sm{font-size:var(--empty-icon-size-sm, 2.5rem)}.ds-empty__icon--md{font-size:var(--empty-icon-size-md, 3.5rem)}.ds-empty__icon--lg{font-size:var(--empty-icon-size-lg, 5rem)}.ds-empty__image{display:flex;align-items:center;justify-content:center;margin-bottom:var(--empty-image-margin, var(--space-4))}.ds-empty__image--sm{width:var(--empty-image-size-sm, 120px);height:var(--empty-image-size-sm, 120px)}.ds-empty__image--md{width:var(--empty-image-size-md, 180px);height:var(--empty-image-size-md, 180px)}.ds-empty__image--lg{width:var(--empty-image-size-lg, 240px);height:var(--empty-image-size-lg, 240px)}.ds-empty__image-element{width:100%;height:100%;object-fit:contain}.ds-empty__content{margin-bottom:var(--empty-content-margin, var(--space-4))}.ds-empty__title{margin:0 0 var(--space-2);font-size:var(--empty-title-font-size, var(--font-size-lg));font-weight:var(--empty-title-font-weight, 600);color:var(--empty-title-color, var(--text-default))}.ds-empty__description{margin:0;font-size:var(--empty-description-font-size, var(--font-size-sm));color:var(--empty-description-color, var(--text-muted));max-width:var(--empty-description-max-width, 400px)}.ds-empty__actions{display:flex;gap:var(--empty-actions-gap, var(--space-3));align-items:center;justify-content:center}.ds-empty__actions:empty{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i1$1.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }] });
8642
+ }
8643
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsEmpty, decorators: [{
8644
+ type: Component,
8645
+ args: [{ selector: 'ds-empty', imports: [CommonModule, FontAwesomeModule], template: "<div\n [class]=\"containerClasses()\"\n role=\"region\"\n [attr.aria-label]=\"'\u00C9tat vide : ' + title()\">\n\n <!-- Image personnalis\u00E9e -->\n @if (hasImage()) {\n <div [class]=\"imageClasses()\">\n <img\n [src]=\"imageUrl()\"\n [alt]=\"title()\"\n class=\"ds-empty__image-element\" />\n </div>\n }\n\n <!-- Ic\u00F4ne FontAwesome par d\u00E9faut -->\n @if (!hasImage()) {\n <div [class]=\"iconClasses()\">\n <fa-icon\n [icon]=\"icon()\"\n aria-hidden=\"true\" />\n </div>\n }\n\n <!-- Contenu texte -->\n <div class=\"ds-empty__content\">\n <h3 class=\"ds-empty__title\">{{ title() }}</h3>\n\n @if (hasDescription()) {\n <p class=\"ds-empty__description\">{{ description() }}</p>\n }\n </div>\n\n <!-- Slot pour action button personnalis\u00E9 -->\n <div class=\"ds-empty__actions\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [".ds-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:var(--empty-padding, var(--space-8));color:var(--empty-text, var(--text-muted))}.ds-empty--sm{padding:var(--empty-padding-sm, var(--space-6))}.ds-empty--md{padding:var(--empty-padding-md, var(--space-8))}.ds-empty--lg{padding:var(--empty-padding-lg, var(--space-10))}.ds-empty__icon{display:flex;align-items:center;justify-content:center;margin-bottom:var(--empty-icon-margin, var(--space-4));color:var(--empty-icon-color, var(--text-disabled))}.ds-empty__icon--sm{font-size:var(--empty-icon-size-sm, 2.5rem)}.ds-empty__icon--md{font-size:var(--empty-icon-size-md, 3.5rem)}.ds-empty__icon--lg{font-size:var(--empty-icon-size-lg, 5rem)}.ds-empty__image{display:flex;align-items:center;justify-content:center;margin-bottom:var(--empty-image-margin, var(--space-4))}.ds-empty__image--sm{width:var(--empty-image-size-sm, 120px);height:var(--empty-image-size-sm, 120px)}.ds-empty__image--md{width:var(--empty-image-size-md, 180px);height:var(--empty-image-size-md, 180px)}.ds-empty__image--lg{width:var(--empty-image-size-lg, 240px);height:var(--empty-image-size-lg, 240px)}.ds-empty__image-element{width:100%;height:100%;object-fit:contain}.ds-empty__content{margin-bottom:var(--empty-content-margin, var(--space-4))}.ds-empty__title{margin:0 0 var(--space-2);font-size:var(--empty-title-font-size, var(--font-size-lg));font-weight:var(--empty-title-font-weight, 600);color:var(--empty-title-color, var(--text-default))}.ds-empty__description{margin:0;font-size:var(--empty-description-font-size, var(--font-size-sm));color:var(--empty-description-color, var(--text-muted));max-width:var(--empty-description-max-width, 400px)}.ds-empty__actions{display:flex;gap:var(--empty-actions-gap, var(--space-3));align-items:center;justify-content:center}.ds-empty__actions:empty{display:none}\n"] }]
8646
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], imageUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageUrl", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
8647
+
8648
+ /**
8649
+ * # DsRating
8650
+ *
8651
+ * Composant de notation par étoiles permettant d'afficher et de saisir
8652
+ * une note sur une échelle configurable (par défaut 0-5).
8653
+ *
8654
+ * ## Usage
8655
+ *
8656
+ * ```html
8657
+ * <ds-rating
8658
+ * [(value)]="rating"
8659
+ * [max]="5"
8660
+ * [allowHalf]="true"
8661
+ * (ratingChange)="handleRatingChange($event)" />
8662
+ * ```
8663
+ *
8664
+ * ## Intégration formulaires
8665
+ *
8666
+ * ```html
8667
+ * <form [formGroup]="form">
8668
+ * <ds-rating formControlName="rating" />
8669
+ * </form>
8670
+ * ```
8671
+ *
8672
+ * ## Accessibilité
8673
+ *
8674
+ * - Navigation clavier : ArrowLeft/Right pour changer la note
8675
+ * - Attributs ARIA : role, aria-label, aria-valuenow/valuemin/valuemax
8676
+ * - Focus visible sur les étoiles
8677
+ *
8678
+ * @component
8679
+ */
8680
+ class DsRating {
8681
+ /**
8682
+ * Valeur actuelle de la notation (0 à max).
8683
+ * @default 0
8684
+ */
8685
+ value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
8686
+ /**
8687
+ * Valeur maximale de la notation.
8688
+ * @default 5
8689
+ */
8690
+ max = input(5, ...(ngDevMode ? [{ debugName: "max" }] : []));
8691
+ /**
8692
+ * Taille du composant (affecte la taille des étoiles).
8693
+ * @default 'md'
8694
+ */
8695
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
8696
+ /**
8697
+ * Permet la saisie de demi-étoiles (notes 0.5, 1.5, etc.).
8698
+ * @default false
8699
+ */
8700
+ allowHalf = input(false, ...(ngDevMode ? [{ debugName: "allowHalf" }] : []));
8701
+ /**
8702
+ * Mode lecture seule (affichage uniquement).
8703
+ * @default false
8704
+ */
8705
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
8706
+ /**
8707
+ * État désactivé (pas d'interaction).
8708
+ * @default false
8709
+ */
8710
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
8711
+ /**
8712
+ * Émis lorsque la notation change.
8713
+ */
8714
+ ratingChange = output();
8715
+ /**
8716
+ * État interne de la valeur (ControlValueAccessor).
8717
+ */
8718
+ internalValue = signal(0, ...(ngDevMode ? [{ debugName: "internalValue" }] : []));
8719
+ /**
8720
+ * État de survol (pour aperçu avant clic).
8721
+ */
8722
+ hoverValue = signal(null, ...(ngDevMode ? [{ debugName: "hoverValue" }] : []));
8723
+ /**
8724
+ * Callbacks ControlValueAccessor.
8725
+ */
8726
+ onChange = () => { };
8727
+ onTouched = () => { };
8728
+ /**
8729
+ * Icônes FontAwesome pour les étoiles.
8730
+ */
8731
+ faStar = faStar;
8732
+ faStarHalf = faStarHalfStroke;
8733
+ /**
8734
+ * Tableau des indices d'étoiles pour le rendu.
8735
+ */
8736
+ stars = computed(() => {
8737
+ return Array.from({ length: this.max() }, (_, i) => i + 1);
8738
+ }, ...(ngDevMode ? [{ debugName: "stars" }] : []));
8739
+ /**
8740
+ * Valeur affichée (avec prise en compte du survol).
8741
+ */
8742
+ displayValue = computed(() => {
8743
+ return this.hoverValue() ?? this.internalValue();
8744
+ }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
8745
+ /**
8746
+ * Classes CSS calculées pour le conteneur.
8747
+ */
8748
+ containerClasses = computed(() => {
8749
+ return [
8750
+ 'ds-rating',
8751
+ `ds-rating--${this.size()}`,
8752
+ this.disabled() ? 'ds-rating--disabled' : '',
8753
+ this.readonly() ? 'ds-rating--readonly' : '',
8754
+ ].filter(Boolean).join(' ');
8755
+ }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
8756
+ /**
8757
+ * Détermine le type d'icône à afficher pour une étoile donnée.
8758
+ * - 'full' : étoile pleine
8759
+ * - 'half' : demi-étoile
8760
+ * - 'empty' : étoile vide
8761
+ */
8762
+ getStarType(index) {
8763
+ const value = this.displayValue();
8764
+ const diff = value - index;
8765
+ if (diff >= 0)
8766
+ return 'full';
8767
+ if (this.allowHalf() && diff >= -0.5)
8768
+ return 'half';
8769
+ return 'empty';
8770
+ }
8771
+ /**
8772
+ * Gère le clic sur une étoile.
8773
+ */
8774
+ handleStarClick(index, event) {
8775
+ if (this.disabled() || this.readonly())
8776
+ return;
8777
+ let newValue = index;
8778
+ // Détection du clic sur la moitié gauche ou droite
8779
+ if (this.allowHalf()) {
8780
+ const target = event.target;
8781
+ const rect = target.getBoundingClientRect();
8782
+ const clickX = event.clientX - rect.left;
8783
+ const halfWidth = rect.width / 2;
8784
+ if (clickX < halfWidth) {
8785
+ newValue = index - 0.5;
8786
+ }
8787
+ }
8788
+ this.updateValue(newValue);
8789
+ }
8790
+ /**
8791
+ * Gère le survol d'une étoile.
8792
+ */
8793
+ handleStarHover(index, event) {
8794
+ if (this.disabled() || this.readonly())
8795
+ return;
8796
+ let hoverVal = index;
8797
+ if (this.allowHalf()) {
8798
+ const target = event.target;
8799
+ const rect = target.getBoundingClientRect();
8800
+ const hoverX = event.clientX - rect.left;
8801
+ const halfWidth = rect.width / 2;
8802
+ if (hoverX < halfWidth) {
8803
+ hoverVal = index - 0.5;
8804
+ }
8805
+ }
8806
+ this.hoverValue.set(hoverVal);
8807
+ }
8808
+ /**
8809
+ * Réinitialise le survol.
8810
+ */
8811
+ handleMouseLeave() {
8812
+ this.hoverValue.set(null);
8813
+ }
8814
+ /**
8815
+ * Navigation clavier (ArrowLeft/Right).
8816
+ */
8817
+ handleKeyDown(event) {
8818
+ if (this.disabled() || this.readonly())
8819
+ return;
8820
+ const step = this.allowHalf() ? 0.5 : 1;
8821
+ let newValue = this.internalValue();
8822
+ if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {
8823
+ event.preventDefault();
8824
+ newValue = Math.min(this.max(), newValue + step);
8825
+ this.updateValue(newValue);
8826
+ }
8827
+ else if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {
8828
+ event.preventDefault();
8829
+ newValue = Math.max(0, newValue - step);
8830
+ this.updateValue(newValue);
8831
+ }
8832
+ else if (event.key === 'Home') {
8833
+ event.preventDefault();
8834
+ this.updateValue(0);
8835
+ }
8836
+ else if (event.key === 'End') {
8837
+ event.preventDefault();
8838
+ this.updateValue(this.max());
8839
+ }
8840
+ }
8841
+ /**
8842
+ * Met à jour la valeur interne et notifie les changements.
8843
+ */
8844
+ updateValue(newValue) {
8845
+ this.internalValue.set(newValue);
8846
+ this.onChange(newValue);
8847
+ this.onTouched();
8848
+ this.ratingChange.emit(newValue);
8849
+ }
8850
+ // ============================================================================
8851
+ // ControlValueAccessor
8852
+ // ============================================================================
8853
+ writeValue(value) {
8854
+ this.internalValue.set(value ?? 0);
8855
+ }
8856
+ registerOnChange(fn) {
8857
+ this.onChange = fn;
8858
+ }
8859
+ registerOnTouched(fn) {
8860
+ this.onTouched = fn;
8861
+ }
8862
+ setDisabledState(isDisabled) {
8863
+ // Le signal disabled est déjà géré via input()
8864
+ }
8865
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsRating, deps: [], target: i0.ɵɵFactoryTarget.Component });
8866
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsRating, isStandalone: true, selector: "ds-rating", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, allowHalf: { classPropertyName: "allowHalf", publicName: "allowHalf", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ratingChange: "ratingChange" }, providers: [
8867
+ {
8868
+ provide: NG_VALUE_ACCESSOR,
8869
+ useExisting: forwardRef(() => DsRating),
8870
+ multi: true,
8871
+ },
8872
+ ], ngImport: i0, template: "<div\n [class]=\"containerClasses()\"\n role=\"slider\"\n [attr.aria-label]=\"'Note : ' + displayValue() + ' sur ' + max()\"\n [attr.aria-valuenow]=\"displayValue()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() || readonly() ? -1 : 0\"\n (keydown)=\"handleKeyDown($event)\"\n (mouseleave)=\"handleMouseLeave()\">\n\n @for (starIndex of stars(); track starIndex) {\n <span\n class=\"ds-rating__star\"\n [attr.data-index]=\"starIndex\"\n (click)=\"handleStarClick(starIndex, $event)\"\n (mousemove)=\"handleStarHover(starIndex, $event)\">\n\n @switch (getStarType(starIndex)) {\n @case ('full') {\n <fa-icon [icon]=\"faStar\" class=\"ds-rating__icon ds-rating__icon--filled\" aria-hidden=\"true\" />\n }\n @case ('half') {\n <fa-icon [icon]=\"faStarHalf\" class=\"ds-rating__icon ds-rating__icon--half\" aria-hidden=\"true\" />\n }\n @case ('empty') {\n <fa-icon [icon]=\"faStar\" class=\"ds-rating__icon ds-rating__icon--empty\" aria-hidden=\"true\" />\n }\n }\n </span>\n }\n</div>\n", styles: [".ds-rating{display:inline-flex;align-items:center;gap:var(--rating-gap, var(--space-1));outline:none}.ds-rating--sm{gap:var(--rating-gap-sm, 2px)}.ds-rating--md{gap:var(--rating-gap-md, var(--space-1))}.ds-rating--lg{gap:var(--rating-gap-lg, var(--space-2))}.ds-rating--readonly{cursor:default}.ds-rating--disabled{opacity:var(--rating-disabled-opacity, .5);cursor:not-allowed;pointer-events:none}.ds-rating:focus-visible{outline:2px solid var(--rating-focus-color, var(--color-primary));outline-offset:2px;border-radius:var(--rating-focus-radius, var(--radius-1))}.ds-rating__star{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .15s ease}.ds-rating__star:hover{transform:scale(var(--rating-hover-scale, 1.1))}.ds-rating__star:active{transform:scale(var(--rating-active-scale, .95))}.ds-rating--readonly .ds-rating__star,.ds-rating--disabled .ds-rating__star{cursor:default}.ds-rating--readonly .ds-rating__star:hover,.ds-rating--disabled .ds-rating__star:hover{transform:none}.ds-rating__icon{transition:color .15s ease}.ds-rating--sm .ds-rating__icon{font-size:var(--rating-icon-size-sm, 16px)}.ds-rating--md .ds-rating__icon{font-size:var(--rating-icon-size-md, 20px)}.ds-rating--lg .ds-rating__icon{font-size:var(--rating-icon-size-lg, 28px)}.ds-rating__icon--filled,.ds-rating__icon--half{color:var(--rating-filled-color, var(--warning))}.ds-rating__icon--empty{color:var(--rating-empty-color, var(--border-color))}.ds-rating__star:hover .ds-rating__icon--empty{color:var(--rating-hover-color, color-mix(in oklab, var(--warning) 50%, transparent))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i1$1.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }] });
8873
+ }
8874
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsRating, decorators: [{
8875
+ type: Component,
8876
+ args: [{ selector: 'ds-rating', imports: [CommonModule, FontAwesomeModule], providers: [
8877
+ {
8878
+ provide: NG_VALUE_ACCESSOR,
8879
+ useExisting: forwardRef(() => DsRating),
8880
+ multi: true,
8881
+ },
8882
+ ], template: "<div\n [class]=\"containerClasses()\"\n role=\"slider\"\n [attr.aria-label]=\"'Note : ' + displayValue() + ' sur ' + max()\"\n [attr.aria-valuenow]=\"displayValue()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-readonly]=\"readonly()\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() || readonly() ? -1 : 0\"\n (keydown)=\"handleKeyDown($event)\"\n (mouseleave)=\"handleMouseLeave()\">\n\n @for (starIndex of stars(); track starIndex) {\n <span\n class=\"ds-rating__star\"\n [attr.data-index]=\"starIndex\"\n (click)=\"handleStarClick(starIndex, $event)\"\n (mousemove)=\"handleStarHover(starIndex, $event)\">\n\n @switch (getStarType(starIndex)) {\n @case ('full') {\n <fa-icon [icon]=\"faStar\" class=\"ds-rating__icon ds-rating__icon--filled\" aria-hidden=\"true\" />\n }\n @case ('half') {\n <fa-icon [icon]=\"faStarHalf\" class=\"ds-rating__icon ds-rating__icon--half\" aria-hidden=\"true\" />\n }\n @case ('empty') {\n <fa-icon [icon]=\"faStar\" class=\"ds-rating__icon ds-rating__icon--empty\" aria-hidden=\"true\" />\n }\n }\n </span>\n }\n</div>\n", styles: [".ds-rating{display:inline-flex;align-items:center;gap:var(--rating-gap, var(--space-1));outline:none}.ds-rating--sm{gap:var(--rating-gap-sm, 2px)}.ds-rating--md{gap:var(--rating-gap-md, var(--space-1))}.ds-rating--lg{gap:var(--rating-gap-lg, var(--space-2))}.ds-rating--readonly{cursor:default}.ds-rating--disabled{opacity:var(--rating-disabled-opacity, .5);cursor:not-allowed;pointer-events:none}.ds-rating:focus-visible{outline:2px solid var(--rating-focus-color, var(--color-primary));outline-offset:2px;border-radius:var(--rating-focus-radius, var(--radius-1))}.ds-rating__star{display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:transform .15s ease}.ds-rating__star:hover{transform:scale(var(--rating-hover-scale, 1.1))}.ds-rating__star:active{transform:scale(var(--rating-active-scale, .95))}.ds-rating--readonly .ds-rating__star,.ds-rating--disabled .ds-rating__star{cursor:default}.ds-rating--readonly .ds-rating__star:hover,.ds-rating--disabled .ds-rating__star:hover{transform:none}.ds-rating__icon{transition:color .15s ease}.ds-rating--sm .ds-rating__icon{font-size:var(--rating-icon-size-sm, 16px)}.ds-rating--md .ds-rating__icon{font-size:var(--rating-icon-size-md, 20px)}.ds-rating--lg .ds-rating__icon{font-size:var(--rating-icon-size-lg, 28px)}.ds-rating__icon--filled,.ds-rating__icon--half{color:var(--rating-filled-color, var(--warning))}.ds-rating__icon--empty{color:var(--rating-empty-color, var(--border-color))}.ds-rating__star:hover .ds-rating__icon--empty{color:var(--rating-hover-color, color-mix(in oklab, var(--warning) 50%, transparent))}\n"] }]
8883
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], allowHalf: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowHalf", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ratingChange: [{ type: i0.Output, args: ["ratingChange"] }] } });
8884
+
8885
+ /**
8886
+ * # DsDrawer
8887
+ *
8888
+ * Composant de panneau latéral overlay avec animation slide-in/out.
8889
+ * Utilise CDK Overlay pour le backdrop et le focus trap.
8890
+ *
8891
+ * ## Usage
8892
+ *
8893
+ * ```html
8894
+ * <ds-drawer
8895
+ * [(visible)]="isDrawerOpen"
8896
+ * position="right"
8897
+ * size="md"
8898
+ * title="Détails"
8899
+ * [closable]="true"
8900
+ * (closed)="onDrawerClose()">
8901
+ * <!-- Header -->
8902
+ * <ng-template #header>
8903
+ * <h3>Mon en-tête personnalisé</h3>
8904
+ * </ng-template>
8905
+ *
8906
+ * <!-- Body -->
8907
+ * <p>Contenu du drawer</p>
8908
+ *
8909
+ * <!-- Footer -->
8910
+ * <ng-template #footer>
8911
+ * <button>Annuler</button>
8912
+ * <button>Valider</button>
8913
+ * </ng-template>
8914
+ * </ds-drawer>
8915
+ * ```
8916
+ *
8917
+ * ## Accessibilité
8918
+ *
8919
+ * - Focus trap : le focus reste dans le drawer
8920
+ * - Navigation clavier : Escape pour fermer
8921
+ * - Attributs ARIA : role, aria-labelledby, aria-modal
8922
+ *
8923
+ * @component
8924
+ */
8925
+ class DsDrawer {
8926
+ /**
8927
+ * Visibilité du drawer.
8928
+ * @default false
8929
+ */
8930
+ visible = input(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
8931
+ /**
8932
+ * Position du drawer (left/right).
8933
+ * @default 'right'
8934
+ */
8935
+ position = input('right', ...(ngDevMode ? [{ debugName: "position" }] : []));
8936
+ /**
8937
+ * Taille du drawer.
8938
+ * @default 'md'
8939
+ */
8940
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
8941
+ /**
8942
+ * Titre affiché dans le header (optionnel).
8943
+ */
8944
+ title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
8945
+ /**
8946
+ * Affiche le bouton de fermeture.
8947
+ * @default true
8948
+ */
8949
+ closable = input(true, ...(ngDevMode ? [{ debugName: "closable" }] : []));
8950
+ /**
8951
+ * Ferme le drawer au clic sur le backdrop.
8952
+ * @default true
8953
+ */
8954
+ maskClosable = input(true, ...(ngDevMode ? [{ debugName: "maskClosable" }] : []));
8955
+ /**
8956
+ * Émis lorsque la visibilité change.
8957
+ */
8958
+ visibleChange = output();
8959
+ /**
8960
+ * Émis lorsque le drawer est fermé.
8961
+ */
8962
+ closed = output();
8963
+ /**
8964
+ * Référence au conteneur du drawer.
8965
+ */
8966
+ drawerContainer;
8967
+ /**
8968
+ * État interne de visibilité pour gérer l'animation.
8969
+ */
8970
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
8971
+ isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
8972
+ /**
8973
+ * Indique si la vue est prête.
8974
+ */
8975
+ viewReady = signal(false, ...(ngDevMode ? [{ debugName: "viewReady" }] : []));
8976
+ /**
8977
+ * Focus trap pour confiner la navigation clavier.
8978
+ */
8979
+ focusTrap = null;
8980
+ /**
8981
+ * Services injectés.
8982
+ */
8983
+ documentRef = inject(DOCUMENT);
8984
+ focusTrapFactory = inject(FocusTrapFactory);
8985
+ /**
8986
+ * Icône de fermeture.
8987
+ */
8988
+ closeIcon = faTimes;
8989
+ /**
8990
+ * ID unique pour l'accessibilité.
8991
+ */
8992
+ drawerId = crypto.randomUUID();
8993
+ drawerTitleId = `drawer-${this.drawerId}-title`;
8994
+ /**
8995
+ * Classes CSS calculées pour le conteneur.
8996
+ */
8997
+ containerClasses = computed(() => {
8998
+ return [
8999
+ 'ds-drawer',
9000
+ `ds-drawer--${this.position()}`,
9001
+ `ds-drawer--${this.size()}`,
9002
+ this.isOpen() ? 'ds-drawer--open' : '',
9003
+ ].filter(Boolean).join(' ');
9004
+ }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
9005
+ /**
9006
+ * Classes CSS calculées pour le backdrop.
9007
+ */
9008
+ backdropClasses = computed(() => {
9009
+ return [
9010
+ 'ds-drawer__backdrop',
9011
+ this.isOpen() ? 'ds-drawer__backdrop--visible' : '',
9012
+ ].filter(Boolean).join(' ');
9013
+ }, ...(ngDevMode ? [{ debugName: "backdropClasses" }] : []));
9014
+ constructor() {
9015
+ // Effet pour synchroniser l'état visible avec l'animation
9016
+ effect(() => {
9017
+ if (!this.viewReady())
9018
+ return;
9019
+ if (this.visible()) {
9020
+ this.openDrawer();
9021
+ }
9022
+ else {
9023
+ this.closeDrawer();
9024
+ }
9025
+ });
9026
+ }
9027
+ ngAfterViewInit() {
9028
+ this.viewReady.set(true);
9029
+ }
9030
+ ngOnDestroy() {
9031
+ this.detachFocusTrap();
9032
+ }
9033
+ /**
9034
+ * Ouvre le drawer avec animation.
9035
+ */
9036
+ openDrawer() {
9037
+ this.isAnimating.set(true);
9038
+ this.isOpen.set(true);
9039
+ // Empêche le scroll du body
9040
+ this.documentRef.body.style.overflow = 'hidden';
9041
+ // Attache le focus trap après l'animation
9042
+ setTimeout(() => {
9043
+ this.attachFocusTrap();
9044
+ this.focusInitialElement();
9045
+ this.isAnimating.set(false);
9046
+ }, 300);
9047
+ }
9048
+ /**
9049
+ * Ferme le drawer avec animation.
9050
+ */
9051
+ closeDrawer() {
9052
+ this.isAnimating.set(true);
9053
+ this.detachFocusTrap();
9054
+ setTimeout(() => {
9055
+ this.isOpen.set(false);
9056
+ this.isAnimating.set(false);
9057
+ // Restaure le scroll du body
9058
+ this.documentRef.body.style.overflow = '';
9059
+ this.closed.emit();
9060
+ }, 300);
9061
+ }
9062
+ /**
9063
+ * Gère la fermeture du drawer.
9064
+ */
9065
+ handleClose() {
9066
+ if (!this.closable())
9067
+ return;
9068
+ this.visibleChange.emit(false);
9069
+ }
9070
+ /**
9071
+ * Gère le clic sur le backdrop.
9072
+ */
9073
+ handleBackdropClick() {
9074
+ if (!this.maskClosable())
9075
+ return;
9076
+ this.handleClose();
9077
+ }
9078
+ /**
9079
+ * Gère la touche Escape.
9080
+ */
9081
+ handleKeyDown(event) {
9082
+ if (event.key === 'Escape' && this.closable()) {
9083
+ event.preventDefault();
9084
+ this.handleClose();
9085
+ }
9086
+ }
9087
+ /**
9088
+ * Attache le focus trap.
9089
+ */
9090
+ attachFocusTrap() {
9091
+ if (this.focusTrap || !this.drawerContainer)
9092
+ return;
9093
+ const element = this.drawerContainer.nativeElement;
9094
+ this.focusTrap = this.focusTrapFactory.create(element);
9095
+ this.focusTrap.attachAnchors();
9096
+ }
9097
+ /**
9098
+ * Détache le focus trap.
9099
+ */
9100
+ detachFocusTrap() {
9101
+ if (this.focusTrap) {
9102
+ this.focusTrap.destroy();
9103
+ this.focusTrap = null;
9104
+ }
9105
+ }
9106
+ /**
9107
+ * Place le focus sur le premier élément focusable.
9108
+ */
9109
+ focusInitialElement() {
9110
+ if (!this.drawerContainer)
9111
+ return;
9112
+ const firstFocusable = this.drawerContainer.nativeElement.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
9113
+ if (firstFocusable) {
9114
+ firstFocusable.focus();
9115
+ }
9116
+ }
9117
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
9118
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsDrawer, isStandalone: true, selector: "ds-drawer", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, maskClosable: { classPropertyName: "maskClosable", publicName: "maskClosable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visibleChange: "visibleChange", closed: "closed" }, viewQueries: [{ propertyName: "drawerContainer", first: true, predicate: ["drawerContainer"], descendants: true }], ngImport: i0, template: "<!-- Backdrop -->\n@if (isOpen()) {\n <div\n [class]=\"backdropClasses()\"\n (click)=\"handleBackdropClick()\"\n aria-hidden=\"true\">\n </div>\n}\n\n<!-- Drawer Panel -->\n@if (isOpen()) {\n <div\n #drawerContainer\n [class]=\"containerClasses()\"\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"title() ? drawerTitleId : null\"\n (keydown)=\"handleKeyDown($event)\">\n\n <!-- Header -->\n <div class=\"ds-drawer__header\">\n @if (title()) {\n <h3 class=\"ds-drawer__title\" [id]=\"drawerTitleId\">{{ title() }}</h3>\n }\n\n <ng-content select=\"[drawer-header]\"></ng-content>\n\n @if (closable()) {\n <button\n class=\"ds-drawer__close\"\n type=\"button\"\n aria-label=\"Fermer\"\n (click)=\"handleClose()\">\n <fa-icon [icon]=\"closeIcon\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n\n <!-- Body -->\n <div class=\"ds-drawer__body\">\n <ng-content></ng-content>\n </div>\n\n <!-- Footer -->\n <div class=\"ds-drawer__footer\">\n <ng-content select=\"[drawer-footer]\"></ng-content>\n </div>\n </div>\n}\n", styles: [".ds-drawer__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--drawer-backdrop, rgba(var(--black-rgb), .5));z-index:var(--drawer-backdrop-z-index, 1000);opacity:0;transition:opacity .3s ease-in-out}.ds-drawer__backdrop--visible{opacity:1}.ds-drawer{position:fixed;top:0;height:100%;background:var(--drawer-bg, var(--surface-default));box-shadow:var(--drawer-shadow, var(--shadow-3));z-index:var(--drawer-z-index, 1001);display:flex;flex-direction:column;overflow:hidden;transition:transform .3s ease-in-out}.ds-drawer--left{left:0;transform:translate(-100%)}.ds-drawer--left.ds-drawer--open{transform:translate(0)}.ds-drawer--right{right:0;transform:translate(100%)}.ds-drawer--right.ds-drawer--open{transform:translate(0)}.ds-drawer--sm{width:var(--drawer-width-sm, 320px)}.ds-drawer--md{width:var(--drawer-width-md, 480px)}.ds-drawer--lg{width:var(--drawer-width-lg, 640px)}.ds-drawer--full{width:100%}.ds-drawer__header{display:flex;align-items:center;justify-content:space-between;padding:var(--drawer-header-padding, var(--space-4));border-bottom:1px solid var(--drawer-border, var(--border-color));background:var(--drawer-header-bg, var(--surface-raised));flex-shrink:0}.ds-drawer__title{margin:0;font-size:var(--drawer-title-font-size, var(--font-size-lg));font-weight:var(--drawer-title-font-weight, 600);color:var(--drawer-title-color, var(--text-default));flex:1}.ds-drawer__close{display:inline-flex;align-items:center;justify-content:center;width:var(--drawer-close-size, 32px);height:var(--drawer-close-size, 32px);padding:0;background:transparent;border:none;border-radius:var(--drawer-close-radius, var(--radius-1));color:var(--drawer-close-color, var(--text-muted));cursor:pointer;transition:all .15s ease}.ds-drawer__close:hover{background:var(--drawer-close-hover-bg, var(--surface-hover));color:var(--drawer-close-hover-color, var(--text-default))}.ds-drawer__close:active{background:var(--drawer-close-active-bg, var(--surface-raised))}.ds-drawer__close:focus-visible{outline:2px solid var(--drawer-close-focus-color, var(--color-primary));outline-offset:2px}.ds-drawer__body{flex:1;overflow-y:auto;padding:var(--drawer-body-padding, var(--space-4));color:var(--drawer-body-color, var(--text-default))}.ds-drawer__footer{padding:var(--drawer-footer-padding, var(--space-4));border-top:1px solid var(--drawer-border, var(--border-color));background:var(--drawer-footer-bg, var(--surface-raised));flex-shrink:0}.ds-drawer__footer:empty{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i1$1.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }] });
9119
+ }
9120
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsDrawer, decorators: [{
9121
+ type: Component,
9122
+ args: [{ selector: 'ds-drawer', imports: [CommonModule, FontAwesomeModule], template: "<!-- Backdrop -->\n@if (isOpen()) {\n <div\n [class]=\"backdropClasses()\"\n (click)=\"handleBackdropClick()\"\n aria-hidden=\"true\">\n </div>\n}\n\n<!-- Drawer Panel -->\n@if (isOpen()) {\n <div\n #drawerContainer\n [class]=\"containerClasses()\"\n role=\"dialog\"\n [attr.aria-modal]=\"true\"\n [attr.aria-labelledby]=\"title() ? drawerTitleId : null\"\n (keydown)=\"handleKeyDown($event)\">\n\n <!-- Header -->\n <div class=\"ds-drawer__header\">\n @if (title()) {\n <h3 class=\"ds-drawer__title\" [id]=\"drawerTitleId\">{{ title() }}</h3>\n }\n\n <ng-content select=\"[drawer-header]\"></ng-content>\n\n @if (closable()) {\n <button\n class=\"ds-drawer__close\"\n type=\"button\"\n aria-label=\"Fermer\"\n (click)=\"handleClose()\">\n <fa-icon [icon]=\"closeIcon\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n\n <!-- Body -->\n <div class=\"ds-drawer__body\">\n <ng-content></ng-content>\n </div>\n\n <!-- Footer -->\n <div class=\"ds-drawer__footer\">\n <ng-content select=\"[drawer-footer]\"></ng-content>\n </div>\n </div>\n}\n", styles: [".ds-drawer__backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:var(--drawer-backdrop, rgba(var(--black-rgb), .5));z-index:var(--drawer-backdrop-z-index, 1000);opacity:0;transition:opacity .3s ease-in-out}.ds-drawer__backdrop--visible{opacity:1}.ds-drawer{position:fixed;top:0;height:100%;background:var(--drawer-bg, var(--surface-default));box-shadow:var(--drawer-shadow, var(--shadow-3));z-index:var(--drawer-z-index, 1001);display:flex;flex-direction:column;overflow:hidden;transition:transform .3s ease-in-out}.ds-drawer--left{left:0;transform:translate(-100%)}.ds-drawer--left.ds-drawer--open{transform:translate(0)}.ds-drawer--right{right:0;transform:translate(100%)}.ds-drawer--right.ds-drawer--open{transform:translate(0)}.ds-drawer--sm{width:var(--drawer-width-sm, 320px)}.ds-drawer--md{width:var(--drawer-width-md, 480px)}.ds-drawer--lg{width:var(--drawer-width-lg, 640px)}.ds-drawer--full{width:100%}.ds-drawer__header{display:flex;align-items:center;justify-content:space-between;padding:var(--drawer-header-padding, var(--space-4));border-bottom:1px solid var(--drawer-border, var(--border-color));background:var(--drawer-header-bg, var(--surface-raised));flex-shrink:0}.ds-drawer__title{margin:0;font-size:var(--drawer-title-font-size, var(--font-size-lg));font-weight:var(--drawer-title-font-weight, 600);color:var(--drawer-title-color, var(--text-default));flex:1}.ds-drawer__close{display:inline-flex;align-items:center;justify-content:center;width:var(--drawer-close-size, 32px);height:var(--drawer-close-size, 32px);padding:0;background:transparent;border:none;border-radius:var(--drawer-close-radius, var(--radius-1));color:var(--drawer-close-color, var(--text-muted));cursor:pointer;transition:all .15s ease}.ds-drawer__close:hover{background:var(--drawer-close-hover-bg, var(--surface-hover));color:var(--drawer-close-hover-color, var(--text-default))}.ds-drawer__close:active{background:var(--drawer-close-active-bg, var(--surface-raised))}.ds-drawer__close:focus-visible{outline:2px solid var(--drawer-close-focus-color, var(--color-primary));outline-offset:2px}.ds-drawer__body{flex:1;overflow-y:auto;padding:var(--drawer-body-padding, var(--space-4));color:var(--drawer-body-color, var(--text-default))}.ds-drawer__footer{padding:var(--drawer-footer-padding, var(--space-4));border-top:1px solid var(--drawer-border, var(--border-color));background:var(--drawer-footer-bg, var(--surface-raised));flex-shrink:0}.ds-drawer__footer:empty{display:none}\n"] }]
9123
+ }], ctorParameters: () => [], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], maskClosable: [{ type: i0.Input, args: [{ isSignal: true, alias: "maskClosable", required: false }] }], visibleChange: [{ type: i0.Output, args: ["visibleChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], drawerContainer: [{
9124
+ type: ViewChild,
9125
+ args: ['drawerContainer']
9126
+ }] } });
9127
+
9128
+ class DsTimePickerPanelComponent {
9129
+ hoursColumn;
9130
+ minutesColumn;
9131
+ secondsColumn;
9132
+ // Config (set by parent)
9133
+ value = '';
9134
+ format = '24h';
9135
+ showSeconds = false;
9136
+ minuteStep = 1;
9137
+ hourStep = 1;
9138
+ minTime = null;
9139
+ maxTime = null;
9140
+ // Outputs
9141
+ timeSelected = output();
9142
+ // State
9143
+ selectedHours = signal(0, ...(ngDevMode ? [{ debugName: "selectedHours" }] : []));
9144
+ selectedMinutes = signal(0, ...(ngDevMode ? [{ debugName: "selectedMinutes" }] : []));
9145
+ selectedSeconds = signal(0, ...(ngDevMode ? [{ debugName: "selectedSeconds" }] : []));
9146
+ selectedPeriod = signal('AM', ...(ngDevMode ? [{ debugName: "selectedPeriod" }] : []));
9147
+ // Computed
9148
+ hoursOptions = computed(() => {
9149
+ const options = [];
9150
+ const max = this.format === '12h' ? 12 : 23;
9151
+ const start = this.format === '12h' ? 1 : 0;
9152
+ for (let i = start; i <= max; i += this.hourStep) {
9153
+ options.push({
9154
+ value: i,
9155
+ label: i.toString().padStart(2, '0'),
9156
+ disabled: this.isHourDisabled(i),
9157
+ });
9158
+ }
9159
+ return options;
9160
+ }, ...(ngDevMode ? [{ debugName: "hoursOptions" }] : []));
9161
+ minutesOptions = computed(() => {
9162
+ const options = [];
9163
+ for (let i = 0; i < 60; i += this.minuteStep) {
9164
+ options.push({
9165
+ value: i,
9166
+ label: i.toString().padStart(2, '0'),
9167
+ disabled: this.isMinuteDisabled(i),
9168
+ });
9169
+ }
9170
+ return options;
9171
+ }, ...(ngDevMode ? [{ debugName: "minutesOptions" }] : []));
9172
+ secondsOptions = computed(() => {
9173
+ const options = [];
9174
+ for (let i = 0; i < 60; i++) {
9175
+ options.push({
9176
+ value: i,
9177
+ label: i.toString().padStart(2, '0'),
9178
+ disabled: false,
9179
+ });
9180
+ }
9181
+ return options;
9182
+ }, ...(ngDevMode ? [{ debugName: "secondsOptions" }] : []));
9183
+ constructor() {
9184
+ // Parse initial value
9185
+ effect(() => {
9186
+ this.parseAndSetValue();
9187
+ }, { allowSignalWrites: true });
9188
+ // Emit when values change
9189
+ effect(() => {
9190
+ const hours = this.selectedHours();
9191
+ const minutes = this.selectedMinutes();
9192
+ const seconds = this.selectedSeconds();
9193
+ const period = this.selectedPeriod();
9194
+ this.emitTime(hours, minutes, seconds, period);
9195
+ });
9196
+ }
9197
+ ngAfterViewInit() {
9198
+ // Scroll to selected values
9199
+ setTimeout(() => {
9200
+ this.scrollToSelected();
9201
+ }, 0);
9202
+ }
9203
+ selectHours(hours) {
9204
+ this.selectedHours.set(hours);
9205
+ }
9206
+ selectMinutes(minutes) {
9207
+ this.selectedMinutes.set(minutes);
9208
+ }
9209
+ selectSeconds(seconds) {
9210
+ this.selectedSeconds.set(seconds);
9211
+ }
9212
+ selectPeriod(period) {
9213
+ this.selectedPeriod.set(period);
9214
+ }
9215
+ onScroll(column, event) {
9216
+ // Optional: could implement snap-to-value on scroll end
9217
+ }
9218
+ parseAndSetValue() {
9219
+ if (!this.value) {
9220
+ this.selectedHours.set(this.format === '12h' ? 12 : 0);
9221
+ this.selectedMinutes.set(0);
9222
+ this.selectedSeconds.set(0);
9223
+ this.selectedPeriod.set('AM');
9224
+ return;
9225
+ }
9226
+ const parts = this.value.split(':');
9227
+ if (parts.length < 2)
9228
+ return;
9229
+ let hours = parseInt(parts[0], 10);
9230
+ const minutes = parseInt(parts[1], 10);
9231
+ const seconds = parts[2] ? parseInt(parts[2], 10) : 0;
9232
+ if (this.format === '12h') {
9233
+ const period = hours >= 12 ? 'PM' : 'AM';
9234
+ hours = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours;
9235
+ this.selectedPeriod.set(period);
9236
+ }
9237
+ this.selectedHours.set(hours);
9238
+ this.selectedMinutes.set(minutes);
9239
+ this.selectedSeconds.set(seconds);
9240
+ }
9241
+ emitTime(hours, minutes, seconds, period) {
9242
+ let finalHours = hours;
9243
+ if (this.format === '12h') {
9244
+ if (period === 'PM' && hours !== 12) {
9245
+ finalHours = hours + 12;
9246
+ }
9247
+ else if (period === 'AM' && hours === 12) {
9248
+ finalHours = 0;
9249
+ }
9250
+ }
9251
+ const hoursStr = finalHours.toString().padStart(2, '0');
9252
+ const minutesStr = minutes.toString().padStart(2, '0');
9253
+ const secondsStr = seconds.toString().padStart(2, '0');
9254
+ const timeString = this.showSeconds
9255
+ ? `${hoursStr}:${minutesStr}:${secondsStr}`
9256
+ : `${hoursStr}:${minutesStr}`;
9257
+ this.timeSelected.emit(timeString);
9258
+ }
9259
+ isHourDisabled(hour) {
9260
+ // TODO: implement minTime/maxTime validation
9261
+ return false;
9262
+ }
9263
+ isMinuteDisabled(minute) {
9264
+ // TODO: implement minTime/maxTime validation
9265
+ return false;
9266
+ }
9267
+ scrollToSelected() {
9268
+ this.scrollColumnToValue(this.hoursColumn, this.selectedHours());
9269
+ this.scrollColumnToValue(this.minutesColumn, this.selectedMinutes());
9270
+ if (this.showSeconds && this.secondsColumn) {
9271
+ this.scrollColumnToValue(this.secondsColumn, this.selectedSeconds());
9272
+ }
9273
+ }
9274
+ scrollColumnToValue(column, value) {
9275
+ if (!column)
9276
+ return;
9277
+ const element = column.nativeElement;
9278
+ const options = element.querySelectorAll('.ds-time-picker-panel__option');
9279
+ const selectedOption = Array.from(options).find((option) => option.textContent?.trim() === value.toString().padStart(2, '0'));
9280
+ if (selectedOption) {
9281
+ const optionElement = selectedOption;
9282
+ element.scrollTop = optionElement.offsetTop - element.offsetHeight / 2 + optionElement.offsetHeight / 2;
9283
+ }
9284
+ }
9285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTimePickerPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9286
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsTimePickerPanelComponent, isStandalone: true, selector: "ds-time-picker-panel", outputs: { timeSelected: "timeSelected" }, viewQueries: [{ propertyName: "hoursColumn", first: true, predicate: ["hoursColumn"], descendants: true }, { propertyName: "minutesColumn", first: true, predicate: ["minutesColumn"], descendants: true }, { propertyName: "secondsColumn", first: true, predicate: ["secondsColumn"], descendants: true }], ngImport: i0, template: `
9287
+ <div class="ds-time-picker-panel" role="dialog" aria-label="Time picker">
9288
+ <div class="ds-time-picker-panel__columns">
9289
+ <!-- Hours column -->
9290
+ <div class="ds-time-picker-panel__column" role="listbox" aria-label="Hours">
9291
+ <div
9292
+ #hoursColumn
9293
+ class="ds-time-picker-panel__column-scroll"
9294
+ (scroll)="onScroll('hours', $event)">
9295
+ @for (hour of hoursOptions(); track hour.value) {
9296
+ <button
9297
+ type="button"
9298
+ class="ds-time-picker-panel__option"
9299
+ [class.ds-time-picker-panel__option--selected]="hour.value === selectedHours()"
9300
+ [class.ds-time-picker-panel__option--disabled]="hour.disabled"
9301
+ [disabled]="hour.disabled"
9302
+ [attr.role]="'option'"
9303
+ [attr.aria-selected]="hour.value === selectedHours()"
9304
+ (click)="selectHours(hour.value)">
9305
+ {{ hour.label }}
9306
+ </button>
9307
+ }
9308
+ </div>
9309
+ </div>
9310
+
9311
+ <!-- Minutes column -->
9312
+ <div class="ds-time-picker-panel__column" role="listbox" aria-label="Minutes">
9313
+ <div
9314
+ #minutesColumn
9315
+ class="ds-time-picker-panel__column-scroll"
9316
+ (scroll)="onScroll('minutes', $event)">
9317
+ @for (minute of minutesOptions(); track minute.value) {
9318
+ <button
9319
+ type="button"
9320
+ class="ds-time-picker-panel__option"
9321
+ [class.ds-time-picker-panel__option--selected]="minute.value === selectedMinutes()"
9322
+ [class.ds-time-picker-panel__option--disabled]="minute.disabled"
9323
+ [disabled]="minute.disabled"
9324
+ [attr.role]="'option'"
9325
+ [attr.aria-selected]="minute.value === selectedMinutes()"
9326
+ (click)="selectMinutes(minute.value)">
9327
+ {{ minute.label }}
9328
+ </button>
9329
+ }
9330
+ </div>
9331
+ </div>
9332
+
9333
+ <!-- Seconds column (conditional) -->
9334
+ @if (showSeconds) {
9335
+ <div class="ds-time-picker-panel__column" role="listbox" aria-label="Seconds">
9336
+ <div
9337
+ #secondsColumn
9338
+ class="ds-time-picker-panel__column-scroll"
9339
+ (scroll)="onScroll('seconds', $event)">
9340
+ @for (second of secondsOptions(); track second.value) {
9341
+ <button
9342
+ type="button"
9343
+ class="ds-time-picker-panel__option"
9344
+ [class.ds-time-picker-panel__option--selected]="second.value === selectedSeconds()"
9345
+ [class.ds-time-picker-panel__option--disabled]="second.disabled"
9346
+ [disabled]="second.disabled"
9347
+ [attr.role]="'option'"
9348
+ [attr.aria-selected]="second.value === selectedSeconds()"
9349
+ (click)="selectSeconds(second.value)">
9350
+ {{ second.label }}
9351
+ </button>
9352
+ }
9353
+ </div>
9354
+ </div>
9355
+ }
9356
+
9357
+ <!-- AM/PM column (12h format) -->
9358
+ @if (format === '12h') {
9359
+ <div class="ds-time-picker-panel__column ds-time-picker-panel__column--period" role="listbox" aria-label="Period">
9360
+ <div class="ds-time-picker-panel__column-scroll">
9361
+ <button
9362
+ type="button"
9363
+ class="ds-time-picker-panel__option"
9364
+ [class.ds-time-picker-panel__option--selected]="selectedPeriod() === 'AM'"
9365
+ [attr.role]="'option'"
9366
+ [attr.aria-selected]="selectedPeriod() === 'AM'"
9367
+ (click)="selectPeriod('AM')">
9368
+ AM
9369
+ </button>
9370
+ <button
9371
+ type="button"
9372
+ class="ds-time-picker-panel__option"
9373
+ [class.ds-time-picker-panel__option--selected]="selectedPeriod() === 'PM'"
9374
+ [attr.role]="'option'"
9375
+ [attr.aria-selected]="selectedPeriod() === 'PM'"
9376
+ (click)="selectPeriod('PM')">
9377
+ PM
9378
+ </button>
9379
+ </div>
9380
+ </div>
9381
+ }
9382
+ </div>
9383
+ </div>
9384
+ `, isInline: true, styles: [".ds-time-picker-panel{background-color:var(--time-picker-panel-bg, var(--white));border:1px solid var(--time-picker-panel-border, var(--gray-300));border-radius:var(--radius-2);box-shadow:var(--shadow-lg);padding:var(--space-2);min-width:200px}.ds-time-picker-panel__columns{display:flex;gap:var(--space-2)}.ds-time-picker-panel__column{display:flex;flex-direction:column;flex:1;min-width:60px}.ds-time-picker-panel__column--period{min-width:50px}.ds-time-picker-panel__column-scroll{max-height:200px;overflow-y:auto;border:1px solid var(--time-picker-column-border, var(--gray-200));border-radius:var(--radius-1);background-color:var(--time-picker-column-bg, var(--white))}.ds-time-picker-panel__column-scroll::-webkit-scrollbar{width:6px}.ds-time-picker-panel__column-scroll::-webkit-scrollbar-track{background:var(--gray-100);border-radius:var(--radius-1)}.ds-time-picker-panel__column-scroll::-webkit-scrollbar-thumb{background:var(--gray-400);border-radius:var(--radius-1)}.ds-time-picker-panel__column-scroll::-webkit-scrollbar-thumb:hover{background:var(--gray-500)}.ds-time-picker-panel__option{display:flex;align-items:center;justify-content:center;padding:var(--space-2);background:transparent;border:none;cursor:pointer;font-size:var(--font-size-sm);color:var(--time-picker-option-text, var(--gray-900));transition:all .15s ease;outline:none}.ds-time-picker-panel__option:hover:not(.ds-time-picker-panel__option--disabled){background-color:var(--time-picker-option-hover, var(--gray-100))}.ds-time-picker-panel__option:focus-visible{background-color:var(--time-picker-option-focus, var(--gray-100));box-shadow:inset 0 0 0 2px var(--color-primary)}.ds-time-picker-panel__option--selected{background-color:var(--time-picker-option-selected-bg, var(--color-primary));color:var(--time-picker-option-selected-text, var(--white));font-weight:600}.ds-time-picker-panel__option--selected:hover{background-color:var(--time-picker-option-selected-hover, var(--primary-dark))}.ds-time-picker-panel__option--disabled{opacity:.4;cursor:not-allowed;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9385
+ }
9386
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTimePickerPanelComponent, decorators: [{
9387
+ type: Component,
9388
+ args: [{ selector: 'ds-time-picker-panel', standalone: true, imports: [CommonModule], template: `
9389
+ <div class="ds-time-picker-panel" role="dialog" aria-label="Time picker">
9390
+ <div class="ds-time-picker-panel__columns">
9391
+ <!-- Hours column -->
9392
+ <div class="ds-time-picker-panel__column" role="listbox" aria-label="Hours">
9393
+ <div
9394
+ #hoursColumn
9395
+ class="ds-time-picker-panel__column-scroll"
9396
+ (scroll)="onScroll('hours', $event)">
9397
+ @for (hour of hoursOptions(); track hour.value) {
9398
+ <button
9399
+ type="button"
9400
+ class="ds-time-picker-panel__option"
9401
+ [class.ds-time-picker-panel__option--selected]="hour.value === selectedHours()"
9402
+ [class.ds-time-picker-panel__option--disabled]="hour.disabled"
9403
+ [disabled]="hour.disabled"
9404
+ [attr.role]="'option'"
9405
+ [attr.aria-selected]="hour.value === selectedHours()"
9406
+ (click)="selectHours(hour.value)">
9407
+ {{ hour.label }}
9408
+ </button>
9409
+ }
9410
+ </div>
9411
+ </div>
9412
+
9413
+ <!-- Minutes column -->
9414
+ <div class="ds-time-picker-panel__column" role="listbox" aria-label="Minutes">
9415
+ <div
9416
+ #minutesColumn
9417
+ class="ds-time-picker-panel__column-scroll"
9418
+ (scroll)="onScroll('minutes', $event)">
9419
+ @for (minute of minutesOptions(); track minute.value) {
9420
+ <button
9421
+ type="button"
9422
+ class="ds-time-picker-panel__option"
9423
+ [class.ds-time-picker-panel__option--selected]="minute.value === selectedMinutes()"
9424
+ [class.ds-time-picker-panel__option--disabled]="minute.disabled"
9425
+ [disabled]="minute.disabled"
9426
+ [attr.role]="'option'"
9427
+ [attr.aria-selected]="minute.value === selectedMinutes()"
9428
+ (click)="selectMinutes(minute.value)">
9429
+ {{ minute.label }}
9430
+ </button>
9431
+ }
9432
+ </div>
9433
+ </div>
9434
+
9435
+ <!-- Seconds column (conditional) -->
9436
+ @if (showSeconds) {
9437
+ <div class="ds-time-picker-panel__column" role="listbox" aria-label="Seconds">
9438
+ <div
9439
+ #secondsColumn
9440
+ class="ds-time-picker-panel__column-scroll"
9441
+ (scroll)="onScroll('seconds', $event)">
9442
+ @for (second of secondsOptions(); track second.value) {
9443
+ <button
9444
+ type="button"
9445
+ class="ds-time-picker-panel__option"
9446
+ [class.ds-time-picker-panel__option--selected]="second.value === selectedSeconds()"
9447
+ [class.ds-time-picker-panel__option--disabled]="second.disabled"
9448
+ [disabled]="second.disabled"
9449
+ [attr.role]="'option'"
9450
+ [attr.aria-selected]="second.value === selectedSeconds()"
9451
+ (click)="selectSeconds(second.value)">
9452
+ {{ second.label }}
9453
+ </button>
9454
+ }
9455
+ </div>
9456
+ </div>
9457
+ }
9458
+
9459
+ <!-- AM/PM column (12h format) -->
9460
+ @if (format === '12h') {
9461
+ <div class="ds-time-picker-panel__column ds-time-picker-panel__column--period" role="listbox" aria-label="Period">
9462
+ <div class="ds-time-picker-panel__column-scroll">
9463
+ <button
9464
+ type="button"
9465
+ class="ds-time-picker-panel__option"
9466
+ [class.ds-time-picker-panel__option--selected]="selectedPeriod() === 'AM'"
9467
+ [attr.role]="'option'"
9468
+ [attr.aria-selected]="selectedPeriod() === 'AM'"
9469
+ (click)="selectPeriod('AM')">
9470
+ AM
9471
+ </button>
9472
+ <button
9473
+ type="button"
9474
+ class="ds-time-picker-panel__option"
9475
+ [class.ds-time-picker-panel__option--selected]="selectedPeriod() === 'PM'"
9476
+ [attr.role]="'option'"
9477
+ [attr.aria-selected]="selectedPeriod() === 'PM'"
9478
+ (click)="selectPeriod('PM')">
9479
+ PM
9480
+ </button>
9481
+ </div>
9482
+ </div>
9483
+ }
9484
+ </div>
9485
+ </div>
9486
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ds-time-picker-panel{background-color:var(--time-picker-panel-bg, var(--white));border:1px solid var(--time-picker-panel-border, var(--gray-300));border-radius:var(--radius-2);box-shadow:var(--shadow-lg);padding:var(--space-2);min-width:200px}.ds-time-picker-panel__columns{display:flex;gap:var(--space-2)}.ds-time-picker-panel__column{display:flex;flex-direction:column;flex:1;min-width:60px}.ds-time-picker-panel__column--period{min-width:50px}.ds-time-picker-panel__column-scroll{max-height:200px;overflow-y:auto;border:1px solid var(--time-picker-column-border, var(--gray-200));border-radius:var(--radius-1);background-color:var(--time-picker-column-bg, var(--white))}.ds-time-picker-panel__column-scroll::-webkit-scrollbar{width:6px}.ds-time-picker-panel__column-scroll::-webkit-scrollbar-track{background:var(--gray-100);border-radius:var(--radius-1)}.ds-time-picker-panel__column-scroll::-webkit-scrollbar-thumb{background:var(--gray-400);border-radius:var(--radius-1)}.ds-time-picker-panel__column-scroll::-webkit-scrollbar-thumb:hover{background:var(--gray-500)}.ds-time-picker-panel__option{display:flex;align-items:center;justify-content:center;padding:var(--space-2);background:transparent;border:none;cursor:pointer;font-size:var(--font-size-sm);color:var(--time-picker-option-text, var(--gray-900));transition:all .15s ease;outline:none}.ds-time-picker-panel__option:hover:not(.ds-time-picker-panel__option--disabled){background-color:var(--time-picker-option-hover, var(--gray-100))}.ds-time-picker-panel__option:focus-visible{background-color:var(--time-picker-option-focus, var(--gray-100));box-shadow:inset 0 0 0 2px var(--color-primary)}.ds-time-picker-panel__option--selected{background-color:var(--time-picker-option-selected-bg, var(--color-primary));color:var(--time-picker-option-selected-text, var(--white));font-weight:600}.ds-time-picker-panel__option--selected:hover{background-color:var(--time-picker-option-selected-hover, var(--primary-dark))}.ds-time-picker-panel__option--disabled{opacity:.4;cursor:not-allowed;pointer-events:none}\n"] }]
9487
+ }], ctorParameters: () => [], propDecorators: { hoursColumn: [{
9488
+ type: ViewChild,
9489
+ args: ['hoursColumn']
9490
+ }], minutesColumn: [{
9491
+ type: ViewChild,
9492
+ args: ['minutesColumn']
9493
+ }], secondsColumn: [{
9494
+ type: ViewChild,
9495
+ args: ['secondsColumn']
9496
+ }], timeSelected: [{ type: i0.Output, args: ["timeSelected"] }] } });
9497
+
9498
+ /**
9499
+ * DsTimePicker - Composant de sélection d'heure
9500
+ *
9501
+ * @description
9502
+ * Sélecteur d'heure avec dropdown scrollable, support 12h/24h,
9503
+ * et intégration formulaires via ControlValueAccessor.
9504
+ *
9505
+ * @example
9506
+ * ```html
9507
+ * <ds-time-picker
9508
+ * [format]="'24h'"
9509
+ * [showSeconds]="true"
9510
+ * (timeChange)="onTimeChange($event)">
9511
+ * </ds-time-picker>
9512
+ * ```
9513
+ */
9514
+ class DsTimePicker {
9515
+ overlay;
9516
+ // Inputs
9517
+ value = input('', ...(ngDevMode ? [{ debugName: "value" }] : []));
9518
+ format = input('24h', ...(ngDevMode ? [{ debugName: "format" }] : []));
9519
+ showSeconds = input(false, ...(ngDevMode ? [{ debugName: "showSeconds" }] : []));
9520
+ minuteStep = input(1, ...(ngDevMode ? [{ debugName: "minuteStep" }] : []));
9521
+ hourStep = input(1, ...(ngDevMode ? [{ debugName: "hourStep" }] : []));
9522
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
9523
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
9524
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
9525
+ placeholder = input('Select time', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
9526
+ minTime = input(null, ...(ngDevMode ? [{ debugName: "minTime" }] : []));
9527
+ maxTime = input(null, ...(ngDevMode ? [{ debugName: "maxTime" }] : []));
9528
+ // Outputs
9529
+ timeChange = output();
9530
+ // Icons
9531
+ clockIcon = faClock;
9532
+ upIcon = faChevronUp;
9533
+ downIcon = faChevronDown;
9534
+ // State
9535
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
9536
+ internalValue = signal('', ...(ngDevMode ? [{ debugName: "internalValue" }] : []));
9537
+ isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : []));
9538
+ // Overlay
9539
+ overlayRef = null;
9540
+ // Computed
9541
+ containerClasses = computed(() => {
9542
+ const classes = ['ds-time-picker'];
9543
+ classes.push(`ds-time-picker--${this.size()}`);
9544
+ if (this.disabled())
9545
+ classes.push('ds-time-picker--disabled');
9546
+ if (this.readonly())
9547
+ classes.push('ds-time-picker--readonly');
9548
+ if (this.isFocused())
9549
+ classes.push('ds-time-picker--focused');
9550
+ if (this.isOpen())
9551
+ classes.push('ds-time-picker--open');
9552
+ return classes.join(' ');
9553
+ }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
9554
+ displayValue = computed(() => {
9555
+ const val = this.internalValue();
9556
+ if (!val)
9557
+ return '';
9558
+ const time = this.parseTime(val);
9559
+ if (!time)
9560
+ return val;
9561
+ return this.formatTimeForDisplay(time);
9562
+ }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
9563
+ isDisabled = computed(() => this.disabled() || this.readonly(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
9564
+ // ControlValueAccessor
9565
+ onChange = () => { };
9566
+ onTouched = () => { };
9567
+ constructor(overlay) {
9568
+ this.overlay = overlay;
9569
+ // Sync external value with internal
9570
+ effect(() => {
9571
+ const val = this.value();
9572
+ if (val !== this.internalValue()) {
9573
+ this.internalValue.set(val);
9574
+ }
9575
+ });
9576
+ }
9577
+ writeValue(value) {
9578
+ this.internalValue.set(value || '');
9579
+ }
9580
+ registerOnChange(fn) {
9581
+ this.onChange = fn;
9582
+ }
9583
+ registerOnTouched(fn) {
9584
+ this.onTouched = fn;
9585
+ }
9586
+ setDisabledState(isDisabled) {
9587
+ // Géré par input disabled
9588
+ }
9589
+ toggle() {
9590
+ if (this.isDisabled())
9591
+ return;
9592
+ if (this.isOpen()) {
9593
+ this.close();
9594
+ }
9595
+ else {
9596
+ this.open();
9597
+ }
9598
+ }
9599
+ open() {
9600
+ if (this.isDisabled() || this.isOpen())
9601
+ return;
9602
+ this.isOpen.set(true);
9603
+ this.createOverlay();
9604
+ }
9605
+ close() {
9606
+ if (!this.isOpen())
9607
+ return;
9608
+ this.isOpen.set(false);
9609
+ this.destroyOverlay();
9610
+ this.onTouched();
9611
+ }
9612
+ onFocus() {
9613
+ if (!this.disabled()) {
9614
+ this.isFocused.set(true);
9615
+ }
9616
+ }
9617
+ onBlur() {
9618
+ this.isFocused.set(false);
9619
+ if (!this.isOpen()) {
9620
+ this.onTouched();
9621
+ }
9622
+ }
9623
+ onTimeSelected(timeString) {
9624
+ this.updateValue(timeString);
9625
+ this.close();
9626
+ }
9627
+ updateValue(value) {
9628
+ this.internalValue.set(value);
9629
+ this.onChange(value);
9630
+ this.timeChange.emit(value);
9631
+ }
9632
+ createOverlay() {
9633
+ if (this.overlayRef)
9634
+ return;
9635
+ const positionStrategy = this.overlay
9636
+ .position()
9637
+ .flexibleConnectedTo(document.querySelector('.ds-time-picker__input'))
9638
+ .withPositions([
9639
+ {
9640
+ originX: 'start',
9641
+ originY: 'bottom',
9642
+ overlayX: 'start',
9643
+ overlayY: 'top',
9644
+ offsetY: 4,
9645
+ },
9646
+ {
9647
+ originX: 'start',
9648
+ originY: 'top',
9649
+ overlayX: 'start',
9650
+ overlayY: 'bottom',
9651
+ offsetY: -4,
9652
+ },
9653
+ ]);
9654
+ this.overlayRef = this.overlay.create({
9655
+ positionStrategy,
9656
+ hasBackdrop: true,
9657
+ backdropClass: 'cdk-overlay-transparent-backdrop',
9658
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
9659
+ });
9660
+ const portal = new ComponentPortal(DsTimePickerPanelComponent);
9661
+ const componentRef = this.overlayRef.attach(portal);
9662
+ // Pass config to panel
9663
+ componentRef.instance.value = this.internalValue();
9664
+ componentRef.instance.format = this.format();
9665
+ componentRef.instance.showSeconds = this.showSeconds();
9666
+ componentRef.instance.minuteStep = this.minuteStep();
9667
+ componentRef.instance.hourStep = this.hourStep();
9668
+ componentRef.instance.minTime = this.minTime();
9669
+ componentRef.instance.maxTime = this.maxTime();
9670
+ componentRef.instance.timeSelected.subscribe((time) => {
9671
+ this.onTimeSelected(time);
9672
+ });
9673
+ this.overlayRef.backdropClick().subscribe(() => this.close());
9674
+ }
9675
+ destroyOverlay() {
9676
+ if (this.overlayRef) {
9677
+ this.overlayRef.dispose();
9678
+ this.overlayRef = null;
9679
+ }
9680
+ }
9681
+ parseTime(timeString) {
9682
+ if (!timeString)
9683
+ return null;
9684
+ const parts = timeString.split(':');
9685
+ if (parts.length < 2)
9686
+ return null;
9687
+ const hours = parseInt(parts[0], 10);
9688
+ const minutes = parseInt(parts[1], 10);
9689
+ const seconds = parts[2] ? parseInt(parts[2], 10) : undefined;
9690
+ if (isNaN(hours) || isNaN(minutes))
9691
+ return null;
9692
+ if (seconds !== undefined && isNaN(seconds))
9693
+ return null;
9694
+ return { hours, minutes, seconds };
9695
+ }
9696
+ formatTimeForDisplay(time) {
9697
+ const { hours, minutes, seconds } = time;
9698
+ if (this.format() === '12h') {
9699
+ const period = hours >= 12 ? 'PM' : 'AM';
9700
+ const displayHours = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours;
9701
+ const formattedMinutes = minutes.toString().padStart(2, '0');
9702
+ if (this.showSeconds() && seconds !== undefined) {
9703
+ const formattedSeconds = seconds.toString().padStart(2, '0');
9704
+ return `${displayHours}:${formattedMinutes}:${formattedSeconds} ${period}`;
9705
+ }
9706
+ return `${displayHours}:${formattedMinutes} ${period}`;
9707
+ }
9708
+ else {
9709
+ const formattedHours = hours.toString().padStart(2, '0');
9710
+ const formattedMinutes = minutes.toString().padStart(2, '0');
9711
+ if (this.showSeconds() && seconds !== undefined) {
9712
+ const formattedSeconds = seconds.toString().padStart(2, '0');
9713
+ return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
9714
+ }
9715
+ return `${formattedHours}:${formattedMinutes}`;
9716
+ }
9717
+ }
9718
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTimePicker, deps: [{ token: i1$3.Overlay }], target: i0.ɵɵFactoryTarget.Component });
9719
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsTimePicker, isStandalone: true, selector: "ds-time-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null }, hourStep: { classPropertyName: "hourStep", publicName: "hourStep", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timeChange: "timeChange" }, providers: [
9720
+ {
9721
+ provide: NG_VALUE_ACCESSOR,
9722
+ useExisting: forwardRef(() => DsTimePicker),
9723
+ multi: true,
9724
+ },
9725
+ ], ngImport: i0, template: "<div [class]=\"containerClasses()\">\n <div class=\"ds-time-picker__wrapper\">\n <div\n class=\"ds-time-picker__input\"\n [class.ds-time-picker__input--disabled]=\"disabled()\"\n [class.ds-time-picker__input--readonly]=\"readonly()\"\n [class.ds-time-picker__input--focused]=\"isFocused()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-label]=\"placeholder()\"\n (click)=\"toggle()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown.enter)=\"toggle()\"\n (keydown.space)=\"toggle(); $event.preventDefault()\">\n\n <fa-icon\n class=\"ds-time-picker__icon\"\n [icon]=\"clockIcon\"\n aria-hidden=\"true\">\n </fa-icon>\n\n <span class=\"ds-time-picker__display\">\n @if (displayValue(); as display) {\n {{ display }}\n } @else {\n <span class=\"ds-time-picker__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n </div>\n </div>\n</div>\n", styles: [".ds-time-picker{display:inline-block;position:relative}.ds-time-picker__wrapper{position:relative}.ds-time-picker__input{display:flex;align-items:center;gap:var(--space-2);padding:0 var(--input-padding-horizontal-md);height:var(--input-height-md);background-color:var(--input-bg, var(--white));border:1px solid var(--input-border-color, var(--gray-300));border-radius:var(--input-border-radius);cursor:pointer;transition:all .2s ease;outline:none}.ds-time-picker__input:hover:not(.ds-time-picker__input--disabled):not(.ds-time-picker__input--readonly){border-color:var(--input-border-hover, var(--gray-400))}.ds-time-picker__input--focused{border-color:var(--input-border-focus, var(--color-primary));box-shadow:var(--input-focus-shadow)}.ds-time-picker__input--disabled{opacity:.5;cursor:not-allowed;background-color:var(--input-bg-disabled, var(--gray-100))}.ds-time-picker__input--readonly{cursor:default;background-color:var(--input-bg-readonly, var(--gray-50))}.ds-time-picker__icon{color:var(--input-text-color, var(--gray-600));font-size:var(--input-icon-md);flex-shrink:0}.ds-time-picker__display{flex:1;color:var(--input-text-color, var(--gray-900));font-size:var(--input-font-size-md);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ds-time-picker__placeholder{color:var(--input-placeholder-color, var(--gray-500))}.ds-time-picker--sm .ds-time-picker__input{height:var(--input-height-sm);padding:0 var(--input-padding-horizontal-sm)}.ds-time-picker--sm .ds-time-picker__display{font-size:var(--input-font-size-sm)}.ds-time-picker--sm .ds-time-picker__icon{font-size:var(--input-icon-sm)}.ds-time-picker--lg .ds-time-picker__input{height:var(--input-height-lg);padding:0 var(--input-padding-horizontal-lg)}.ds-time-picker--lg .ds-time-picker__display{font-size:var(--input-font-size-lg)}.ds-time-picker--lg .ds-time-picker__icon{font-size:var(--input-icon-lg)}.ds-time-picker--disabled{pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i1$1.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }, { kind: "ngmodule", type: OverlayModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9726
+ }
9727
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTimePicker, decorators: [{
9728
+ type: Component,
9729
+ args: [{ selector: 'ds-time-picker', standalone: true, imports: [CommonModule, FontAwesomeModule, OverlayModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
9730
+ {
9731
+ provide: NG_VALUE_ACCESSOR,
9732
+ useExisting: forwardRef(() => DsTimePicker),
9733
+ multi: true,
9734
+ },
9735
+ ], template: "<div [class]=\"containerClasses()\">\n <div class=\"ds-time-picker__wrapper\">\n <div\n class=\"ds-time-picker__input\"\n [class.ds-time-picker__input--disabled]=\"disabled()\"\n [class.ds-time-picker__input--readonly]=\"readonly()\"\n [class.ds-time-picker__input--focused]=\"isFocused()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-label]=\"placeholder()\"\n (click)=\"toggle()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown.enter)=\"toggle()\"\n (keydown.space)=\"toggle(); $event.preventDefault()\">\n\n <fa-icon\n class=\"ds-time-picker__icon\"\n [icon]=\"clockIcon\"\n aria-hidden=\"true\">\n </fa-icon>\n\n <span class=\"ds-time-picker__display\">\n @if (displayValue(); as display) {\n {{ display }}\n } @else {\n <span class=\"ds-time-picker__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n </div>\n </div>\n</div>\n", styles: [".ds-time-picker{display:inline-block;position:relative}.ds-time-picker__wrapper{position:relative}.ds-time-picker__input{display:flex;align-items:center;gap:var(--space-2);padding:0 var(--input-padding-horizontal-md);height:var(--input-height-md);background-color:var(--input-bg, var(--white));border:1px solid var(--input-border-color, var(--gray-300));border-radius:var(--input-border-radius);cursor:pointer;transition:all .2s ease;outline:none}.ds-time-picker__input:hover:not(.ds-time-picker__input--disabled):not(.ds-time-picker__input--readonly){border-color:var(--input-border-hover, var(--gray-400))}.ds-time-picker__input--focused{border-color:var(--input-border-focus, var(--color-primary));box-shadow:var(--input-focus-shadow)}.ds-time-picker__input--disabled{opacity:.5;cursor:not-allowed;background-color:var(--input-bg-disabled, var(--gray-100))}.ds-time-picker__input--readonly{cursor:default;background-color:var(--input-bg-readonly, var(--gray-50))}.ds-time-picker__icon{color:var(--input-text-color, var(--gray-600));font-size:var(--input-icon-md);flex-shrink:0}.ds-time-picker__display{flex:1;color:var(--input-text-color, var(--gray-900));font-size:var(--input-font-size-md);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ds-time-picker__placeholder{color:var(--input-placeholder-color, var(--gray-500))}.ds-time-picker--sm .ds-time-picker__input{height:var(--input-height-sm);padding:0 var(--input-padding-horizontal-sm)}.ds-time-picker--sm .ds-time-picker__display{font-size:var(--input-font-size-sm)}.ds-time-picker--sm .ds-time-picker__icon{font-size:var(--input-icon-sm)}.ds-time-picker--lg .ds-time-picker__input{height:var(--input-height-lg);padding:0 var(--input-padding-horizontal-lg)}.ds-time-picker--lg .ds-time-picker__display{font-size:var(--input-font-size-lg)}.ds-time-picker--lg .ds-time-picker__icon{font-size:var(--input-icon-lg)}.ds-time-picker--disabled{pointer-events:none}\n"] }]
9736
+ }], ctorParameters: () => [{ type: i1$3.Overlay }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], hourStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourStep", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], timeChange: [{ type: i0.Output, args: ["timeChange"] }] } });
9737
+
9738
+ class DsTreeNodeComponent {
9739
+ // Inputs
9740
+ node = input.required(...(ngDevMode ? [{ debugName: "node" }] : []));
9741
+ level = input(0, ...(ngDevMode ? [{ debugName: "level" }] : []));
9742
+ selectable = input(true, ...(ngDevMode ? [{ debugName: "selectable" }] : []));
9743
+ checkable = input(false, ...(ngDevMode ? [{ debugName: "checkable" }] : []));
9744
+ showIcon = input(true, ...(ngDevMode ? [{ debugName: "showIcon" }] : []));
9745
+ selectedNodeId = input(null, ...(ngDevMode ? [{ debugName: "selectedNodeId" }] : []));
9746
+ expandedNodeIds = input(new Set(), ...(ngDevMode ? [{ debugName: "expandedNodeIds" }] : []));
9747
+ checkedNodeIds = input(new Set(), ...(ngDevMode ? [{ debugName: "checkedNodeIds" }] : []));
9748
+ getIndeterminateState = input(null, ...(ngDevMode ? [{ debugName: "getIndeterminateState" }] : []));
9749
+ // Outputs
9750
+ nodeClick = output();
9751
+ nodeToggle = output();
9752
+ nodeCheck = output();
9753
+ // Icons
9754
+ collapsedIcon = faChevronRight;
9755
+ expandedIcon = faChevronDown;
9756
+ folderIcon = faFolder;
9757
+ folderOpenIcon = faFolderOpen;
9758
+ fileIcon = faFile;
9759
+ // Computed
9760
+ hasChildren = computed(() => {
9761
+ const children = this.node().children;
9762
+ return !!children && children.length > 0;
9763
+ }, ...(ngDevMode ? [{ debugName: "hasChildren" }] : []));
9764
+ isExpanded = computed(() => {
9765
+ return this.expandedNodeIds().has(this.node().id);
9766
+ }, ...(ngDevMode ? [{ debugName: "isExpanded" }] : []));
9767
+ isSelected = computed(() => {
9768
+ return this.selectedNodeId() === this.node().id;
9769
+ }, ...(ngDevMode ? [{ debugName: "isSelected" }] : []));
9770
+ isChecked = computed(() => {
9771
+ return this.checkedNodeIds().has(this.node().id);
9772
+ }, ...(ngDevMode ? [{ debugName: "isChecked" }] : []));
9773
+ isIndeterminate = computed(() => {
9774
+ const fn = this.getIndeterminateState();
9775
+ return fn ? fn(this.node()) : false;
9776
+ }, ...(ngDevMode ? [{ debugName: "isIndeterminate" }] : []));
9777
+ nodeIcon = computed(() => {
9778
+ const node = this.node();
9779
+ // Custom icon
9780
+ if (node.icon) {
9781
+ // TODO: support custom icons
9782
+ return this.fileIcon;
9783
+ }
9784
+ // Default folder/file icons
9785
+ if (this.hasChildren()) {
9786
+ return this.isExpanded() ? this.folderOpenIcon : this.folderIcon;
9787
+ }
9788
+ return this.fileIcon;
9789
+ }, ...(ngDevMode ? [{ debugName: "nodeIcon" }] : []));
9790
+ handleClick(event) {
9791
+ event.stopPropagation();
9792
+ if (!this.node().disabled && this.selectable()) {
9793
+ this.nodeClick.emit(this.node());
9794
+ }
9795
+ }
9796
+ handleToggle(event) {
9797
+ event.stopPropagation();
9798
+ if (!this.node().disabled) {
9799
+ this.nodeToggle.emit(this.node());
9800
+ }
9801
+ }
9802
+ handleCheck(event) {
9803
+ event.stopPropagation();
9804
+ const checkbox = event.target;
9805
+ if (!this.node().disabled) {
9806
+ this.nodeCheck.emit({ node: this.node(), checked: checkbox.checked });
9807
+ }
9808
+ }
9809
+ handleArrowRight(event) {
9810
+ event.preventDefault();
9811
+ if (this.hasChildren() && !this.isExpanded()) {
9812
+ this.handleToggle(event);
9813
+ }
9814
+ }
9815
+ handleArrowLeft(event) {
9816
+ event.preventDefault();
9817
+ if (this.hasChildren() && this.isExpanded()) {
9818
+ this.handleToggle(event);
9819
+ }
9820
+ }
9821
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTreeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9822
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsTreeNodeComponent, isStandalone: true, selector: "ds-tree-node", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, checkable: { classPropertyName: "checkable", publicName: "checkable", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, selectedNodeId: { classPropertyName: "selectedNodeId", publicName: "selectedNodeId", isSignal: true, isRequired: false, transformFunction: null }, expandedNodeIds: { classPropertyName: "expandedNodeIds", publicName: "expandedNodeIds", isSignal: true, isRequired: false, transformFunction: null }, checkedNodeIds: { classPropertyName: "checkedNodeIds", publicName: "checkedNodeIds", isSignal: true, isRequired: false, transformFunction: null }, getIndeterminateState: { classPropertyName: "getIndeterminateState", publicName: "getIndeterminateState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeClick: "nodeClick", nodeToggle: "nodeToggle", nodeCheck: "nodeCheck" }, ngImport: i0, template: `
9823
+ <div
9824
+ class="ds-tree-node"
9825
+ [class.ds-tree-node--selected]="isSelected()"
9826
+ [class.ds-tree-node--disabled]="node().disabled"
9827
+ [attr.role]="'treeitem'"
9828
+ [attr.aria-selected]="isSelected()"
9829
+ [attr.aria-expanded]="hasChildren() ? isExpanded() : null"
9830
+ [attr.aria-disabled]="node().disabled"
9831
+ [attr.tabindex]="node().disabled ? -1 : 0"
9832
+ (click)="handleClick($event)"
9833
+ (keydown.enter)="handleClick($event)"
9834
+ (keydown.space)="handleClick($event); $event.preventDefault()"
9835
+ (keydown.arrowRight)="handleArrowRight($event)"
9836
+ (keydown.arrowLeft)="handleArrowLeft($event)">
9837
+
9838
+ <div class="ds-tree-node__content" [style.padding-left.px]="level() * 20">
9839
+ <!-- Expand/collapse toggle -->
9840
+ @if (hasChildren()) {
9841
+ <button
9842
+ type="button"
9843
+ class="ds-tree-node__toggle"
9844
+ [attr.aria-label]="isExpanded() ? 'Collapse' : 'Expand'"
9845
+ (click)="handleToggle($event)">
9846
+ <fa-icon
9847
+ [icon]="isExpanded() ? expandedIcon : collapsedIcon"
9848
+ aria-hidden="true">
9849
+ </fa-icon>
9850
+ </button>
9851
+ } @else {
9852
+ <span class="ds-tree-node__toggle-placeholder"></span>
9853
+ }
9854
+
9855
+ <!-- Checkbox (if checkable) -->
9856
+ @if (checkable()) {
9857
+ <input
9858
+ type="checkbox"
9859
+ class="ds-tree-node__checkbox"
9860
+ [checked]="isChecked()"
9861
+ [indeterminate]="isIndeterminate()"
9862
+ [disabled]="node().disabled"
9863
+ (change)="handleCheck($event)"
9864
+ (click)="$event.stopPropagation()">
9865
+ }
9866
+
9867
+ <!-- Icon -->
9868
+ @if (showIcon()) {
9869
+ <fa-icon
9870
+ class="ds-tree-node__icon"
9871
+ [icon]="nodeIcon()"
9872
+ aria-hidden="true">
9873
+ </fa-icon>
9874
+ }
9875
+
9876
+ <!-- Label -->
9877
+ <span class="ds-tree-node__label">{{ node().label }}</span>
9878
+ </div>
9879
+ </div>
9880
+
9881
+ <!-- Children (recursive) -->
9882
+ @if (hasChildren() && isExpanded()) {
9883
+ <div class="ds-tree-node__children" role="group">
9884
+ @for (child of node().children; track child.id) {
9885
+ <ds-tree-node
9886
+ [node]="child"
9887
+ [level]="level() + 1"
9888
+ [selectable]="selectable()"
9889
+ [checkable]="checkable()"
9890
+ [showIcon]="showIcon()"
9891
+ [selectedNodeId]="selectedNodeId()"
9892
+ [expandedNodeIds]="expandedNodeIds()"
9893
+ [checkedNodeIds]="checkedNodeIds()"
9894
+ [getIndeterminateState]="getIndeterminateState()"
9895
+ (nodeClick)="nodeClick.emit($event)"
9896
+ (nodeToggle)="nodeToggle.emit($event)"
9897
+ (nodeCheck)="nodeCheck.emit($event)">
9898
+ </ds-tree-node>
9899
+ }
9900
+ </div>
9901
+ }
9902
+ `, isInline: true, styles: [".ds-tree-node{display:block;cursor:pointer;outline:none}.ds-tree-node__content{display:flex;align-items:center;gap:var(--space-2);padding:var(--tree-node-padding, var(--space-1, .25rem) var(--space-2, .5rem));border-radius:var(--radius-1);transition:background-color .15s ease;-webkit-user-select:none;user-select:none}.ds-tree-node__content:hover:not(.ds-tree-node--disabled .ds-tree-node__content){background-color:var(--tree-node-hover-bg, var(--gray-100))}.ds-tree-node:focus-visible .ds-tree-node__content{box-shadow:0 0 0 2px var(--color-primary)}.ds-tree-node--selected .ds-tree-node__content{background-color:var(--tree-node-selected-bg, var(--blue-100));color:var(--tree-node-selected-text, var(--color-primary))}.ds-tree-node--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ds-tree-node__toggle{display:flex;align-items:center;justify-content:center;width:20px;height:20px;background:transparent;border:none;cursor:pointer;padding:0;color:var(--tree-toggle-color, var(--gray-600));transition:transform .2s ease;outline:none}.ds-tree-node__toggle:hover{color:var(--tree-toggle-hover-color, var(--gray-900))}.ds-tree-node__toggle:focus-visible{box-shadow:0 0 0 2px var(--color-primary);border-radius:var(--radius-1)}.ds-tree-node__toggle fa-icon{font-size:12px}.ds-tree-node__toggle-placeholder{display:inline-block;width:20px;height:20px}.ds-tree-node__checkbox{margin:0;cursor:pointer}.ds-tree-node__checkbox:disabled{cursor:not-allowed}.ds-tree-node__icon{color:var(--tree-icon-color, var(--gray-600));font-size:var(--tree-icon-size, 16px);flex-shrink:0}.ds-tree-node__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:var(--tree-label-font-size, var(--font-size-base))}.ds-tree-node__children{margin-left:0}\n"], dependencies: [{ kind: "component", type: DsTreeNodeComponent, selector: "ds-tree-node", inputs: ["node", "level", "selectable", "checkable", "showIcon", "selectedNodeId", "expandedNodeIds", "checkedNodeIds", "getIndeterminateState"], outputs: ["nodeClick", "nodeToggle", "nodeCheck"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FontAwesomeModule }, { kind: "component", type: i1$1.FaIconComponent, selector: "fa-icon", inputs: ["icon", "title", "animation", "mask", "flip", "size", "pull", "border", "inverse", "symbol", "rotate", "fixedWidth", "transform", "a11yRole"], outputs: ["iconChange", "titleChange", "animationChange", "maskChange", "flipChange", "sizeChange", "pullChange", "borderChange", "inverseChange", "symbolChange", "rotateChange", "fixedWidthChange", "transformChange", "a11yRoleChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9903
+ }
9904
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTreeNodeComponent, decorators: [{
9905
+ type: Component,
9906
+ args: [{ selector: 'ds-tree-node', standalone: true, imports: [CommonModule, FontAwesomeModule, DsTreeNodeComponent], template: `
9907
+ <div
9908
+ class="ds-tree-node"
9909
+ [class.ds-tree-node--selected]="isSelected()"
9910
+ [class.ds-tree-node--disabled]="node().disabled"
9911
+ [attr.role]="'treeitem'"
9912
+ [attr.aria-selected]="isSelected()"
9913
+ [attr.aria-expanded]="hasChildren() ? isExpanded() : null"
9914
+ [attr.aria-disabled]="node().disabled"
9915
+ [attr.tabindex]="node().disabled ? -1 : 0"
9916
+ (click)="handleClick($event)"
9917
+ (keydown.enter)="handleClick($event)"
9918
+ (keydown.space)="handleClick($event); $event.preventDefault()"
9919
+ (keydown.arrowRight)="handleArrowRight($event)"
9920
+ (keydown.arrowLeft)="handleArrowLeft($event)">
9921
+
9922
+ <div class="ds-tree-node__content" [style.padding-left.px]="level() * 20">
9923
+ <!-- Expand/collapse toggle -->
9924
+ @if (hasChildren()) {
9925
+ <button
9926
+ type="button"
9927
+ class="ds-tree-node__toggle"
9928
+ [attr.aria-label]="isExpanded() ? 'Collapse' : 'Expand'"
9929
+ (click)="handleToggle($event)">
9930
+ <fa-icon
9931
+ [icon]="isExpanded() ? expandedIcon : collapsedIcon"
9932
+ aria-hidden="true">
9933
+ </fa-icon>
9934
+ </button>
9935
+ } @else {
9936
+ <span class="ds-tree-node__toggle-placeholder"></span>
9937
+ }
9938
+
9939
+ <!-- Checkbox (if checkable) -->
9940
+ @if (checkable()) {
9941
+ <input
9942
+ type="checkbox"
9943
+ class="ds-tree-node__checkbox"
9944
+ [checked]="isChecked()"
9945
+ [indeterminate]="isIndeterminate()"
9946
+ [disabled]="node().disabled"
9947
+ (change)="handleCheck($event)"
9948
+ (click)="$event.stopPropagation()">
9949
+ }
9950
+
9951
+ <!-- Icon -->
9952
+ @if (showIcon()) {
9953
+ <fa-icon
9954
+ class="ds-tree-node__icon"
9955
+ [icon]="nodeIcon()"
9956
+ aria-hidden="true">
9957
+ </fa-icon>
9958
+ }
9959
+
9960
+ <!-- Label -->
9961
+ <span class="ds-tree-node__label">{{ node().label }}</span>
9962
+ </div>
9963
+ </div>
9964
+
9965
+ <!-- Children (recursive) -->
9966
+ @if (hasChildren() && isExpanded()) {
9967
+ <div class="ds-tree-node__children" role="group">
9968
+ @for (child of node().children; track child.id) {
9969
+ <ds-tree-node
9970
+ [node]="child"
9971
+ [level]="level() + 1"
9972
+ [selectable]="selectable()"
9973
+ [checkable]="checkable()"
9974
+ [showIcon]="showIcon()"
9975
+ [selectedNodeId]="selectedNodeId()"
9976
+ [expandedNodeIds]="expandedNodeIds()"
9977
+ [checkedNodeIds]="checkedNodeIds()"
9978
+ [getIndeterminateState]="getIndeterminateState()"
9979
+ (nodeClick)="nodeClick.emit($event)"
9980
+ (nodeToggle)="nodeToggle.emit($event)"
9981
+ (nodeCheck)="nodeCheck.emit($event)">
9982
+ </ds-tree-node>
9983
+ }
9984
+ </div>
9985
+ }
9986
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ds-tree-node{display:block;cursor:pointer;outline:none}.ds-tree-node__content{display:flex;align-items:center;gap:var(--space-2);padding:var(--tree-node-padding, var(--space-1, .25rem) var(--space-2, .5rem));border-radius:var(--radius-1);transition:background-color .15s ease;-webkit-user-select:none;user-select:none}.ds-tree-node__content:hover:not(.ds-tree-node--disabled .ds-tree-node__content){background-color:var(--tree-node-hover-bg, var(--gray-100))}.ds-tree-node:focus-visible .ds-tree-node__content{box-shadow:0 0 0 2px var(--color-primary)}.ds-tree-node--selected .ds-tree-node__content{background-color:var(--tree-node-selected-bg, var(--blue-100));color:var(--tree-node-selected-text, var(--color-primary))}.ds-tree-node--disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.ds-tree-node__toggle{display:flex;align-items:center;justify-content:center;width:20px;height:20px;background:transparent;border:none;cursor:pointer;padding:0;color:var(--tree-toggle-color, var(--gray-600));transition:transform .2s ease;outline:none}.ds-tree-node__toggle:hover{color:var(--tree-toggle-hover-color, var(--gray-900))}.ds-tree-node__toggle:focus-visible{box-shadow:0 0 0 2px var(--color-primary);border-radius:var(--radius-1)}.ds-tree-node__toggle fa-icon{font-size:12px}.ds-tree-node__toggle-placeholder{display:inline-block;width:20px;height:20px}.ds-tree-node__checkbox{margin:0;cursor:pointer}.ds-tree-node__checkbox:disabled{cursor:not-allowed}.ds-tree-node__icon{color:var(--tree-icon-color, var(--gray-600));font-size:var(--tree-icon-size, 16px);flex-shrink:0}.ds-tree-node__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:var(--tree-label-font-size, var(--font-size-base))}.ds-tree-node__children{margin-left:0}\n"] }]
9987
+ }], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], checkable: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkable", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], selectedNodeId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedNodeId", required: false }] }], expandedNodeIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedNodeIds", required: false }] }], checkedNodeIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkedNodeIds", required: false }] }], getIndeterminateState: [{ type: i0.Input, args: [{ isSignal: true, alias: "getIndeterminateState", required: false }] }], nodeClick: [{ type: i0.Output, args: ["nodeClick"] }], nodeToggle: [{ type: i0.Output, args: ["nodeToggle"] }], nodeCheck: [{ type: i0.Output, args: ["nodeCheck"] }] } });
9988
+
9989
+ /**
9990
+ * DsTree - Composant d'affichage hiérarchique
9991
+ *
9992
+ * @description
9993
+ * Arbre hiérarchique avec support de sélection, checkbox,
9994
+ * expand/collapse, et navigation clavier.
9995
+ *
9996
+ * @example
9997
+ * ```html
9998
+ * <ds-tree
9999
+ * [data]="treeData"
10000
+ * [selectable]="true"
10001
+ * (nodeSelect)="onNodeSelect($event)">
10002
+ * </ds-tree>
10003
+ * ```
10004
+ */
10005
+ class DsTree {
10006
+ // Inputs
10007
+ data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
10008
+ selectable = input(true, ...(ngDevMode ? [{ debugName: "selectable" }] : []));
10009
+ checkable = input(false, ...(ngDevMode ? [{ debugName: "checkable" }] : []));
10010
+ expandAll = input(false, ...(ngDevMode ? [{ debugName: "expandAll" }] : []));
10011
+ showIcon = input(true, ...(ngDevMode ? [{ debugName: "showIcon" }] : []));
10012
+ showLine = input(false, ...(ngDevMode ? [{ debugName: "showLine" }] : []));
10013
+ draggable = input(false, ...(ngDevMode ? [{ debugName: "draggable" }] : []));
10014
+ virtualScroll = input(false, ...(ngDevMode ? [{ debugName: "virtualScroll" }] : []));
10015
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
10016
+ loadChildren = input(null, ...(ngDevMode ? [{ debugName: "loadChildren" }] : []));
10017
+ // Outputs
10018
+ nodeSelect = output();
10019
+ nodeExpand = output();
10020
+ nodeCheck = output();
10021
+ // State
10022
+ selectedNodeId = signal(null, ...(ngDevMode ? [{ debugName: "selectedNodeId" }] : []));
10023
+ expandedNodeIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedNodeIds" }] : []));
10024
+ checkedNodeIds = signal(new Set(), ...(ngDevMode ? [{ debugName: "checkedNodeIds" }] : []));
10025
+ // Computed
10026
+ containerClasses = computed(() => {
10027
+ const classes = ['ds-tree'];
10028
+ classes.push(`ds-tree--${this.size()}`);
10029
+ if (this.showLine())
10030
+ classes.push('ds-tree--with-lines');
10031
+ if (this.checkable())
10032
+ classes.push('ds-tree--checkable');
10033
+ return classes.join(' ');
10034
+ }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
10035
+ processedData = computed(() => {
10036
+ const data = this.data();
10037
+ if (this.expandAll()) {
10038
+ this.expandAllNodes(data);
10039
+ }
10040
+ return data;
10041
+ }, ...(ngDevMode ? [{ debugName: "processedData" }] : []));
10042
+ constructor() {
10043
+ // Initialize expanded state from data
10044
+ this.initializeExpandedState();
10045
+ }
10046
+ onNodeClick(node) {
10047
+ if (node.disabled || !this.selectable())
10048
+ return;
10049
+ this.selectedNodeId.set(node.id);
10050
+ this.nodeSelect.emit({ node, selected: true });
10051
+ }
10052
+ onNodeToggle(node) {
10053
+ if (node.disabled)
10054
+ return;
10055
+ const expanded = !this.isExpanded(node.id);
10056
+ this.toggleExpand(node.id, expanded);
10057
+ this.nodeExpand.emit({ node, expanded });
10058
+ // Load children if lazy loading
10059
+ if (expanded && this.loadChildren()) {
10060
+ const loader = this.loadChildren();
10061
+ if (loader) {
10062
+ loader(node).then((children) => {
10063
+ node.children = children;
10064
+ });
10065
+ }
10066
+ }
10067
+ }
10068
+ onNodeCheck(node, checked) {
10069
+ if (node.disabled)
10070
+ return;
10071
+ this.setNodeChecked(node, checked);
10072
+ this.nodeCheck.emit({ node, checked });
10073
+ }
10074
+ isSelected(nodeId) {
10075
+ return this.selectedNodeId() === nodeId;
10076
+ }
10077
+ isExpanded(nodeId) {
10078
+ return this.expandedNodeIds().has(nodeId);
10079
+ }
10080
+ isChecked(nodeId) {
10081
+ return this.checkedNodeIds().has(nodeId);
10082
+ }
10083
+ getIndeterminateState(node) {
10084
+ if (!node.children || node.children.length === 0)
10085
+ return false;
10086
+ const checkedChildren = node.children.filter((child) => this.isChecked(child.id));
10087
+ return checkedChildren.length > 0 && checkedChildren.length < node.children.length;
10088
+ }
10089
+ toggleExpand(nodeId, expanded) {
10090
+ const expandedIds = new Set(this.expandedNodeIds());
10091
+ if (expanded) {
10092
+ expandedIds.add(nodeId);
10093
+ }
10094
+ else {
10095
+ expandedIds.delete(nodeId);
10096
+ }
10097
+ this.expandedNodeIds.set(expandedIds);
10098
+ }
10099
+ setNodeChecked(node, checked) {
10100
+ const checkedIds = new Set(this.checkedNodeIds());
10101
+ // Update current node
10102
+ if (checked) {
10103
+ checkedIds.add(node.id);
10104
+ }
10105
+ else {
10106
+ checkedIds.delete(node.id);
10107
+ }
10108
+ // Update all children recursively
10109
+ if (node.children) {
10110
+ this.updateChildrenChecked(node.children, checked, checkedIds);
10111
+ }
10112
+ this.checkedNodeIds.set(checkedIds);
10113
+ }
10114
+ updateChildrenChecked(children, checked, checkedIds) {
10115
+ children.forEach((child) => {
10116
+ if (!child.disabled) {
10117
+ if (checked) {
10118
+ checkedIds.add(child.id);
10119
+ }
10120
+ else {
10121
+ checkedIds.delete(child.id);
10122
+ }
10123
+ if (child.children) {
10124
+ this.updateChildrenChecked(child.children, checked, checkedIds);
10125
+ }
10126
+ }
10127
+ });
10128
+ }
10129
+ expandAllNodes(nodes) {
10130
+ const expandedIds = new Set(this.expandedNodeIds());
10131
+ const expand = (items) => {
10132
+ items.forEach((item) => {
10133
+ if (item.children && item.children.length > 0) {
10134
+ expandedIds.add(item.id);
10135
+ expand(item.children);
10136
+ }
10137
+ });
10138
+ };
10139
+ expand(nodes);
10140
+ this.expandedNodeIds.set(expandedIds);
10141
+ }
10142
+ initializeExpandedState() {
10143
+ const data = this.data();
10144
+ const expandedIds = new Set();
10145
+ const findExpanded = (nodes) => {
10146
+ nodes.forEach((node) => {
10147
+ if (node.expanded) {
10148
+ expandedIds.add(node.id);
10149
+ }
10150
+ if (node.children) {
10151
+ findExpanded(node.children);
10152
+ }
10153
+ });
10154
+ };
10155
+ findExpanded(data);
10156
+ this.expandedNodeIds.set(expandedIds);
10157
+ }
10158
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTree, deps: [], target: i0.ɵɵFactoryTarget.Component });
10159
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsTree, isStandalone: true, selector: "ds-tree", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, checkable: { classPropertyName: "checkable", publicName: "checkable", isSignal: true, isRequired: false, transformFunction: null }, expandAll: { classPropertyName: "expandAll", publicName: "expandAll", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, showLine: { classPropertyName: "showLine", publicName: "showLine", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, loadChildren: { classPropertyName: "loadChildren", publicName: "loadChildren", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeSelect: "nodeSelect", nodeExpand: "nodeExpand", nodeCheck: "nodeCheck" }, ngImport: i0, template: "<div [class]=\"containerClasses()\" role=\"tree\">\n @if (processedData().length === 0) {\n <div class=\"ds-tree__empty\">\n <p>No data available</p>\n </div>\n } @else {\n @for (node of processedData(); track node.id) {\n <ds-tree-node\n [node]=\"node\"\n [level]=\"0\"\n [selectable]=\"selectable()\"\n [checkable]=\"checkable()\"\n [showIcon]=\"showIcon()\"\n [selectedNodeId]=\"selectedNodeId()\"\n [expandedNodeIds]=\"expandedNodeIds()\"\n [checkedNodeIds]=\"checkedNodeIds()\"\n [getIndeterminateState]=\"getIndeterminateState.bind(this)\"\n (nodeClick)=\"onNodeClick($event)\"\n (nodeToggle)=\"onNodeToggle($event)\"\n (nodeCheck)=\"onNodeCheck($event.node, $event.checked)\">\n </ds-tree-node>\n }\n }\n</div>\n", styles: [".ds-tree{display:block;width:100%;background-color:var(--tree-bg, var(--white));border:1px solid var(--tree-border, var(--gray-300));border-radius:var(--radius-2);padding:var(--space-2);max-height:400px;overflow-y:auto}.ds-tree__empty{display:flex;align-items:center;justify-content:center;padding:var(--space-8);color:var(--text-muted, var(--gray-500));font-size:var(--font-size-sm)}.ds-tree--sm{font-size:var(--font-size-sm);padding:var(--space-1)}.ds-tree--lg{font-size:var(--font-size-lg);padding:var(--space-3)}.ds-tree::-webkit-scrollbar{width:8px}.ds-tree::-webkit-scrollbar-track{background:var(--gray-100);border-radius:var(--radius-1)}.ds-tree::-webkit-scrollbar-thumb{background:var(--gray-400);border-radius:var(--radius-1)}.ds-tree::-webkit-scrollbar-thumb:hover{background:var(--gray-500)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsTreeNodeComponent, selector: "ds-tree-node", inputs: ["node", "level", "selectable", "checkable", "showIcon", "selectedNodeId", "expandedNodeIds", "checkedNodeIds", "getIndeterminateState"], outputs: ["nodeClick", "nodeToggle", "nodeCheck"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10160
+ }
10161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTree, decorators: [{
10162
+ type: Component,
10163
+ args: [{ selector: 'ds-tree', standalone: true, imports: [CommonModule, DsTreeNodeComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"containerClasses()\" role=\"tree\">\n @if (processedData().length === 0) {\n <div class=\"ds-tree__empty\">\n <p>No data available</p>\n </div>\n } @else {\n @for (node of processedData(); track node.id) {\n <ds-tree-node\n [node]=\"node\"\n [level]=\"0\"\n [selectable]=\"selectable()\"\n [checkable]=\"checkable()\"\n [showIcon]=\"showIcon()\"\n [selectedNodeId]=\"selectedNodeId()\"\n [expandedNodeIds]=\"expandedNodeIds()\"\n [checkedNodeIds]=\"checkedNodeIds()\"\n [getIndeterminateState]=\"getIndeterminateState.bind(this)\"\n (nodeClick)=\"onNodeClick($event)\"\n (nodeToggle)=\"onNodeToggle($event)\"\n (nodeCheck)=\"onNodeCheck($event.node, $event.checked)\">\n </ds-tree-node>\n }\n }\n</div>\n", styles: [".ds-tree{display:block;width:100%;background-color:var(--tree-bg, var(--white));border:1px solid var(--tree-border, var(--gray-300));border-radius:var(--radius-2);padding:var(--space-2);max-height:400px;overflow-y:auto}.ds-tree__empty{display:flex;align-items:center;justify-content:center;padding:var(--space-8);color:var(--text-muted, var(--gray-500));font-size:var(--font-size-sm)}.ds-tree--sm{font-size:var(--font-size-sm);padding:var(--space-1)}.ds-tree--lg{font-size:var(--font-size-lg);padding:var(--space-3)}.ds-tree::-webkit-scrollbar{width:8px}.ds-tree::-webkit-scrollbar-track{background:var(--gray-100);border-radius:var(--radius-1)}.ds-tree::-webkit-scrollbar-thumb{background:var(--gray-400);border-radius:var(--radius-1)}.ds-tree::-webkit-scrollbar-thumb:hover{background:var(--gray-500)}\n"] }]
10164
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], checkable: [{ type: i0.Input, args: [{ isSignal: true, alias: "checkable", required: false }] }], expandAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandAll", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], showLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLine", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], loadChildren: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadChildren", required: false }] }], nodeSelect: [{ type: i0.Output, args: ["nodeSelect"] }], nodeExpand: [{ type: i0.Output, args: ["nodeExpand"] }], nodeCheck: [{ type: i0.Output, args: ["nodeCheck"] }] } });
10165
+
8559
10166
  /*
8560
10167
  * Components barrel export
8561
10168
  */
@@ -9127,5 +10734,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
9127
10734
  * Generated bundle index. Do not edit.
9128
10735
  */
9129
10736
 
9130
- export { AUTOCOMPLETE_POSITIONS, BUTTON_APPEARANCE_OPTIONS, BUTTON_SIZE_OPTIONS, BUTTON_VARIANT_OPTIONS, DROPDOWN_POSITIONS, DsAccordion, DsAlert, DsAvatar, DsBadge, DsBreadcrumb, DsButton, DsCard, DsCheckbox, DsChip, DsCombobox, DsContainer, DsDatePicker, DsDivider, DsDropdown, DsFileUpload, DsI18nService, DsInputField, DsInputTextarea, DsMenu, DsModalComponent, DsPagination, DsPopover, DsPopoverComponent, DsProgressBar, DsRadioGroup, DsSearchInput, DsSelect, DsSkeleton, DsSlider, DsStepper, DsTable, DsTabs, DsToastComponent, DsToastContainerComponent, DsToastService, DsToggle, DsTooltip, DsTooltipComponent, IconRegistryService, POPOVER_POSITIONS, PrimitiveBadge, PrimitiveButton, PrimitiveCheckbox, PrimitiveInput, PrimitiveRadio, PrimitiveTextarea, PrimitiveToggle, TOOLTIP_POSITIONS, buildButtonArgTypes, buildButtonArgs, createSizeRender, createVariantRender };
10737
+ export { AUTOCOMPLETE_POSITIONS, BUTTON_APPEARANCE_OPTIONS, BUTTON_SIZE_OPTIONS, BUTTON_VARIANT_OPTIONS, DROPDOWN_POSITIONS, DsAccordion, DsAlert, DsAvatar, DsBadge, DsBreadcrumb, DsButton, DsCard, DsCheckbox, DsChip, DsCombobox, DsContainer, DsDatePicker, DsDivider, DsDrawer, DsDropdown, DsEmpty, DsFileUpload, DsI18nService, DsInputField, DsInputTextarea, DsMenu, DsModalComponent, DsPagination, DsPopover, DsPopoverComponent, DsProgressBar, DsRadioGroup, DsRating, DsSearchInput, DsSelect, DsSkeleton, DsSlider, DsStepper, DsTable, DsTabs, DsTimePicker, DsToastComponent, DsToastContainerComponent, DsToastService, DsToggle, DsTooltip, DsTooltipComponent, DsTree, IconRegistryService, POPOVER_POSITIONS, PrimitiveBadge, PrimitiveButton, PrimitiveCheckbox, PrimitiveInput, PrimitiveRadio, PrimitiveTextarea, PrimitiveToggle, TOOLTIP_POSITIONS, buildButtonArgTypes, buildButtonArgs, createSizeRender, createVariantRender };
9131
10738
  //# sourceMappingURL=kksdev-ds-angular.mjs.map