@kksdev/ds-angular 1.3.0 → 1.5.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.
- package/fesm2022/kksdev-ds-angular.mjs +2889 -14
- package/fesm2022/kksdev-ds-angular.mjs.map +1 -1
- package/index.d.ts +1185 -4
- package/package.json +2 -2
- package/src/styles/themes/_dark.scss +226 -0
- package/src/styles/themes/_light.scss +226 -0
- package/src/styles/tokens/_primitives.scss +8 -0
- package/src/styles/tokens/_semantic.scss +291 -0
- package/src/styles/tokens/_tokens.scss +265 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, Component, output, HostBinding, model, signal, computed, forwardRef, effect, ElementRef, ViewChildren, ViewChild, EventEmitter, inject, HostListener, ContentChild, Output, Directive, DestroyRef, Injectable, ChangeDetectionStrategy, viewChild } from '@angular/core';
|
|
2
|
+
import { input, Component, output, HostBinding, model, signal, computed, forwardRef, effect, ElementRef, ViewChildren, ViewChild, EventEmitter, inject, HostListener, ContentChild, Output, Directive, DestroyRef, Injectable, ChangeDetectionStrategy, viewChild, ViewEncapsulation } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule, DOCUMENT, NgClass } from '@angular/common';
|
|
5
5
|
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, faCircle, faCircleHalfStroke, faTriangleExclamation } 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(
|
|
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(
|
|
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:
|
|
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:
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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,2881 @@ 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
|
+
|
|
10166
|
+
/**
|
|
10167
|
+
* # DsPasswordStrength
|
|
10168
|
+
*
|
|
10169
|
+
* Composant indicateur de force de mot de passe avec affichage visuel
|
|
10170
|
+
* (barres de progression) et optionnel des critères de validation.
|
|
10171
|
+
*
|
|
10172
|
+
* ## Usage
|
|
10173
|
+
*
|
|
10174
|
+
* ```html
|
|
10175
|
+
* <ds-password-strength
|
|
10176
|
+
* [password]="userPassword"
|
|
10177
|
+
* [minLength]="8"
|
|
10178
|
+
* [showLabel]="true"
|
|
10179
|
+
* [showCriteria]="true"
|
|
10180
|
+
* (strengthChange)="handleStrengthChange($event)" />
|
|
10181
|
+
* ```
|
|
10182
|
+
*
|
|
10183
|
+
* ## Calcul de la force
|
|
10184
|
+
*
|
|
10185
|
+
* - `none`: Champ vide
|
|
10186
|
+
* - `weak`: Longueur < minLength OU uniquement lettres
|
|
10187
|
+
* - `medium`: Longueur ≥ minLength ET (lettres+chiffres OU lettres+spéciaux)
|
|
10188
|
+
* - `strong`: Longueur ≥ minLength ET majuscules + minuscules + chiffres + spéciaux
|
|
10189
|
+
*
|
|
10190
|
+
* ## Accessibilité
|
|
10191
|
+
*
|
|
10192
|
+
* - Attribut `role="status"` pour annoncer les changements
|
|
10193
|
+
* - Label ARIA dynamique selon la force
|
|
10194
|
+
* - Couleurs sémantiques (error/warning/success)
|
|
10195
|
+
*
|
|
10196
|
+
* @component
|
|
10197
|
+
*/
|
|
10198
|
+
class DsPasswordStrength {
|
|
10199
|
+
/**
|
|
10200
|
+
* Mot de passe à évaluer.
|
|
10201
|
+
* @default ''
|
|
10202
|
+
*/
|
|
10203
|
+
password = input('', ...(ngDevMode ? [{ debugName: "password" }] : []));
|
|
10204
|
+
/**
|
|
10205
|
+
* Longueur minimale requise.
|
|
10206
|
+
* @default 8
|
|
10207
|
+
*/
|
|
10208
|
+
minLength = input(8, ...(ngDevMode ? [{ debugName: "minLength" }] : []));
|
|
10209
|
+
/**
|
|
10210
|
+
* Afficher le label textuel (ex: "Faible", "Moyen", "Fort").
|
|
10211
|
+
* @default true
|
|
10212
|
+
*/
|
|
10213
|
+
showLabel = input(true, ...(ngDevMode ? [{ debugName: "showLabel" }] : []));
|
|
10214
|
+
/**
|
|
10215
|
+
* Afficher les critères détaillés de validation.
|
|
10216
|
+
* @default false
|
|
10217
|
+
*/
|
|
10218
|
+
showCriteria = input(false, ...(ngDevMode ? [{ debugName: "showCriteria" }] : []));
|
|
10219
|
+
/**
|
|
10220
|
+
* Taille du composant.
|
|
10221
|
+
* @default 'md'
|
|
10222
|
+
*/
|
|
10223
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
10224
|
+
/**
|
|
10225
|
+
* Émis lorsque la force du mot de passe change.
|
|
10226
|
+
*/
|
|
10227
|
+
strengthChange = output();
|
|
10228
|
+
/**
|
|
10229
|
+
* Icônes FontAwesome pour les critères.
|
|
10230
|
+
*/
|
|
10231
|
+
faCheck = faCheck;
|
|
10232
|
+
faTimes = faTimes;
|
|
10233
|
+
/**
|
|
10234
|
+
* Regex patterns pour la validation.
|
|
10235
|
+
*/
|
|
10236
|
+
hasUpperCase = /[A-Z]/;
|
|
10237
|
+
hasLowerCase = /[a-z]/;
|
|
10238
|
+
hasNumber = /[0-9]/;
|
|
10239
|
+
hasSpecialChar = /[^A-Za-z0-9]/;
|
|
10240
|
+
/**
|
|
10241
|
+
* Calcul de la force du mot de passe.
|
|
10242
|
+
*/
|
|
10243
|
+
strength = computed(() => {
|
|
10244
|
+
const pwd = this.password();
|
|
10245
|
+
const minLen = this.minLength();
|
|
10246
|
+
if (!pwd || pwd.length === 0) {
|
|
10247
|
+
return 'none';
|
|
10248
|
+
}
|
|
10249
|
+
const hasUpper = this.hasUpperCase.test(pwd);
|
|
10250
|
+
const hasLower = this.hasLowerCase.test(pwd);
|
|
10251
|
+
const hasNum = this.hasNumber.test(pwd);
|
|
10252
|
+
const hasSpecial = this.hasSpecialChar.test(pwd);
|
|
10253
|
+
const lengthValid = pwd.length >= minLen;
|
|
10254
|
+
// Weak: longueur insuffisante OU uniquement lettres
|
|
10255
|
+
if (!lengthValid) {
|
|
10256
|
+
return 'weak';
|
|
10257
|
+
}
|
|
10258
|
+
const hasLetters = hasUpper || hasLower;
|
|
10259
|
+
const hasOnlyLetters = hasLetters && !hasNum && !hasSpecial;
|
|
10260
|
+
if (hasOnlyLetters) {
|
|
10261
|
+
return 'weak';
|
|
10262
|
+
}
|
|
10263
|
+
// Strong: toutes les catégories présentes
|
|
10264
|
+
if (hasUpper && hasLower && hasNum && hasSpecial) {
|
|
10265
|
+
return 'strong';
|
|
10266
|
+
}
|
|
10267
|
+
// Medium: au moins deux catégories
|
|
10268
|
+
return 'medium';
|
|
10269
|
+
}, ...(ngDevMode ? [{ debugName: "strength" }] : []));
|
|
10270
|
+
/**
|
|
10271
|
+
* Label textuel de la force (pour affichage).
|
|
10272
|
+
*/
|
|
10273
|
+
strengthLabel = computed(() => {
|
|
10274
|
+
const labels = {
|
|
10275
|
+
none: '',
|
|
10276
|
+
weak: 'Faible',
|
|
10277
|
+
medium: 'Moyen',
|
|
10278
|
+
strong: 'Fort',
|
|
10279
|
+
};
|
|
10280
|
+
return labels[this.strength()];
|
|
10281
|
+
}, ...(ngDevMode ? [{ debugName: "strengthLabel" }] : []));
|
|
10282
|
+
/**
|
|
10283
|
+
* Label ARIA pour accessibilité.
|
|
10284
|
+
*/
|
|
10285
|
+
ariaLabel = computed(() => {
|
|
10286
|
+
const str = this.strength();
|
|
10287
|
+
if (str === 'none') {
|
|
10288
|
+
return 'Force du mot de passe : non définie';
|
|
10289
|
+
}
|
|
10290
|
+
return `Force du mot de passe : ${this.strengthLabel()}`;
|
|
10291
|
+
}, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
|
|
10292
|
+
/**
|
|
10293
|
+
* Classes CSS calculées pour le conteneur.
|
|
10294
|
+
*/
|
|
10295
|
+
containerClasses = computed(() => {
|
|
10296
|
+
return [
|
|
10297
|
+
'ds-password-strength',
|
|
10298
|
+
`ds-password-strength--${this.size()}`,
|
|
10299
|
+
`ds-password-strength--${this.strength()}`,
|
|
10300
|
+
].filter(Boolean).join(' ');
|
|
10301
|
+
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
10302
|
+
/**
|
|
10303
|
+
* Barres indicatrices (3 barres).
|
|
10304
|
+
* Chaque barre est active selon la force.
|
|
10305
|
+
*/
|
|
10306
|
+
bars = computed(() => {
|
|
10307
|
+
const str = this.strength();
|
|
10308
|
+
const barCount = 3;
|
|
10309
|
+
const activeCount = {
|
|
10310
|
+
none: 0,
|
|
10311
|
+
weak: 1,
|
|
10312
|
+
medium: 2,
|
|
10313
|
+
strong: 3,
|
|
10314
|
+
};
|
|
10315
|
+
const count = activeCount[str];
|
|
10316
|
+
return Array.from({ length: barCount }, (_, index) => ({
|
|
10317
|
+
active: index < count,
|
|
10318
|
+
level: str,
|
|
10319
|
+
}));
|
|
10320
|
+
}, ...(ngDevMode ? [{ debugName: "bars" }] : []));
|
|
10321
|
+
/**
|
|
10322
|
+
* Liste des critères de validation (pour affichage détaillé).
|
|
10323
|
+
*/
|
|
10324
|
+
criteria = computed(() => {
|
|
10325
|
+
const pwd = this.password();
|
|
10326
|
+
const minLen = this.minLength();
|
|
10327
|
+
return [
|
|
10328
|
+
{
|
|
10329
|
+
key: 'length',
|
|
10330
|
+
label: `Au moins ${minLen} caractères`,
|
|
10331
|
+
valid: pwd.length >= minLen,
|
|
10332
|
+
},
|
|
10333
|
+
{
|
|
10334
|
+
key: 'uppercase',
|
|
10335
|
+
label: 'Contient des majuscules',
|
|
10336
|
+
valid: this.hasUpperCase.test(pwd),
|
|
10337
|
+
},
|
|
10338
|
+
{
|
|
10339
|
+
key: 'lowercase',
|
|
10340
|
+
label: 'Contient des minuscules',
|
|
10341
|
+
valid: this.hasLowerCase.test(pwd),
|
|
10342
|
+
},
|
|
10343
|
+
{
|
|
10344
|
+
key: 'number',
|
|
10345
|
+
label: 'Contient des chiffres',
|
|
10346
|
+
valid: this.hasNumber.test(pwd),
|
|
10347
|
+
},
|
|
10348
|
+
{
|
|
10349
|
+
key: 'special',
|
|
10350
|
+
label: 'Contient des caractères spéciaux',
|
|
10351
|
+
valid: this.hasSpecialChar.test(pwd),
|
|
10352
|
+
},
|
|
10353
|
+
];
|
|
10354
|
+
}, ...(ngDevMode ? [{ debugName: "criteria" }] : []));
|
|
10355
|
+
/**
|
|
10356
|
+
* Constructeur : émet les changements de force via effect.
|
|
10357
|
+
*/
|
|
10358
|
+
constructor() {
|
|
10359
|
+
let previousStrength = 'none';
|
|
10360
|
+
// Émettre strengthChange à chaque changement
|
|
10361
|
+
effect(() => {
|
|
10362
|
+
const currentStrength = this.strength();
|
|
10363
|
+
if (currentStrength !== previousStrength) {
|
|
10364
|
+
previousStrength = currentStrength;
|
|
10365
|
+
this.strengthChange.emit(currentStrength);
|
|
10366
|
+
}
|
|
10367
|
+
});
|
|
10368
|
+
}
|
|
10369
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsPasswordStrength, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10370
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsPasswordStrength, isStandalone: true, selector: "ds-password-strength", inputs: { password: { classPropertyName: "password", publicName: "password", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, showCriteria: { classPropertyName: "showCriteria", publicName: "showCriteria", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { strengthChange: "strengthChange" }, ngImport: i0, template: "<div [ngClass]=\"containerClasses()\" role=\"status\" [attr.aria-label]=\"ariaLabel()\">\n <!-- Barres indicatrices (3 barres) -->\n <div class=\"ds-password-strength__bars\">\n @for (bar of bars(); track $index) {\n <div\n class=\"ds-password-strength__bar\"\n [class.ds-password-strength__bar--active]=\"bar.active\"\n [class.ds-password-strength__bar--weak]=\"bar.active && bar.level === 'weak'\"\n [class.ds-password-strength__bar--medium]=\"bar.active && bar.level === 'medium'\"\n [class.ds-password-strength__bar--strong]=\"bar.active && bar.level === 'strong'\">\n </div>\n }\n </div>\n\n <!-- Label optionnel -->\n @if (showLabel() && strength() !== 'none') {\n <span\n class=\"ds-password-strength__label\"\n [class]=\"'ds-password-strength__label--' + strength()\">\n {{ strengthLabel() }}\n </span>\n }\n\n <!-- Crit\u00E8res d\u00E9taill\u00E9s optionnels -->\n @if (showCriteria()) {\n <ul class=\"ds-password-strength__criteria\">\n @for (criterion of criteria(); track criterion.key) {\n <li\n class=\"ds-password-strength__criterion\"\n [class.ds-password-strength__criterion--valid]=\"criterion.valid\">\n <fa-icon [icon]=\"criterion.valid ? faCheck : faTimes\" />\n <span>{{ criterion.label }}</span>\n </li>\n }\n </ul>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.ds-password-strength{display:flex;flex-direction:column;gap:var(--password-strength-label-gap)}.ds-password-strength__bars{display:flex;gap:var(--password-strength-bar-gap);align-items:center}.ds-password-strength__bar{flex:1;height:var(--password-strength-bar-height-md);background-color:var(--password-strength-bg);border-radius:var(--password-strength-bar-radius);transition:background-color .3s ease}.ds-password-strength__bar--active.ds-password-strength__bar--weak{background-color:var(--password-strength-weak)}.ds-password-strength__bar--active.ds-password-strength__bar--medium{background-color:var(--password-strength-medium)}.ds-password-strength__bar--active.ds-password-strength__bar--strong{background-color:var(--password-strength-strong)}.ds-password-strength__label{font-size:var(--password-strength-label-font-size);color:var(--password-strength-text);font-weight:var(--font-weight-medium);text-align:right}.ds-password-strength__label--weak{color:var(--password-strength-weak)}.ds-password-strength__label--medium{color:var(--password-strength-medium)}.ds-password-strength__label--strong{color:var(--password-strength-strong)}.ds-password-strength__criteria{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-1)}.ds-password-strength__criterion{display:flex;align-items:center;gap:var(--space-2);font-size:var(--font-size-2);color:var(--password-strength-criterion-invalid);transition:color .2s ease}.ds-password-strength__criterion fa-icon{font-size:.875rem}.ds-password-strength__criterion--valid{color:var(--password-strength-criterion-valid)}.ds-password-strength--sm .ds-password-strength__bar{height:var(--password-strength-bar-height-sm)}.ds-password-strength--sm .ds-password-strength__label,.ds-password-strength--sm .ds-password-strength__criterion{font-size:var(--font-size-1)}.ds-password-strength--md .ds-password-strength__bar{height:var(--password-strength-bar-height-md)}.ds-password-strength--md .ds-password-strength__label{font-size:var(--password-strength-label-font-size)}.ds-password-strength--md .ds-password-strength__criterion{font-size:var(--font-size-2)}.ds-password-strength--lg .ds-password-strength__bar{height:var(--password-strength-bar-height-lg)}.ds-password-strength--lg .ds-password-strength__label,.ds-password-strength--lg .ds-password-strength__criterion{font-size:var(--font-size-3)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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"] }] });
|
|
10371
|
+
}
|
|
10372
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsPasswordStrength, decorators: [{
|
|
10373
|
+
type: Component,
|
|
10374
|
+
args: [{ selector: 'ds-password-strength', imports: [CommonModule, FontAwesomeModule], template: "<div [ngClass]=\"containerClasses()\" role=\"status\" [attr.aria-label]=\"ariaLabel()\">\n <!-- Barres indicatrices (3 barres) -->\n <div class=\"ds-password-strength__bars\">\n @for (bar of bars(); track $index) {\n <div\n class=\"ds-password-strength__bar\"\n [class.ds-password-strength__bar--active]=\"bar.active\"\n [class.ds-password-strength__bar--weak]=\"bar.active && bar.level === 'weak'\"\n [class.ds-password-strength__bar--medium]=\"bar.active && bar.level === 'medium'\"\n [class.ds-password-strength__bar--strong]=\"bar.active && bar.level === 'strong'\">\n </div>\n }\n </div>\n\n <!-- Label optionnel -->\n @if (showLabel() && strength() !== 'none') {\n <span\n class=\"ds-password-strength__label\"\n [class]=\"'ds-password-strength__label--' + strength()\">\n {{ strengthLabel() }}\n </span>\n }\n\n <!-- Crit\u00E8res d\u00E9taill\u00E9s optionnels -->\n @if (showCriteria()) {\n <ul class=\"ds-password-strength__criteria\">\n @for (criterion of criteria(); track criterion.key) {\n <li\n class=\"ds-password-strength__criterion\"\n [class.ds-password-strength__criterion--valid]=\"criterion.valid\">\n <fa-icon [icon]=\"criterion.valid ? faCheck : faTimes\" />\n <span>{{ criterion.label }}</span>\n </li>\n }\n </ul>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.ds-password-strength{display:flex;flex-direction:column;gap:var(--password-strength-label-gap)}.ds-password-strength__bars{display:flex;gap:var(--password-strength-bar-gap);align-items:center}.ds-password-strength__bar{flex:1;height:var(--password-strength-bar-height-md);background-color:var(--password-strength-bg);border-radius:var(--password-strength-bar-radius);transition:background-color .3s ease}.ds-password-strength__bar--active.ds-password-strength__bar--weak{background-color:var(--password-strength-weak)}.ds-password-strength__bar--active.ds-password-strength__bar--medium{background-color:var(--password-strength-medium)}.ds-password-strength__bar--active.ds-password-strength__bar--strong{background-color:var(--password-strength-strong)}.ds-password-strength__label{font-size:var(--password-strength-label-font-size);color:var(--password-strength-text);font-weight:var(--font-weight-medium);text-align:right}.ds-password-strength__label--weak{color:var(--password-strength-weak)}.ds-password-strength__label--medium{color:var(--password-strength-medium)}.ds-password-strength__label--strong{color:var(--password-strength-strong)}.ds-password-strength__criteria{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-1)}.ds-password-strength__criterion{display:flex;align-items:center;gap:var(--space-2);font-size:var(--font-size-2);color:var(--password-strength-criterion-invalid);transition:color .2s ease}.ds-password-strength__criterion fa-icon{font-size:.875rem}.ds-password-strength__criterion--valid{color:var(--password-strength-criterion-valid)}.ds-password-strength--sm .ds-password-strength__bar{height:var(--password-strength-bar-height-sm)}.ds-password-strength--sm .ds-password-strength__label,.ds-password-strength--sm .ds-password-strength__criterion{font-size:var(--font-size-1)}.ds-password-strength--md .ds-password-strength__bar{height:var(--password-strength-bar-height-md)}.ds-password-strength--md .ds-password-strength__label{font-size:var(--password-strength-label-font-size)}.ds-password-strength--md .ds-password-strength__criterion{font-size:var(--font-size-2)}.ds-password-strength--lg .ds-password-strength__bar{height:var(--password-strength-bar-height-lg)}.ds-password-strength--lg .ds-password-strength__label,.ds-password-strength--lg .ds-password-strength__criterion{font-size:var(--font-size-3)}\n"] }]
|
|
10375
|
+
}], ctorParameters: () => [], propDecorators: { password: [{ type: i0.Input, args: [{ isSignal: true, alias: "password", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], showCriteria: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCriteria", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], strengthChange: [{ type: i0.Output, args: ["strengthChange"] }] } });
|
|
10376
|
+
|
|
10377
|
+
/**
|
|
10378
|
+
* # DsTimeline
|
|
10379
|
+
*
|
|
10380
|
+
* Composant pour afficher une liste d'événements dans un ordre chronologique vertical.
|
|
10381
|
+
*
|
|
10382
|
+
* ## Usage
|
|
10383
|
+
*
|
|
10384
|
+
* ```html
|
|
10385
|
+
* <ds-timeline
|
|
10386
|
+
* [items]="events"
|
|
10387
|
+
* mode="left"
|
|
10388
|
+
* size="md"
|
|
10389
|
+
* [pending]="false"
|
|
10390
|
+
* (itemClick)="onItemClick($event)">
|
|
10391
|
+
* </ds-timeline>
|
|
10392
|
+
* ```
|
|
10393
|
+
*
|
|
10394
|
+
* ## Modes
|
|
10395
|
+
*
|
|
10396
|
+
* - `left` : Contenu aligné à droite de la ligne
|
|
10397
|
+
* - `right` : Contenu aligné à gauche de la ligne
|
|
10398
|
+
* - `alternate` : Contenu alterné gauche/droite
|
|
10399
|
+
*
|
|
10400
|
+
* ## Accessibilité
|
|
10401
|
+
*
|
|
10402
|
+
* - Liste sémantique avec `role="list"` et `role="listitem"`
|
|
10403
|
+
* - Dates et contenus avec attributs ARIA
|
|
10404
|
+
* - Navigation clavier supportée
|
|
10405
|
+
*
|
|
10406
|
+
* @component
|
|
10407
|
+
*/
|
|
10408
|
+
class DsTimeline {
|
|
10409
|
+
/**
|
|
10410
|
+
* Liste des événements à afficher.
|
|
10411
|
+
*/
|
|
10412
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
10413
|
+
/**
|
|
10414
|
+
* Mode d'affichage (position du contenu).
|
|
10415
|
+
* @default 'left'
|
|
10416
|
+
*/
|
|
10417
|
+
mode = input('left', ...(ngDevMode ? [{ debugName: "mode" }] : []));
|
|
10418
|
+
/**
|
|
10419
|
+
* Taille du composant.
|
|
10420
|
+
* @default 'md'
|
|
10421
|
+
*/
|
|
10422
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
10423
|
+
/**
|
|
10424
|
+
* Affiche un indicateur "en cours" à la fin.
|
|
10425
|
+
* @default false
|
|
10426
|
+
*/
|
|
10427
|
+
pending = input(false, ...(ngDevMode ? [{ debugName: "pending" }] : []));
|
|
10428
|
+
/**
|
|
10429
|
+
* Texte de l'indicateur pending.
|
|
10430
|
+
* @default 'En cours...'
|
|
10431
|
+
*/
|
|
10432
|
+
pendingContent = input('En cours...', ...(ngDevMode ? [{ debugName: "pendingContent" }] : []));
|
|
10433
|
+
/**
|
|
10434
|
+
* Inverse l'ordre d'affichage (plus récent en haut).
|
|
10435
|
+
* @default false
|
|
10436
|
+
*/
|
|
10437
|
+
reverse = input(false, ...(ngDevMode ? [{ debugName: "reverse" }] : []));
|
|
10438
|
+
/**
|
|
10439
|
+
* Événement émis au clic sur un item.
|
|
10440
|
+
*/
|
|
10441
|
+
itemClick = output();
|
|
10442
|
+
/**
|
|
10443
|
+
* Icônes par défaut.
|
|
10444
|
+
*/
|
|
10445
|
+
defaultIcon = faCircle;
|
|
10446
|
+
pendingIcon = faCircleHalfStroke;
|
|
10447
|
+
/**
|
|
10448
|
+
* Items triés (reverse si demandé).
|
|
10449
|
+
*/
|
|
10450
|
+
sortedItems = computed(() => {
|
|
10451
|
+
const items = [...this.items()];
|
|
10452
|
+
return this.reverse() ? items.reverse() : items;
|
|
10453
|
+
}, ...(ngDevMode ? [{ debugName: "sortedItems" }] : []));
|
|
10454
|
+
/**
|
|
10455
|
+
* Classes CSS du conteneur.
|
|
10456
|
+
*/
|
|
10457
|
+
containerClasses = computed(() => {
|
|
10458
|
+
return [
|
|
10459
|
+
'ds-timeline',
|
|
10460
|
+
`ds-timeline--${this.mode()}`,
|
|
10461
|
+
`ds-timeline--${this.size()}`,
|
|
10462
|
+
].filter(Boolean);
|
|
10463
|
+
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
10464
|
+
/**
|
|
10465
|
+
* Classes CSS pour un item.
|
|
10466
|
+
*/
|
|
10467
|
+
getItemClasses(item, index) {
|
|
10468
|
+
const position = this.getItemPosition(index);
|
|
10469
|
+
return [
|
|
10470
|
+
'ds-timeline__item',
|
|
10471
|
+
`ds-timeline__item--${position}`,
|
|
10472
|
+
item.color ? `ds-timeline__item--${item.color}` : 'ds-timeline__item--default',
|
|
10473
|
+
].filter(Boolean);
|
|
10474
|
+
}
|
|
10475
|
+
/**
|
|
10476
|
+
* Classes CSS pour le point d'un item.
|
|
10477
|
+
*/
|
|
10478
|
+
getDotClasses(item) {
|
|
10479
|
+
return [
|
|
10480
|
+
'ds-timeline__dot',
|
|
10481
|
+
item.icon ? 'ds-timeline__dot--with-icon' : '',
|
|
10482
|
+
item.color ? `ds-timeline__dot--${item.color}` : 'ds-timeline__dot--default',
|
|
10483
|
+
].filter(Boolean);
|
|
10484
|
+
}
|
|
10485
|
+
/**
|
|
10486
|
+
* Détermine la position d'un item en fonction du mode.
|
|
10487
|
+
*/
|
|
10488
|
+
getItemPosition(index) {
|
|
10489
|
+
const mode = this.mode();
|
|
10490
|
+
if (mode === 'left')
|
|
10491
|
+
return 'right'; // Contenu à droite de la ligne
|
|
10492
|
+
if (mode === 'right')
|
|
10493
|
+
return 'left'; // Contenu à gauche de la ligne
|
|
10494
|
+
// Mode alternate : alterner selon l'index
|
|
10495
|
+
return index % 2 === 0 ? 'right' : 'left';
|
|
10496
|
+
}
|
|
10497
|
+
/**
|
|
10498
|
+
* Gère le clic sur un item.
|
|
10499
|
+
*/
|
|
10500
|
+
handleItemClick(item, index) {
|
|
10501
|
+
this.itemClick.emit({ item, index });
|
|
10502
|
+
}
|
|
10503
|
+
/**
|
|
10504
|
+
* Gère la touche Enter/Space sur un item.
|
|
10505
|
+
*/
|
|
10506
|
+
handleKeydown(event, item, index) {
|
|
10507
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
10508
|
+
event.preventDefault();
|
|
10509
|
+
this.handleItemClick(item, index);
|
|
10510
|
+
}
|
|
10511
|
+
}
|
|
10512
|
+
/**
|
|
10513
|
+
* Icône à afficher pour un item.
|
|
10514
|
+
*/
|
|
10515
|
+
getIcon(item) {
|
|
10516
|
+
return item.icon || this.defaultIcon;
|
|
10517
|
+
}
|
|
10518
|
+
/**
|
|
10519
|
+
* Vérifie si c'est le dernier item.
|
|
10520
|
+
*/
|
|
10521
|
+
isLastItem(index) {
|
|
10522
|
+
return index === this.sortedItems().length - 1;
|
|
10523
|
+
}
|
|
10524
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTimeline, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10525
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsTimeline, isStandalone: true, selector: "ds-timeline", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, pending: { classPropertyName: "pending", publicName: "pending", isSignal: true, isRequired: false, transformFunction: null }, pendingContent: { classPropertyName: "pendingContent", publicName: "pendingContent", isSignal: true, isRequired: false, transformFunction: null }, reverse: { classPropertyName: "reverse", publicName: "reverse", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, ngImport: i0, template: "<div [ngClass]=\"containerClasses()\" role=\"list\" aria-label=\"Timeline\">\n @for (item of sortedItems(); track $index) {\n <div\n [ngClass]=\"getItemClasses(item, $index)\"\n role=\"listitem\"\n tabindex=\"0\"\n (click)=\"handleItemClick(item, $index)\"\n (keydown)=\"handleKeydown($event, item, $index)\"\n [class.ds-timeline__item--last]=\"isLastItem($index) && !pending()\">\n\n <!-- Point de la timeline -->\n <div [ngClass]=\"getDotClasses(item)\" [attr.aria-label]=\"item.date || '\u00C9v\u00E9nement'\">\n @if (item.icon) {\n <fa-icon [icon]=\"getIcon(item)\" class=\"ds-timeline__icon\" aria-hidden=\"true\"></fa-icon>\n }\n </div>\n\n <!-- Ligne de connexion -->\n @if (!isLastItem($index) || pending()) {\n <div class=\"ds-timeline__line\" aria-hidden=\"true\"></div>\n }\n\n <!-- Contenu -->\n <div class=\"ds-timeline__content\">\n @if (item.date) {\n <div class=\"ds-timeline__date\">{{ item.date }}</div>\n }\n <div class=\"ds-timeline__text\">{{ item.content }}</div>\n </div>\n </div>\n }\n\n <!-- Indicateur pending -->\n @if (pending()) {\n <div\n class=\"ds-timeline__item ds-timeline__item--pending ds-timeline__item--{{ getItemPosition(sortedItems().length) }}\"\n role=\"listitem\">\n <div class=\"ds-timeline__dot ds-timeline__dot--pending ds-timeline__dot--with-icon\">\n <fa-icon [icon]=\"pendingIcon\" class=\"ds-timeline__icon ds-timeline__icon--pending\" aria-hidden=\"true\"></fa-icon>\n </div>\n <div class=\"ds-timeline__content\">\n <div class=\"ds-timeline__text ds-timeline__text--pending\">{{ pendingContent() }}</div>\n </div>\n </div>\n }\n</div>\n", styles: [".ds-timeline{display:flex;flex-direction:column;position:relative;width:100%}.ds-timeline__item{position:relative;display:grid;padding-bottom:var(--timeline-item-gap);cursor:pointer;transition:opacity .2s ease}.ds-timeline__item:focus{outline:2px solid var(--color-primary);outline-offset:2px;border-radius:var(--radius-1)}.ds-timeline__item:focus-visible{outline:2px solid var(--color-primary)}.ds-timeline__item--last{padding-bottom:0}.ds-timeline__item--pending{cursor:default;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}.ds-timeline--left .ds-timeline__item{grid-template-columns:auto 1fr;grid-template-areas:\"dot content\" \"line content\"}.ds-timeline--right .ds-timeline__item{grid-template-columns:1fr auto;grid-template-areas:\"content dot\" \"content line\";text-align:right}.ds-timeline--right .ds-timeline__item .ds-timeline__content{padding-left:0;padding-right:var(--timeline-content-gap)}.ds-timeline--alternate .ds-timeline__item--left{grid-template-columns:1fr auto;grid-template-areas:\"content dot\" \"content line\";text-align:right}.ds-timeline--alternate .ds-timeline__item--left .ds-timeline__content{padding-left:0;padding-right:var(--timeline-content-gap)}.ds-timeline--alternate .ds-timeline__item--right{grid-template-columns:auto 1fr;grid-template-areas:\"dot content\" \"line content\"}.ds-timeline__dot{grid-area:dot;width:var(--timeline-dot-size);height:var(--timeline-dot-size);border-radius:50%;border:var(--timeline-dot-border-width) solid var(--timeline-dot-border-color);background:var(--timeline-dot-bg);display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:2;transition:all .3s ease}.ds-timeline__dot--default{background:var(--timeline-dot-bg-default);border-color:var(--timeline-dot-border-default)}.ds-timeline__dot--primary{background:var(--timeline-dot-bg-primary);border-color:var(--timeline-dot-border-primary)}.ds-timeline__dot--success{background:var(--timeline-dot-bg-success);border-color:var(--timeline-dot-border-success)}.ds-timeline__dot--warning{background:var(--timeline-dot-bg-warning);border-color:var(--timeline-dot-border-warning)}.ds-timeline__dot--error{background:var(--timeline-dot-bg-error);border-color:var(--timeline-dot-border-error)}.ds-timeline__dot--info{background:var(--timeline-dot-bg-info);border-color:var(--timeline-dot-border-info)}.ds-timeline__dot--pending{background:var(--timeline-dot-bg-pending);border-color:var(--timeline-dot-border-pending)}.ds-timeline__dot--with-icon{background:transparent;border:none}.ds-timeline__item:hover .ds-timeline__dot{transform:scale(1.1)}.ds-timeline__icon{font-size:var(--timeline-icon-size);color:var(--timeline-icon-color)}.ds-timeline__icon--pending{color:var(--timeline-icon-color-pending);animation:spin 2s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ds-timeline__line{grid-area:line;width:var(--timeline-line-width);background:var(--timeline-line-color);justify-self:center;flex:1;min-height:var(--timeline-item-gap);margin-top:4px}.ds-timeline__content{grid-area:content;padding-left:var(--timeline-content-gap);display:flex;flex-direction:column;gap:var(--timeline-content-inner-gap);min-width:0}.ds-timeline__date{font-size:var(--timeline-date-font-size);color:var(--timeline-date-color);font-weight:500}.ds-timeline__text{font-size:var(--timeline-text-font-size);color:var(--timeline-text-color);line-height:1.5}.ds-timeline__text--pending{color:var(--timeline-text-color-pending);font-style:italic}.ds-timeline--sm{--timeline-dot-size: var(--timeline-dot-size-sm);--timeline-line-width: var(--timeline-line-width-sm);--timeline-item-gap: var(--timeline-item-gap-sm);--timeline-content-gap: var(--timeline-content-gap-sm);--timeline-content-inner-gap: var(--timeline-content-inner-gap-sm);--timeline-date-font-size: var(--timeline-date-font-size-sm);--timeline-text-font-size: var(--timeline-text-font-size-sm);--timeline-icon-size: var(--timeline-icon-size-sm)}.ds-timeline--md{--timeline-dot-size: var(--timeline-dot-size-md);--timeline-line-width: var(--timeline-line-width-md);--timeline-item-gap: var(--timeline-item-gap-md);--timeline-content-gap: var(--timeline-content-gap-md);--timeline-content-inner-gap: var(--timeline-content-inner-gap-md);--timeline-date-font-size: var(--timeline-date-font-size-md);--timeline-text-font-size: var(--timeline-text-font-size-md);--timeline-icon-size: var(--timeline-icon-size-md)}.ds-timeline--lg{--timeline-dot-size: var(--timeline-dot-size-lg);--timeline-line-width: var(--timeline-line-width-lg);--timeline-item-gap: var(--timeline-item-gap-lg);--timeline-content-gap: var(--timeline-content-gap-lg);--timeline-content-inner-gap: var(--timeline-content-inner-gap-lg);--timeline-date-font-size: var(--timeline-date-font-size-lg);--timeline-text-font-size: var(--timeline-text-font-size-lg);--timeline-icon-size: var(--timeline-icon-size-lg)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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"] }] });
|
|
10526
|
+
}
|
|
10527
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTimeline, decorators: [{
|
|
10528
|
+
type: Component,
|
|
10529
|
+
args: [{ selector: 'ds-timeline', imports: [CommonModule, FontAwesomeModule], template: "<div [ngClass]=\"containerClasses()\" role=\"list\" aria-label=\"Timeline\">\n @for (item of sortedItems(); track $index) {\n <div\n [ngClass]=\"getItemClasses(item, $index)\"\n role=\"listitem\"\n tabindex=\"0\"\n (click)=\"handleItemClick(item, $index)\"\n (keydown)=\"handleKeydown($event, item, $index)\"\n [class.ds-timeline__item--last]=\"isLastItem($index) && !pending()\">\n\n <!-- Point de la timeline -->\n <div [ngClass]=\"getDotClasses(item)\" [attr.aria-label]=\"item.date || '\u00C9v\u00E9nement'\">\n @if (item.icon) {\n <fa-icon [icon]=\"getIcon(item)\" class=\"ds-timeline__icon\" aria-hidden=\"true\"></fa-icon>\n }\n </div>\n\n <!-- Ligne de connexion -->\n @if (!isLastItem($index) || pending()) {\n <div class=\"ds-timeline__line\" aria-hidden=\"true\"></div>\n }\n\n <!-- Contenu -->\n <div class=\"ds-timeline__content\">\n @if (item.date) {\n <div class=\"ds-timeline__date\">{{ item.date }}</div>\n }\n <div class=\"ds-timeline__text\">{{ item.content }}</div>\n </div>\n </div>\n }\n\n <!-- Indicateur pending -->\n @if (pending()) {\n <div\n class=\"ds-timeline__item ds-timeline__item--pending ds-timeline__item--{{ getItemPosition(sortedItems().length) }}\"\n role=\"listitem\">\n <div class=\"ds-timeline__dot ds-timeline__dot--pending ds-timeline__dot--with-icon\">\n <fa-icon [icon]=\"pendingIcon\" class=\"ds-timeline__icon ds-timeline__icon--pending\" aria-hidden=\"true\"></fa-icon>\n </div>\n <div class=\"ds-timeline__content\">\n <div class=\"ds-timeline__text ds-timeline__text--pending\">{{ pendingContent() }}</div>\n </div>\n </div>\n }\n</div>\n", styles: [".ds-timeline{display:flex;flex-direction:column;position:relative;width:100%}.ds-timeline__item{position:relative;display:grid;padding-bottom:var(--timeline-item-gap);cursor:pointer;transition:opacity .2s ease}.ds-timeline__item:focus{outline:2px solid var(--color-primary);outline-offset:2px;border-radius:var(--radius-1)}.ds-timeline__item:focus-visible{outline:2px solid var(--color-primary)}.ds-timeline__item--last{padding-bottom:0}.ds-timeline__item--pending{cursor:default;animation:pulse 2s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.7}}.ds-timeline--left .ds-timeline__item{grid-template-columns:auto 1fr;grid-template-areas:\"dot content\" \"line content\"}.ds-timeline--right .ds-timeline__item{grid-template-columns:1fr auto;grid-template-areas:\"content dot\" \"content line\";text-align:right}.ds-timeline--right .ds-timeline__item .ds-timeline__content{padding-left:0;padding-right:var(--timeline-content-gap)}.ds-timeline--alternate .ds-timeline__item--left{grid-template-columns:1fr auto;grid-template-areas:\"content dot\" \"content line\";text-align:right}.ds-timeline--alternate .ds-timeline__item--left .ds-timeline__content{padding-left:0;padding-right:var(--timeline-content-gap)}.ds-timeline--alternate .ds-timeline__item--right{grid-template-columns:auto 1fr;grid-template-areas:\"dot content\" \"line content\"}.ds-timeline__dot{grid-area:dot;width:var(--timeline-dot-size);height:var(--timeline-dot-size);border-radius:50%;border:var(--timeline-dot-border-width) solid var(--timeline-dot-border-color);background:var(--timeline-dot-bg);display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;z-index:2;transition:all .3s ease}.ds-timeline__dot--default{background:var(--timeline-dot-bg-default);border-color:var(--timeline-dot-border-default)}.ds-timeline__dot--primary{background:var(--timeline-dot-bg-primary);border-color:var(--timeline-dot-border-primary)}.ds-timeline__dot--success{background:var(--timeline-dot-bg-success);border-color:var(--timeline-dot-border-success)}.ds-timeline__dot--warning{background:var(--timeline-dot-bg-warning);border-color:var(--timeline-dot-border-warning)}.ds-timeline__dot--error{background:var(--timeline-dot-bg-error);border-color:var(--timeline-dot-border-error)}.ds-timeline__dot--info{background:var(--timeline-dot-bg-info);border-color:var(--timeline-dot-border-info)}.ds-timeline__dot--pending{background:var(--timeline-dot-bg-pending);border-color:var(--timeline-dot-border-pending)}.ds-timeline__dot--with-icon{background:transparent;border:none}.ds-timeline__item:hover .ds-timeline__dot{transform:scale(1.1)}.ds-timeline__icon{font-size:var(--timeline-icon-size);color:var(--timeline-icon-color)}.ds-timeline__icon--pending{color:var(--timeline-icon-color-pending);animation:spin 2s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ds-timeline__line{grid-area:line;width:var(--timeline-line-width);background:var(--timeline-line-color);justify-self:center;flex:1;min-height:var(--timeline-item-gap);margin-top:4px}.ds-timeline__content{grid-area:content;padding-left:var(--timeline-content-gap);display:flex;flex-direction:column;gap:var(--timeline-content-inner-gap);min-width:0}.ds-timeline__date{font-size:var(--timeline-date-font-size);color:var(--timeline-date-color);font-weight:500}.ds-timeline__text{font-size:var(--timeline-text-font-size);color:var(--timeline-text-color);line-height:1.5}.ds-timeline__text--pending{color:var(--timeline-text-color-pending);font-style:italic}.ds-timeline--sm{--timeline-dot-size: var(--timeline-dot-size-sm);--timeline-line-width: var(--timeline-line-width-sm);--timeline-item-gap: var(--timeline-item-gap-sm);--timeline-content-gap: var(--timeline-content-gap-sm);--timeline-content-inner-gap: var(--timeline-content-inner-gap-sm);--timeline-date-font-size: var(--timeline-date-font-size-sm);--timeline-text-font-size: var(--timeline-text-font-size-sm);--timeline-icon-size: var(--timeline-icon-size-sm)}.ds-timeline--md{--timeline-dot-size: var(--timeline-dot-size-md);--timeline-line-width: var(--timeline-line-width-md);--timeline-item-gap: var(--timeline-item-gap-md);--timeline-content-gap: var(--timeline-content-gap-md);--timeline-content-inner-gap: var(--timeline-content-inner-gap-md);--timeline-date-font-size: var(--timeline-date-font-size-md);--timeline-text-font-size: var(--timeline-text-font-size-md);--timeline-icon-size: var(--timeline-icon-size-md)}.ds-timeline--lg{--timeline-dot-size: var(--timeline-dot-size-lg);--timeline-line-width: var(--timeline-line-width-lg);--timeline-item-gap: var(--timeline-item-gap-lg);--timeline-content-gap: var(--timeline-content-gap-lg);--timeline-content-inner-gap: var(--timeline-content-inner-gap-lg);--timeline-date-font-size: var(--timeline-date-font-size-lg);--timeline-text-font-size: var(--timeline-text-font-size-lg);--timeline-icon-size: var(--timeline-icon-size-lg)}\n"] }]
|
|
10530
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], pending: [{ type: i0.Input, args: [{ isSignal: true, alias: "pending", required: false }] }], pendingContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "pendingContent", required: false }] }], reverse: [{ type: i0.Input, args: [{ isSignal: true, alias: "reverse", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
|
|
10531
|
+
|
|
10532
|
+
/**
|
|
10533
|
+
* DS Transfer
|
|
10534
|
+
*
|
|
10535
|
+
* Composant permettant de transférer des items entre deux listes (source et cible).
|
|
10536
|
+
* Inclut recherche, sélection multiple, et navigation clavier.
|
|
10537
|
+
*
|
|
10538
|
+
* @example
|
|
10539
|
+
* <ds-transfer
|
|
10540
|
+
* [source]="sourceItems"
|
|
10541
|
+
* [target]="targetItems"
|
|
10542
|
+
* sourceTitle="Disponibles"
|
|
10543
|
+
* targetTitle="Sélectionnés"
|
|
10544
|
+
* [showSearch]="true"
|
|
10545
|
+
* (transferChange)="onTransfer($event)"
|
|
10546
|
+
* />
|
|
10547
|
+
*/
|
|
10548
|
+
class DsTransfer {
|
|
10549
|
+
// Inputs
|
|
10550
|
+
source = input([], ...(ngDevMode ? [{ debugName: "source" }] : []));
|
|
10551
|
+
target = input([], ...(ngDevMode ? [{ debugName: "target" }] : []));
|
|
10552
|
+
sourceTitle = input('Source', ...(ngDevMode ? [{ debugName: "sourceTitle" }] : []));
|
|
10553
|
+
targetTitle = input('Target', ...(ngDevMode ? [{ debugName: "targetTitle" }] : []));
|
|
10554
|
+
showSearch = input(true, ...(ngDevMode ? [{ debugName: "showSearch" }] : []));
|
|
10555
|
+
showSelectAll = input(true, ...(ngDevMode ? [{ debugName: "showSelectAll" }] : []));
|
|
10556
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
10557
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
10558
|
+
// Outputs
|
|
10559
|
+
transferChange = output();
|
|
10560
|
+
// Internal state
|
|
10561
|
+
sourceSelected = signal(new Set(), ...(ngDevMode ? [{ debugName: "sourceSelected" }] : []));
|
|
10562
|
+
targetSelected = signal(new Set(), ...(ngDevMode ? [{ debugName: "targetSelected" }] : []));
|
|
10563
|
+
sourceSearchQuery = signal('', ...(ngDevMode ? [{ debugName: "sourceSearchQuery" }] : []));
|
|
10564
|
+
targetSearchQuery = signal('', ...(ngDevMode ? [{ debugName: "targetSearchQuery" }] : []));
|
|
10565
|
+
// Computed
|
|
10566
|
+
filteredSource = computed(() => {
|
|
10567
|
+
const query = this.sourceSearchQuery().toLowerCase();
|
|
10568
|
+
if (!query)
|
|
10569
|
+
return this.source();
|
|
10570
|
+
return this.source().filter(item => item.label.toLowerCase().includes(query) ||
|
|
10571
|
+
item.description?.toLowerCase().includes(query));
|
|
10572
|
+
}, ...(ngDevMode ? [{ debugName: "filteredSource" }] : []));
|
|
10573
|
+
filteredTarget = computed(() => {
|
|
10574
|
+
const query = this.targetSearchQuery().toLowerCase();
|
|
10575
|
+
if (!query)
|
|
10576
|
+
return this.target();
|
|
10577
|
+
return this.target().filter(item => item.label.toLowerCase().includes(query) ||
|
|
10578
|
+
item.description?.toLowerCase().includes(query));
|
|
10579
|
+
}, ...(ngDevMode ? [{ debugName: "filteredTarget" }] : []));
|
|
10580
|
+
sourceSelectableCount = computed(() => this.filteredSource().filter(item => !item.disabled).length, ...(ngDevMode ? [{ debugName: "sourceSelectableCount" }] : []));
|
|
10581
|
+
targetSelectableCount = computed(() => this.filteredTarget().filter(item => !item.disabled).length, ...(ngDevMode ? [{ debugName: "targetSelectableCount" }] : []));
|
|
10582
|
+
isAllSourceSelected = computed(() => {
|
|
10583
|
+
const count = this.sourceSelectableCount();
|
|
10584
|
+
return count > 0 && this.sourceSelected().size === count;
|
|
10585
|
+
}, ...(ngDevMode ? [{ debugName: "isAllSourceSelected" }] : []));
|
|
10586
|
+
isAllTargetSelected = computed(() => {
|
|
10587
|
+
const count = this.targetSelectableCount();
|
|
10588
|
+
return count > 0 && this.targetSelected().size === count;
|
|
10589
|
+
}, ...(ngDevMode ? [{ debugName: "isAllTargetSelected" }] : []));
|
|
10590
|
+
canTransferToTarget = computed(() => this.sourceSelected().size > 0 && !this.disabled(), ...(ngDevMode ? [{ debugName: "canTransferToTarget" }] : []));
|
|
10591
|
+
canTransferToSource = computed(() => this.targetSelected().size > 0 && !this.disabled(), ...(ngDevMode ? [{ debugName: "canTransferToSource" }] : []));
|
|
10592
|
+
containerClasses = computed(() => ({
|
|
10593
|
+
'ds-transfer': true,
|
|
10594
|
+
'ds-transfer--disabled': this.disabled(),
|
|
10595
|
+
[`ds-transfer--${this.size()}`]: true,
|
|
10596
|
+
}), ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
10597
|
+
// Public methods
|
|
10598
|
+
transferToTarget() {
|
|
10599
|
+
if (!this.canTransferToTarget())
|
|
10600
|
+
return;
|
|
10601
|
+
const selectedKeys = Array.from(this.sourceSelected());
|
|
10602
|
+
const itemsToTransfer = this.source().filter(item => selectedKeys.includes(item.key));
|
|
10603
|
+
const newSource = this.source().filter(item => !selectedKeys.includes(item.key));
|
|
10604
|
+
const newTarget = [...this.target(), ...itemsToTransfer];
|
|
10605
|
+
this.sourceSelected.set(new Set());
|
|
10606
|
+
this.emitChange(newSource, newTarget);
|
|
10607
|
+
}
|
|
10608
|
+
transferToSource() {
|
|
10609
|
+
if (!this.canTransferToSource())
|
|
10610
|
+
return;
|
|
10611
|
+
const selectedKeys = Array.from(this.targetSelected());
|
|
10612
|
+
const itemsToTransfer = this.target().filter(item => selectedKeys.includes(item.key));
|
|
10613
|
+
const newTarget = this.target().filter(item => !selectedKeys.includes(item.key));
|
|
10614
|
+
const newSource = [...this.source(), ...itemsToTransfer];
|
|
10615
|
+
this.targetSelected.set(new Set());
|
|
10616
|
+
this.emitChange(newSource, newTarget);
|
|
10617
|
+
}
|
|
10618
|
+
toggleSelectAll(direction) {
|
|
10619
|
+
if (this.disabled())
|
|
10620
|
+
return;
|
|
10621
|
+
const isSource = direction === 'left';
|
|
10622
|
+
const items = isSource ? this.filteredSource() : this.filteredTarget();
|
|
10623
|
+
const selected = isSource ? this.sourceSelected() : this.targetSelected();
|
|
10624
|
+
const isAllSelected = isSource ? this.isAllSourceSelected() : this.isAllTargetSelected();
|
|
10625
|
+
const newSelected = new Set();
|
|
10626
|
+
if (!isAllSelected) {
|
|
10627
|
+
items.forEach(item => {
|
|
10628
|
+
if (!item.disabled) {
|
|
10629
|
+
newSelected.add(item.key);
|
|
10630
|
+
}
|
|
10631
|
+
});
|
|
10632
|
+
}
|
|
10633
|
+
if (isSource) {
|
|
10634
|
+
this.sourceSelected.set(newSelected);
|
|
10635
|
+
}
|
|
10636
|
+
else {
|
|
10637
|
+
this.targetSelected.set(newSelected);
|
|
10638
|
+
}
|
|
10639
|
+
}
|
|
10640
|
+
toggleItemSelection(item, direction) {
|
|
10641
|
+
if (this.disabled() || item.disabled)
|
|
10642
|
+
return;
|
|
10643
|
+
const isSource = direction === 'left';
|
|
10644
|
+
const selected = isSource ? this.sourceSelected() : this.targetSelected();
|
|
10645
|
+
const newSelected = new Set(selected);
|
|
10646
|
+
if (newSelected.has(item.key)) {
|
|
10647
|
+
newSelected.delete(item.key);
|
|
10648
|
+
}
|
|
10649
|
+
else {
|
|
10650
|
+
newSelected.add(item.key);
|
|
10651
|
+
}
|
|
10652
|
+
if (isSource) {
|
|
10653
|
+
this.sourceSelected.set(newSelected);
|
|
10654
|
+
}
|
|
10655
|
+
else {
|
|
10656
|
+
this.targetSelected.set(newSelected);
|
|
10657
|
+
}
|
|
10658
|
+
}
|
|
10659
|
+
isItemSelected(item, direction) {
|
|
10660
|
+
const selected = direction === 'left' ? this.sourceSelected() : this.targetSelected();
|
|
10661
|
+
return selected.has(item.key);
|
|
10662
|
+
}
|
|
10663
|
+
onSearchInput(event, direction) {
|
|
10664
|
+
const input = event.target;
|
|
10665
|
+
const query = input.value;
|
|
10666
|
+
if (direction === 'left') {
|
|
10667
|
+
this.sourceSearchQuery.set(query);
|
|
10668
|
+
}
|
|
10669
|
+
else {
|
|
10670
|
+
this.targetSearchQuery.set(query);
|
|
10671
|
+
}
|
|
10672
|
+
}
|
|
10673
|
+
clearSearch(direction) {
|
|
10674
|
+
if (direction === 'left') {
|
|
10675
|
+
this.sourceSearchQuery.set('');
|
|
10676
|
+
}
|
|
10677
|
+
else {
|
|
10678
|
+
this.targetSearchQuery.set('');
|
|
10679
|
+
}
|
|
10680
|
+
}
|
|
10681
|
+
getSelectedCount(direction) {
|
|
10682
|
+
return direction === 'left'
|
|
10683
|
+
? this.sourceSelected().size
|
|
10684
|
+
: this.targetSelected().size;
|
|
10685
|
+
}
|
|
10686
|
+
getItemCount(direction) {
|
|
10687
|
+
return direction === 'left'
|
|
10688
|
+
? this.filteredSource().length
|
|
10689
|
+
: this.filteredTarget().length;
|
|
10690
|
+
}
|
|
10691
|
+
emitChange(source, target) {
|
|
10692
|
+
this.transferChange.emit({ source, target });
|
|
10693
|
+
}
|
|
10694
|
+
// ARIA helpers
|
|
10695
|
+
getListboxId(direction) {
|
|
10696
|
+
return `ds-transfer-${direction}-listbox`;
|
|
10697
|
+
}
|
|
10698
|
+
getItemId(item, direction) {
|
|
10699
|
+
return `ds-transfer-${direction}-item-${item.key}`;
|
|
10700
|
+
}
|
|
10701
|
+
sourceListboxLabel = computed(() => `${this.sourceTitle()} (${this.getSelectedCount('left')}/${this.getItemCount('left')} sélectionné(s))`, ...(ngDevMode ? [{ debugName: "sourceListboxLabel" }] : []));
|
|
10702
|
+
targetListboxLabel = computed(() => `${this.targetTitle()} (${this.getSelectedCount('right')}/${this.getItemCount('right')} sélectionné(s))`, ...(ngDevMode ? [{ debugName: "targetListboxLabel" }] : []));
|
|
10703
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTransfer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10704
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsTransfer, isStandalone: true, selector: "ds-transfer", inputs: { source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, sourceTitle: { classPropertyName: "sourceTitle", publicName: "sourceTitle", isSignal: true, isRequired: false, transformFunction: null }, targetTitle: { classPropertyName: "targetTitle", publicName: "targetTitle", isSignal: true, isRequired: false, transformFunction: null }, showSearch: { classPropertyName: "showSearch", publicName: "showSearch", isSignal: true, isRequired: false, transformFunction: null }, showSelectAll: { classPropertyName: "showSelectAll", publicName: "showSelectAll", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { transferChange: "transferChange" }, ngImport: i0, template: "<div [ngClass]=\"containerClasses()\" role=\"group\" aria-label=\"Transfer component\">\n <!-- Source panel -->\n <div class=\"ds-transfer__panel ds-transfer__panel--source\">\n <!-- Header -->\n <div class=\"ds-transfer__header\">\n <div class=\"ds-transfer__title\">\n <span>{{ sourceTitle() }}</span>\n <span class=\"ds-transfer__count\">\n {{ getSelectedCount('left') }} / {{ source().length }}\n </span>\n </div>\n @if (showSelectAll()) {\n <primitive-checkbox\n [checked]=\"isAllSourceSelected()\"\n [indeterminate]=\"sourceSelected().size > 0 && !isAllSourceSelected()\"\n [disabled]=\"disabled() || sourceSelectableCount() === 0\"\n (checkedChange)=\"toggleSelectAll('left')\"\n size=\"sm\"\n label=\"Tout s\u00E9lectionner\"\n class=\"ds-transfer__select-all\"\n />\n }\n </div>\n\n <!-- Search -->\n @if (showSearch()) {\n <div class=\"ds-transfer__search\">\n <input\n type=\"text\"\n class=\"ds-transfer__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"sourceSearchQuery()\"\n (input)=\"onSearchInput($event, 'left')\"\n [disabled]=\"disabled()\"\n aria-label=\"Rechercher dans les items source\"\n />\n @if (sourceSearchQuery()) {\n <button\n type=\"button\"\n class=\"ds-transfer__search-clear\"\n (click)=\"clearSearch('left')\"\n aria-label=\"Effacer la recherche\"\n >\n \u2715\n </button>\n }\n </div>\n }\n\n <!-- List -->\n <div\n class=\"ds-transfer__list\"\n role=\"listbox\"\n [attr.aria-label]=\"sourceListboxLabel()\"\n [attr.id]=\"getListboxId('left')\"\n [attr.aria-multiselectable]=\"true\"\n >\n @if (filteredSource().length === 0) {\n <div class=\"ds-transfer__empty\">\n @if (sourceSearchQuery()) {\n Aucun r\u00E9sultat\n } @else {\n Aucun item disponible\n }\n </div>\n } @else {\n @for (item of filteredSource(); track item.key) {\n <div\n class=\"ds-transfer__item\"\n [class.ds-transfer__item--selected]=\"isItemSelected(item, 'left')\"\n [class.ds-transfer__item--disabled]=\"item.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isItemSelected(item, 'left')\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.id]=\"getItemId(item, 'left')\"\n (click)=\"toggleItemSelection(item, 'left')\"\n >\n <primitive-checkbox\n [checked]=\"isItemSelected(item, 'left')\"\n [disabled]=\"disabled() || (item.disabled ?? false)\"\n (checkedChange)=\"toggleItemSelection(item, 'left')\"\n size=\"sm\"\n />\n <div class=\"ds-transfer__item-content\">\n <div class=\"ds-transfer__item-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"ds-transfer__item-description\">{{ item.description }}</div>\n }\n </div>\n </div>\n }\n }\n </div>\n </div>\n\n <!-- Transfer buttons -->\n <div class=\"ds-transfer__actions\">\n <ds-button\n variant=\"secondary\"\n size=\"sm\"\n [disabled]=\"!canTransferToTarget()\"\n (click)=\"transferToTarget()\"\n aria-label=\"Transf\u00E9rer les items s\u00E9lectionn\u00E9s vers la droite\"\n >\n \u203A\n </ds-button>\n <ds-button\n variant=\"secondary\"\n size=\"sm\"\n [disabled]=\"!canTransferToSource()\"\n (click)=\"transferToSource()\"\n aria-label=\"Transf\u00E9rer les items s\u00E9lectionn\u00E9s vers la gauche\"\n >\n \u2039\n </ds-button>\n </div>\n\n <!-- Target panel -->\n <div class=\"ds-transfer__panel ds-transfer__panel--target\">\n <!-- Header -->\n <div class=\"ds-transfer__header\">\n <div class=\"ds-transfer__title\">\n <span>{{ targetTitle() }}</span>\n <span class=\"ds-transfer__count\">\n {{ getSelectedCount('right') }} / {{ target().length }}\n </span>\n </div>\n @if (showSelectAll()) {\n <primitive-checkbox\n [checked]=\"isAllTargetSelected()\"\n [indeterminate]=\"targetSelected().size > 0 && !isAllTargetSelected()\"\n [disabled]=\"disabled() || targetSelectableCount() === 0\"\n (checkedChange)=\"toggleSelectAll('right')\"\n size=\"sm\"\n label=\"Tout s\u00E9lectionner\"\n class=\"ds-transfer__select-all\"\n />\n }\n </div>\n\n <!-- Search -->\n @if (showSearch()) {\n <div class=\"ds-transfer__search\">\n <input\n type=\"text\"\n class=\"ds-transfer__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"targetSearchQuery()\"\n (input)=\"onSearchInput($event, 'right')\"\n [disabled]=\"disabled()\"\n aria-label=\"Rechercher dans les items cible\"\n />\n @if (targetSearchQuery()) {\n <button\n type=\"button\"\n class=\"ds-transfer__search-clear\"\n (click)=\"clearSearch('right')\"\n aria-label=\"Effacer la recherche\"\n >\n \u2715\n </button>\n }\n </div>\n }\n\n <!-- List -->\n <div\n class=\"ds-transfer__list\"\n role=\"listbox\"\n [attr.aria-label]=\"targetListboxLabel()\"\n [attr.id]=\"getListboxId('right')\"\n [attr.aria-multiselectable]=\"true\"\n >\n @if (filteredTarget().length === 0) {\n <div class=\"ds-transfer__empty\">\n @if (targetSearchQuery()) {\n Aucun r\u00E9sultat\n } @else {\n Aucun item s\u00E9lectionn\u00E9\n }\n </div>\n } @else {\n @for (item of filteredTarget(); track item.key) {\n <div\n class=\"ds-transfer__item\"\n [class.ds-transfer__item--selected]=\"isItemSelected(item, 'right')\"\n [class.ds-transfer__item--disabled]=\"item.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isItemSelected(item, 'right')\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.id]=\"getItemId(item, 'right')\"\n (click)=\"toggleItemSelection(item, 'right')\"\n >\n <primitive-checkbox\n [checked]=\"isItemSelected(item, 'right')\"\n [disabled]=\"disabled() || (item.disabled ?? false)\"\n (checkedChange)=\"toggleItemSelection(item, 'right')\"\n size=\"sm\"\n />\n <div class=\"ds-transfer__item-content\">\n <div class=\"ds-transfer__item-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"ds-transfer__item-description\">{{ item.description }}</div>\n }\n </div>\n </div>\n }\n }\n </div>\n </div>\n</div>\n", styles: [".ds-transfer{display:flex;align-items:center;gap:var(--transfer-gap, 1rem);width:100%}.ds-transfer__panel{flex:1;display:flex;flex-direction:column;border:1px solid var(--transfer-border-color, var(--gray-300));border-radius:var(--transfer-border-radius, var(--radius-2));background:var(--transfer-bg, var(--white));overflow:hidden}.ds-transfer__header{display:flex;align-items:center;justify-content:space-between;padding:var(--transfer-header-padding, .75rem 1rem);border-bottom:1px solid var(--transfer-header-border-color, var(--gray-200));background:var(--transfer-header-bg, var(--gray-50))}.ds-transfer__title{display:flex;align-items:center;gap:.5rem;font-weight:600;font-size:var(--transfer-title-font-size, var(--font-size-sm));color:var(--transfer-title-color, var(--text-default))}.ds-transfer__count{font-weight:400;font-size:var(--font-size-xs);color:var(--transfer-count-color, var(--text-light))}.ds-transfer__search{position:relative;padding:var(--transfer-search-padding, .75rem 1rem);border-bottom:1px solid var(--transfer-search-border-color, var(--gray-200))}.ds-transfer__search-input{width:100%;padding:var(--transfer-search-input-padding, .5rem 2rem .5rem .75rem);border:1px solid var(--transfer-search-input-border, var(--gray-300));border-radius:var(--transfer-search-input-radius, var(--radius-1));font-size:var(--font-size-sm);color:var(--transfer-search-input-text, var(--text-default));background:var(--transfer-search-input-bg, var(--white))}.ds-transfer__search-input::placeholder{color:var(--transfer-search-placeholder, var(--text-lighter))}.ds-transfer__search-input:focus{outline:none;border-color:var(--transfer-search-input-focus, var(--color-primary));box-shadow:0 0 0 3px var(--transfer-search-input-focus-shadow, rgba(59, 130, 246, .1))}.ds-transfer__search-input:disabled{opacity:.6;cursor:not-allowed;background:var(--transfer-search-input-disabled-bg, var(--gray-50))}.ds-transfer__search-clear{position:absolute;top:50%;right:1.5rem;transform:translateY(-50%);padding:.25rem;border:none;background:transparent;color:var(--transfer-search-clear-color, var(--text-lighter));cursor:pointer;font-size:1rem;line-height:1}.ds-transfer__search-clear:hover{color:var(--transfer-search-clear-hover, var(--text-default))}.ds-transfer__search-clear:focus{outline:2px solid var(--color-primary);outline-offset:2px}.ds-transfer__list{flex:1;overflow-y:auto;min-height:var(--transfer-list-min-height, 300px);max-height:var(--transfer-list-max-height, 400px)}.ds-transfer__empty{display:flex;align-items:center;justify-content:center;height:100%;padding:2rem;color:var(--transfer-empty-color, var(--text-lighter));font-size:var(--font-size-sm);text-align:center}.ds-transfer__item{display:flex;align-items:flex-start;gap:.75rem;padding:var(--transfer-item-padding, .75rem 1rem);border-bottom:1px solid var(--transfer-item-border, var(--gray-100));cursor:pointer;transition:background-color .2s}.ds-transfer__item:hover:not(.ds-transfer__item--disabled){background:var(--transfer-item-hover-bg, var(--gray-50))}.ds-transfer__item--selected{background:var(--transfer-item-selected-bg, var(--blue-50))}.ds-transfer__item--selected:hover:not(.ds-transfer__item--selected--disabled){background:var(--transfer-item-selected-hover-bg, var(--blue-100))}.ds-transfer__item--disabled{opacity:.5;cursor:not-allowed}.ds-transfer__item:last-child{border-bottom:none}.ds-transfer__item-content{flex:1;min-width:0}.ds-transfer__item-label{font-size:var(--transfer-item-font-size, var(--font-size-sm));font-weight:500;color:var(--transfer-item-label-color, var(--text-default));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-transfer__item-description{margin-top:.25rem;font-size:var(--font-size-xs);color:var(--transfer-item-description-color, var(--text-light));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-transfer__actions{display:flex;flex-direction:column;gap:var(--transfer-actions-gap, .5rem);align-self:center}.ds-transfer--sm .ds-transfer__header,.ds-transfer--sm .ds-transfer__search{padding:.5rem .75rem}.ds-transfer--sm .ds-transfer__search-input{padding:.375rem 1.5rem .375rem .5rem;font-size:var(--font-size-xs)}.ds-transfer--sm .ds-transfer__item{padding:.5rem .75rem}.ds-transfer--sm .ds-transfer__item-label{font-size:var(--font-size-xs)}.ds-transfer--sm .ds-transfer__list{min-height:200px;max-height:300px}.ds-transfer--lg .ds-transfer__header,.ds-transfer--lg .ds-transfer__search{padding:1rem 1.25rem}.ds-transfer--lg .ds-transfer__search-input{padding:.625rem 2.5rem .625rem 1rem;font-size:var(--font-size-base)}.ds-transfer--lg .ds-transfer__item{padding:1rem 1.25rem}.ds-transfer--lg .ds-transfer__item-label{font-size:var(--font-size-base)}.ds-transfer--lg .ds-transfer__list{min-height:400px;max-height:500px}.ds-transfer--disabled{opacity:.6;cursor:not-allowed}.ds-transfer--disabled .ds-transfer__panel,.ds-transfer--disabled .ds-transfer__item{pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: PrimitiveCheckbox, selector: "primitive-checkbox", inputs: ["checked", "indeterminate", "disabled", "size", "label", "checkboxId"], outputs: ["checkedChange"] }, { kind: "component", type: DsButton, selector: "ds-button", inputs: ["variant", "appearance", "size", "submit", "disabled", "iconStart", "iconEnd", "loading", "block"], outputs: ["clicked"] }] });
|
|
10705
|
+
}
|
|
10706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsTransfer, decorators: [{
|
|
10707
|
+
type: Component,
|
|
10708
|
+
args: [{ selector: 'ds-transfer', standalone: true, imports: [CommonModule, FormsModule, PrimitiveCheckbox, DsButton], template: "<div [ngClass]=\"containerClasses()\" role=\"group\" aria-label=\"Transfer component\">\n <!-- Source panel -->\n <div class=\"ds-transfer__panel ds-transfer__panel--source\">\n <!-- Header -->\n <div class=\"ds-transfer__header\">\n <div class=\"ds-transfer__title\">\n <span>{{ sourceTitle() }}</span>\n <span class=\"ds-transfer__count\">\n {{ getSelectedCount('left') }} / {{ source().length }}\n </span>\n </div>\n @if (showSelectAll()) {\n <primitive-checkbox\n [checked]=\"isAllSourceSelected()\"\n [indeterminate]=\"sourceSelected().size > 0 && !isAllSourceSelected()\"\n [disabled]=\"disabled() || sourceSelectableCount() === 0\"\n (checkedChange)=\"toggleSelectAll('left')\"\n size=\"sm\"\n label=\"Tout s\u00E9lectionner\"\n class=\"ds-transfer__select-all\"\n />\n }\n </div>\n\n <!-- Search -->\n @if (showSearch()) {\n <div class=\"ds-transfer__search\">\n <input\n type=\"text\"\n class=\"ds-transfer__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"sourceSearchQuery()\"\n (input)=\"onSearchInput($event, 'left')\"\n [disabled]=\"disabled()\"\n aria-label=\"Rechercher dans les items source\"\n />\n @if (sourceSearchQuery()) {\n <button\n type=\"button\"\n class=\"ds-transfer__search-clear\"\n (click)=\"clearSearch('left')\"\n aria-label=\"Effacer la recherche\"\n >\n \u2715\n </button>\n }\n </div>\n }\n\n <!-- List -->\n <div\n class=\"ds-transfer__list\"\n role=\"listbox\"\n [attr.aria-label]=\"sourceListboxLabel()\"\n [attr.id]=\"getListboxId('left')\"\n [attr.aria-multiselectable]=\"true\"\n >\n @if (filteredSource().length === 0) {\n <div class=\"ds-transfer__empty\">\n @if (sourceSearchQuery()) {\n Aucun r\u00E9sultat\n } @else {\n Aucun item disponible\n }\n </div>\n } @else {\n @for (item of filteredSource(); track item.key) {\n <div\n class=\"ds-transfer__item\"\n [class.ds-transfer__item--selected]=\"isItemSelected(item, 'left')\"\n [class.ds-transfer__item--disabled]=\"item.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isItemSelected(item, 'left')\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.id]=\"getItemId(item, 'left')\"\n (click)=\"toggleItemSelection(item, 'left')\"\n >\n <primitive-checkbox\n [checked]=\"isItemSelected(item, 'left')\"\n [disabled]=\"disabled() || (item.disabled ?? false)\"\n (checkedChange)=\"toggleItemSelection(item, 'left')\"\n size=\"sm\"\n />\n <div class=\"ds-transfer__item-content\">\n <div class=\"ds-transfer__item-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"ds-transfer__item-description\">{{ item.description }}</div>\n }\n </div>\n </div>\n }\n }\n </div>\n </div>\n\n <!-- Transfer buttons -->\n <div class=\"ds-transfer__actions\">\n <ds-button\n variant=\"secondary\"\n size=\"sm\"\n [disabled]=\"!canTransferToTarget()\"\n (click)=\"transferToTarget()\"\n aria-label=\"Transf\u00E9rer les items s\u00E9lectionn\u00E9s vers la droite\"\n >\n \u203A\n </ds-button>\n <ds-button\n variant=\"secondary\"\n size=\"sm\"\n [disabled]=\"!canTransferToSource()\"\n (click)=\"transferToSource()\"\n aria-label=\"Transf\u00E9rer les items s\u00E9lectionn\u00E9s vers la gauche\"\n >\n \u2039\n </ds-button>\n </div>\n\n <!-- Target panel -->\n <div class=\"ds-transfer__panel ds-transfer__panel--target\">\n <!-- Header -->\n <div class=\"ds-transfer__header\">\n <div class=\"ds-transfer__title\">\n <span>{{ targetTitle() }}</span>\n <span class=\"ds-transfer__count\">\n {{ getSelectedCount('right') }} / {{ target().length }}\n </span>\n </div>\n @if (showSelectAll()) {\n <primitive-checkbox\n [checked]=\"isAllTargetSelected()\"\n [indeterminate]=\"targetSelected().size > 0 && !isAllTargetSelected()\"\n [disabled]=\"disabled() || targetSelectableCount() === 0\"\n (checkedChange)=\"toggleSelectAll('right')\"\n size=\"sm\"\n label=\"Tout s\u00E9lectionner\"\n class=\"ds-transfer__select-all\"\n />\n }\n </div>\n\n <!-- Search -->\n @if (showSearch()) {\n <div class=\"ds-transfer__search\">\n <input\n type=\"text\"\n class=\"ds-transfer__search-input\"\n placeholder=\"Rechercher...\"\n [value]=\"targetSearchQuery()\"\n (input)=\"onSearchInput($event, 'right')\"\n [disabled]=\"disabled()\"\n aria-label=\"Rechercher dans les items cible\"\n />\n @if (targetSearchQuery()) {\n <button\n type=\"button\"\n class=\"ds-transfer__search-clear\"\n (click)=\"clearSearch('right')\"\n aria-label=\"Effacer la recherche\"\n >\n \u2715\n </button>\n }\n </div>\n }\n\n <!-- List -->\n <div\n class=\"ds-transfer__list\"\n role=\"listbox\"\n [attr.aria-label]=\"targetListboxLabel()\"\n [attr.id]=\"getListboxId('right')\"\n [attr.aria-multiselectable]=\"true\"\n >\n @if (filteredTarget().length === 0) {\n <div class=\"ds-transfer__empty\">\n @if (targetSearchQuery()) {\n Aucun r\u00E9sultat\n } @else {\n Aucun item s\u00E9lectionn\u00E9\n }\n </div>\n } @else {\n @for (item of filteredTarget(); track item.key) {\n <div\n class=\"ds-transfer__item\"\n [class.ds-transfer__item--selected]=\"isItemSelected(item, 'right')\"\n [class.ds-transfer__item--disabled]=\"item.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isItemSelected(item, 'right')\"\n [attr.aria-disabled]=\"item.disabled\"\n [attr.id]=\"getItemId(item, 'right')\"\n (click)=\"toggleItemSelection(item, 'right')\"\n >\n <primitive-checkbox\n [checked]=\"isItemSelected(item, 'right')\"\n [disabled]=\"disabled() || (item.disabled ?? false)\"\n (checkedChange)=\"toggleItemSelection(item, 'right')\"\n size=\"sm\"\n />\n <div class=\"ds-transfer__item-content\">\n <div class=\"ds-transfer__item-label\">{{ item.label }}</div>\n @if (item.description) {\n <div class=\"ds-transfer__item-description\">{{ item.description }}</div>\n }\n </div>\n </div>\n }\n }\n </div>\n </div>\n</div>\n", styles: [".ds-transfer{display:flex;align-items:center;gap:var(--transfer-gap, 1rem);width:100%}.ds-transfer__panel{flex:1;display:flex;flex-direction:column;border:1px solid var(--transfer-border-color, var(--gray-300));border-radius:var(--transfer-border-radius, var(--radius-2));background:var(--transfer-bg, var(--white));overflow:hidden}.ds-transfer__header{display:flex;align-items:center;justify-content:space-between;padding:var(--transfer-header-padding, .75rem 1rem);border-bottom:1px solid var(--transfer-header-border-color, var(--gray-200));background:var(--transfer-header-bg, var(--gray-50))}.ds-transfer__title{display:flex;align-items:center;gap:.5rem;font-weight:600;font-size:var(--transfer-title-font-size, var(--font-size-sm));color:var(--transfer-title-color, var(--text-default))}.ds-transfer__count{font-weight:400;font-size:var(--font-size-xs);color:var(--transfer-count-color, var(--text-light))}.ds-transfer__search{position:relative;padding:var(--transfer-search-padding, .75rem 1rem);border-bottom:1px solid var(--transfer-search-border-color, var(--gray-200))}.ds-transfer__search-input{width:100%;padding:var(--transfer-search-input-padding, .5rem 2rem .5rem .75rem);border:1px solid var(--transfer-search-input-border, var(--gray-300));border-radius:var(--transfer-search-input-radius, var(--radius-1));font-size:var(--font-size-sm);color:var(--transfer-search-input-text, var(--text-default));background:var(--transfer-search-input-bg, var(--white))}.ds-transfer__search-input::placeholder{color:var(--transfer-search-placeholder, var(--text-lighter))}.ds-transfer__search-input:focus{outline:none;border-color:var(--transfer-search-input-focus, var(--color-primary));box-shadow:0 0 0 3px var(--transfer-search-input-focus-shadow, rgba(59, 130, 246, .1))}.ds-transfer__search-input:disabled{opacity:.6;cursor:not-allowed;background:var(--transfer-search-input-disabled-bg, var(--gray-50))}.ds-transfer__search-clear{position:absolute;top:50%;right:1.5rem;transform:translateY(-50%);padding:.25rem;border:none;background:transparent;color:var(--transfer-search-clear-color, var(--text-lighter));cursor:pointer;font-size:1rem;line-height:1}.ds-transfer__search-clear:hover{color:var(--transfer-search-clear-hover, var(--text-default))}.ds-transfer__search-clear:focus{outline:2px solid var(--color-primary);outline-offset:2px}.ds-transfer__list{flex:1;overflow-y:auto;min-height:var(--transfer-list-min-height, 300px);max-height:var(--transfer-list-max-height, 400px)}.ds-transfer__empty{display:flex;align-items:center;justify-content:center;height:100%;padding:2rem;color:var(--transfer-empty-color, var(--text-lighter));font-size:var(--font-size-sm);text-align:center}.ds-transfer__item{display:flex;align-items:flex-start;gap:.75rem;padding:var(--transfer-item-padding, .75rem 1rem);border-bottom:1px solid var(--transfer-item-border, var(--gray-100));cursor:pointer;transition:background-color .2s}.ds-transfer__item:hover:not(.ds-transfer__item--disabled){background:var(--transfer-item-hover-bg, var(--gray-50))}.ds-transfer__item--selected{background:var(--transfer-item-selected-bg, var(--blue-50))}.ds-transfer__item--selected:hover:not(.ds-transfer__item--selected--disabled){background:var(--transfer-item-selected-hover-bg, var(--blue-100))}.ds-transfer__item--disabled{opacity:.5;cursor:not-allowed}.ds-transfer__item:last-child{border-bottom:none}.ds-transfer__item-content{flex:1;min-width:0}.ds-transfer__item-label{font-size:var(--transfer-item-font-size, var(--font-size-sm));font-weight:500;color:var(--transfer-item-label-color, var(--text-default));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-transfer__item-description{margin-top:.25rem;font-size:var(--font-size-xs);color:var(--transfer-item-description-color, var(--text-light));overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ds-transfer__actions{display:flex;flex-direction:column;gap:var(--transfer-actions-gap, .5rem);align-self:center}.ds-transfer--sm .ds-transfer__header,.ds-transfer--sm .ds-transfer__search{padding:.5rem .75rem}.ds-transfer--sm .ds-transfer__search-input{padding:.375rem 1.5rem .375rem .5rem;font-size:var(--font-size-xs)}.ds-transfer--sm .ds-transfer__item{padding:.5rem .75rem}.ds-transfer--sm .ds-transfer__item-label{font-size:var(--font-size-xs)}.ds-transfer--sm .ds-transfer__list{min-height:200px;max-height:300px}.ds-transfer--lg .ds-transfer__header,.ds-transfer--lg .ds-transfer__search{padding:1rem 1.25rem}.ds-transfer--lg .ds-transfer__search-input{padding:.625rem 2.5rem .625rem 1rem;font-size:var(--font-size-base)}.ds-transfer--lg .ds-transfer__item{padding:1rem 1.25rem}.ds-transfer--lg .ds-transfer__item-label{font-size:var(--font-size-base)}.ds-transfer--lg .ds-transfer__list{min-height:400px;max-height:500px}.ds-transfer--disabled{opacity:.6;cursor:not-allowed}.ds-transfer--disabled .ds-transfer__panel,.ds-transfer--disabled .ds-transfer__item{pointer-events:none}\n"] }]
|
|
10709
|
+
}], propDecorators: { source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], sourceTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceTitle", required: false }] }], targetTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "targetTitle", required: false }] }], showSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSearch", required: false }] }], showSelectAll: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSelectAll", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], transferChange: [{ type: i0.Output, args: ["transferChange"] }] } });
|
|
10710
|
+
|
|
10711
|
+
class DsCarousel {
|
|
10712
|
+
// Config
|
|
10713
|
+
slides = input([], ...(ngDevMode ? [{ debugName: "slides" }] : []));
|
|
10714
|
+
autoplay = input(false, ...(ngDevMode ? [{ debugName: "autoplay" }] : []));
|
|
10715
|
+
autoplaySpeed = input(3000, ...(ngDevMode ? [{ debugName: "autoplaySpeed" }] : []));
|
|
10716
|
+
effect = input('slide', ...(ngDevMode ? [{ debugName: "effect" }] : []));
|
|
10717
|
+
dots = input(true, ...(ngDevMode ? [{ debugName: "dots" }] : []));
|
|
10718
|
+
dotsPosition = input('bottom', ...(ngDevMode ? [{ debugName: "dotsPosition" }] : []));
|
|
10719
|
+
arrows = input(true, ...(ngDevMode ? [{ debugName: "arrows" }] : []));
|
|
10720
|
+
infinite = input(true, ...(ngDevMode ? [{ debugName: "infinite" }] : []));
|
|
10721
|
+
pauseOnHover = input(true, ...(ngDevMode ? [{ debugName: "pauseOnHover" }] : []));
|
|
10722
|
+
activeIndex = input(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
|
|
10723
|
+
// Events
|
|
10724
|
+
slideChange = output();
|
|
10725
|
+
// ViewChild
|
|
10726
|
+
trackElement;
|
|
10727
|
+
slideElements;
|
|
10728
|
+
// Icons
|
|
10729
|
+
icons = {
|
|
10730
|
+
left: faChevronLeft,
|
|
10731
|
+
right: faChevronRight,
|
|
10732
|
+
};
|
|
10733
|
+
// Internal state
|
|
10734
|
+
internalActiveIndex = signal(0, ...(ngDevMode ? [{ debugName: "internalActiveIndex" }] : []));
|
|
10735
|
+
isPaused = signal(false, ...(ngDevMode ? [{ debugName: "isPaused" }] : []));
|
|
10736
|
+
isTransitioning = signal(false, ...(ngDevMode ? [{ debugName: "isTransitioning" }] : []));
|
|
10737
|
+
autoplayTimer = null;
|
|
10738
|
+
startX = 0;
|
|
10739
|
+
startY = 0;
|
|
10740
|
+
isDragging = false;
|
|
10741
|
+
constructor() {
|
|
10742
|
+
// Sync external activeIndex with internal
|
|
10743
|
+
effect(() => {
|
|
10744
|
+
const extIndex = this.activeIndex();
|
|
10745
|
+
const totalSlides = this.slides().length;
|
|
10746
|
+
if (totalSlides > 0 && extIndex >= 0 && extIndex < totalSlides) {
|
|
10747
|
+
this.internalActiveIndex.set(extIndex);
|
|
10748
|
+
}
|
|
10749
|
+
});
|
|
10750
|
+
// Autoplay effect
|
|
10751
|
+
effect(() => {
|
|
10752
|
+
if (this.autoplay() && !this.isPaused()) {
|
|
10753
|
+
this.startAutoplay();
|
|
10754
|
+
}
|
|
10755
|
+
else {
|
|
10756
|
+
this.stopAutoplay();
|
|
10757
|
+
}
|
|
10758
|
+
});
|
|
10759
|
+
}
|
|
10760
|
+
ngAfterViewInit() {
|
|
10761
|
+
// Initialiser l'index actif
|
|
10762
|
+
const initialIndex = this.activeIndex();
|
|
10763
|
+
if (initialIndex >= 0 && initialIndex < this.slides().length) {
|
|
10764
|
+
this.internalActiveIndex.set(initialIndex);
|
|
10765
|
+
}
|
|
10766
|
+
}
|
|
10767
|
+
ngOnDestroy() {
|
|
10768
|
+
this.stopAutoplay();
|
|
10769
|
+
}
|
|
10770
|
+
containerClasses = computed(() => {
|
|
10771
|
+
const classes = ['ds-carousel'];
|
|
10772
|
+
classes.push(`ds-carousel--${this.effect()}`);
|
|
10773
|
+
classes.push(`ds-carousel--dots-${this.dotsPosition()}`);
|
|
10774
|
+
if (this.isTransitioning())
|
|
10775
|
+
classes.push('ds-carousel--transitioning');
|
|
10776
|
+
return classes.join(' ');
|
|
10777
|
+
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
10778
|
+
trackStyle = computed(() => {
|
|
10779
|
+
if (this.effect() === 'slide') {
|
|
10780
|
+
const offset = -this.internalActiveIndex() * 100;
|
|
10781
|
+
return { transform: `translateX(${offset}%)` };
|
|
10782
|
+
}
|
|
10783
|
+
return {};
|
|
10784
|
+
}, ...(ngDevMode ? [{ debugName: "trackStyle" }] : []));
|
|
10785
|
+
slideClasses(index) {
|
|
10786
|
+
const classes = ['ds-carousel__slide'];
|
|
10787
|
+
const active = this.internalActiveIndex();
|
|
10788
|
+
if (index === active) {
|
|
10789
|
+
classes.push('ds-carousel__slide--active');
|
|
10790
|
+
}
|
|
10791
|
+
if (this.effect() === 'fade') {
|
|
10792
|
+
classes.push('ds-carousel__slide--fade');
|
|
10793
|
+
}
|
|
10794
|
+
return classes.join(' ');
|
|
10795
|
+
}
|
|
10796
|
+
dotClasses(index) {
|
|
10797
|
+
const classes = ['ds-carousel__dot'];
|
|
10798
|
+
if (index === this.internalActiveIndex()) {
|
|
10799
|
+
classes.push('ds-carousel__dot--active');
|
|
10800
|
+
}
|
|
10801
|
+
return classes.join(' ');
|
|
10802
|
+
}
|
|
10803
|
+
// Public methods
|
|
10804
|
+
next() {
|
|
10805
|
+
const totalSlides = this.slides().length;
|
|
10806
|
+
if (totalSlides === 0)
|
|
10807
|
+
return;
|
|
10808
|
+
const currentIndex = this.internalActiveIndex();
|
|
10809
|
+
let nextIndex = currentIndex + 1;
|
|
10810
|
+
if (nextIndex >= totalSlides) {
|
|
10811
|
+
nextIndex = this.infinite() ? 0 : currentIndex;
|
|
10812
|
+
}
|
|
10813
|
+
if (nextIndex !== currentIndex) {
|
|
10814
|
+
this.goTo(nextIndex);
|
|
10815
|
+
}
|
|
10816
|
+
}
|
|
10817
|
+
prev() {
|
|
10818
|
+
const totalSlides = this.slides().length;
|
|
10819
|
+
if (totalSlides === 0)
|
|
10820
|
+
return;
|
|
10821
|
+
const currentIndex = this.internalActiveIndex();
|
|
10822
|
+
let prevIndex = currentIndex - 1;
|
|
10823
|
+
if (prevIndex < 0) {
|
|
10824
|
+
prevIndex = this.infinite() ? totalSlides - 1 : currentIndex;
|
|
10825
|
+
}
|
|
10826
|
+
if (prevIndex !== currentIndex) {
|
|
10827
|
+
this.goTo(prevIndex);
|
|
10828
|
+
}
|
|
10829
|
+
}
|
|
10830
|
+
goTo(index) {
|
|
10831
|
+
const totalSlides = this.slides().length;
|
|
10832
|
+
if (index < 0 || index >= totalSlides || index === this.internalActiveIndex()) {
|
|
10833
|
+
return;
|
|
10834
|
+
}
|
|
10835
|
+
this.isTransitioning.set(true);
|
|
10836
|
+
this.internalActiveIndex.set(index);
|
|
10837
|
+
const slide = this.slides()[index];
|
|
10838
|
+
this.slideChange.emit({ index, slide });
|
|
10839
|
+
// Reset transitioning flag
|
|
10840
|
+
setTimeout(() => {
|
|
10841
|
+
this.isTransitioning.set(false);
|
|
10842
|
+
}, 300);
|
|
10843
|
+
// Reset autoplay
|
|
10844
|
+
if (this.autoplay()) {
|
|
10845
|
+
this.stopAutoplay();
|
|
10846
|
+
this.startAutoplay();
|
|
10847
|
+
}
|
|
10848
|
+
}
|
|
10849
|
+
pause() {
|
|
10850
|
+
this.isPaused.set(true);
|
|
10851
|
+
this.stopAutoplay();
|
|
10852
|
+
}
|
|
10853
|
+
play() {
|
|
10854
|
+
this.isPaused.set(false);
|
|
10855
|
+
if (this.autoplay()) {
|
|
10856
|
+
this.startAutoplay();
|
|
10857
|
+
}
|
|
10858
|
+
}
|
|
10859
|
+
onMouseEnter() {
|
|
10860
|
+
if (this.pauseOnHover() && this.autoplay()) {
|
|
10861
|
+
this.pause();
|
|
10862
|
+
}
|
|
10863
|
+
}
|
|
10864
|
+
onMouseLeave() {
|
|
10865
|
+
if (this.pauseOnHover() && this.autoplay()) {
|
|
10866
|
+
this.play();
|
|
10867
|
+
}
|
|
10868
|
+
}
|
|
10869
|
+
onKeydown(event) {
|
|
10870
|
+
switch (event.key) {
|
|
10871
|
+
case 'ArrowLeft':
|
|
10872
|
+
event.preventDefault();
|
|
10873
|
+
this.prev();
|
|
10874
|
+
break;
|
|
10875
|
+
case 'ArrowRight':
|
|
10876
|
+
event.preventDefault();
|
|
10877
|
+
this.next();
|
|
10878
|
+
break;
|
|
10879
|
+
case 'Home':
|
|
10880
|
+
event.preventDefault();
|
|
10881
|
+
this.goTo(0);
|
|
10882
|
+
break;
|
|
10883
|
+
case 'End':
|
|
10884
|
+
event.preventDefault();
|
|
10885
|
+
this.goTo(this.slides().length - 1);
|
|
10886
|
+
break;
|
|
10887
|
+
}
|
|
10888
|
+
}
|
|
10889
|
+
// Touch/swipe handlers
|
|
10890
|
+
onTouchStart(event) {
|
|
10891
|
+
this.startX = event.touches[0].clientX;
|
|
10892
|
+
this.startY = event.touches[0].clientY;
|
|
10893
|
+
this.isDragging = false;
|
|
10894
|
+
}
|
|
10895
|
+
onTouchMove(event) {
|
|
10896
|
+
if (!this.isDragging) {
|
|
10897
|
+
const deltaX = Math.abs(event.touches[0].clientX - this.startX);
|
|
10898
|
+
const deltaY = Math.abs(event.touches[0].clientY - this.startY);
|
|
10899
|
+
// Detect horizontal swipe
|
|
10900
|
+
if (deltaX > deltaY && deltaX > 10) {
|
|
10901
|
+
this.isDragging = true;
|
|
10902
|
+
}
|
|
10903
|
+
}
|
|
10904
|
+
}
|
|
10905
|
+
onTouchEnd(event) {
|
|
10906
|
+
if (!this.isDragging)
|
|
10907
|
+
return;
|
|
10908
|
+
const endX = event.changedTouches[0].clientX;
|
|
10909
|
+
const deltaX = endX - this.startX;
|
|
10910
|
+
if (Math.abs(deltaX) > 50) {
|
|
10911
|
+
if (deltaX > 0) {
|
|
10912
|
+
this.prev();
|
|
10913
|
+
}
|
|
10914
|
+
else {
|
|
10915
|
+
this.next();
|
|
10916
|
+
}
|
|
10917
|
+
}
|
|
10918
|
+
this.isDragging = false;
|
|
10919
|
+
}
|
|
10920
|
+
startAutoplay() {
|
|
10921
|
+
this.stopAutoplay();
|
|
10922
|
+
this.autoplayTimer = setInterval(() => {
|
|
10923
|
+
this.next();
|
|
10924
|
+
}, this.autoplaySpeed());
|
|
10925
|
+
}
|
|
10926
|
+
stopAutoplay() {
|
|
10927
|
+
if (this.autoplayTimer) {
|
|
10928
|
+
clearInterval(this.autoplayTimer);
|
|
10929
|
+
this.autoplayTimer = null;
|
|
10930
|
+
}
|
|
10931
|
+
}
|
|
10932
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsCarousel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10933
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsCarousel, isStandalone: true, selector: "ds-carousel", inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, autoplaySpeed: { classPropertyName: "autoplaySpeed", publicName: "autoplaySpeed", isSignal: true, isRequired: false, transformFunction: null }, effect: { classPropertyName: "effect", publicName: "effect", isSignal: true, isRequired: false, transformFunction: null }, dots: { classPropertyName: "dots", publicName: "dots", isSignal: true, isRequired: false, transformFunction: null }, dotsPosition: { classPropertyName: "dotsPosition", publicName: "dotsPosition", isSignal: true, isRequired: false, transformFunction: null }, arrows: { classPropertyName: "arrows", publicName: "arrows", isSignal: true, isRequired: false, transformFunction: null }, infinite: { classPropertyName: "infinite", publicName: "infinite", isSignal: true, isRequired: false, transformFunction: null }, pauseOnHover: { classPropertyName: "pauseOnHover", publicName: "pauseOnHover", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { slideChange: "slideChange" }, viewQueries: [{ propertyName: "trackElement", first: true, predicate: ["track"], descendants: true }, { propertyName: "slideElements", predicate: ["slideElement"], descendants: true }], ngImport: i0, template: "<div\n [class]=\"containerClasses()\"\n (mouseenter)=\"onMouseEnter()\"\n (mouseleave)=\"onMouseLeave()\"\n (keydown)=\"onKeydown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (touchmove)=\"onTouchMove($event)\"\n (touchend)=\"onTouchEnd($event)\"\n tabindex=\"0\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n [attr.aria-label]=\"'Carousel with ' + slides().length + ' slides'\"\n>\n <!-- Arrows -->\n @if (arrows() && slides().length > 1) {\n <button\n class=\"ds-carousel__arrow ds-carousel__arrow--left\"\n (click)=\"prev()\"\n [attr.aria-label]=\"'Previous slide'\"\n type=\"button\"\n >\n <fa-icon [icon]=\"icons.left\" />\n </button>\n\n <button\n class=\"ds-carousel__arrow ds-carousel__arrow--right\"\n (click)=\"next()\"\n [attr.aria-label]=\"'Next slide'\"\n type=\"button\"\n >\n <fa-icon [icon]=\"icons.right\" />\n </button>\n }\n\n <!-- Slides container -->\n <div class=\"ds-carousel__container\">\n <div\n class=\"ds-carousel__track\"\n #track\n [ngStyle]=\"trackStyle()\"\n role=\"list\"\n >\n @for (slide of slides(); track slide.id; let i = $index) {\n <div\n class=\"{{ slideClasses(i) }}\"\n #slideElement\n role=\"listitem\"\n [attr.aria-hidden]=\"i !== internalActiveIndex()\"\n [attr.aria-label]=\"'Slide ' + (i + 1) + ' of ' + slides().length\"\n >\n @if (slide.image) {\n <img\n [src]=\"slide.image\"\n [alt]=\"slide.alt || slide.title || 'Slide ' + (i + 1)\"\n class=\"ds-carousel__image\"\n />\n }\n\n @if (slide.title || slide.description) {\n <div class=\"ds-carousel__content\">\n @if (slide.title) {\n <h3 class=\"ds-carousel__title\">{{ slide.title }}</h3>\n }\n @if (slide.description) {\n <p class=\"ds-carousel__description\">{{ slide.description }}</p>\n }\n </div>\n }\n\n <!-- Content projection for custom slides -->\n <ng-content select=\"[carousel-slide]\" />\n </div>\n }\n </div>\n </div>\n\n <!-- Dots -->\n @if (dots() && slides().length > 1) {\n <div\n class=\"ds-carousel__dots\"\n role=\"tablist\"\n [attr.aria-label]=\"'Carousel navigation'\"\n >\n @for (slide of slides(); track slide.id; let i = $index) {\n <button\n type=\"button\"\n [class]=\"dotClasses(i)\"\n (click)=\"goTo(i)\"\n role=\"tab\"\n [attr.aria-selected]=\"i === internalActiveIndex()\"\n [attr.aria-label]=\"'Go to slide ' + (i + 1)\"\n [attr.aria-controls]=\"'carousel-slide-' + i\"\n >\n <span class=\"ds-carousel__dot-inner\"></span>\n </button>\n }\n </div>\n }\n</div>\n", styles: [".ds-carousel{position:relative;width:100%;overflow:hidden;background-color:var(--carousel-bg, var(--gray-50));border-radius:var(--carousel-radius, var(--radius-2));outline:none}.ds-carousel__container{position:relative;width:100%;height:400px;overflow:hidden}.ds-carousel__track{display:flex;height:100%;transition:transform .3s ease-in-out}.ds-carousel__slide{position:relative;flex:0 0 100%;width:100%;height:100%;display:flex;align-items:center;justify-content:center;opacity:1;transition:opacity .3s ease-in-out}.ds-carousel__slide--fade{position:absolute;top:0;left:0;opacity:0;transition:opacity .5s ease-in-out}.ds-carousel__slide--fade.ds-carousel__slide--active{opacity:1;z-index:1}.ds-carousel__image{width:100%;height:100%;object-fit:cover;display:block}.ds-carousel__content{position:absolute;bottom:0;left:0;right:0;padding:var(--carousel-content-padding, var(--space-6));background:var(--carousel-content-bg, linear-gradient(to top, rgba(0, 0, 0, .7), transparent));color:var(--carousel-content-text, var(--white))}.ds-carousel__title{margin:0 0 var(--space-2) 0;font-size:var(--carousel-title-size, var(--font-size-5));font-weight:var(--font-weight-bold, 700);line-height:1.2}.ds-carousel__description{margin:0;font-size:var(--carousel-description-size, var(--font-size-3));line-height:1.5;opacity:.95}.ds-carousel__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:10;display:flex;align-items:center;justify-content:center;width:var(--carousel-arrow-size, 40px);height:var(--carousel-arrow-size, 40px);padding:0;background-color:var(--carousel-arrow-bg, rgba(255, 255, 255, .9));color:var(--carousel-arrow-color, var(--gray-800));border:none;border-radius:var(--carousel-arrow-radius, 50%);cursor:pointer;transition:all .2s ease;box-shadow:var(--carousel-arrow-shadow, var(--shadow-md))}.ds-carousel__arrow:hover{background-color:var(--carousel-arrow-bg-hover, var(--white));color:var(--carousel-arrow-color-hover, var(--color-primary));transform:translateY(-50%) scale(1.1)}.ds-carousel__arrow:active{transform:translateY(-50%) scale(.95)}.ds-carousel__arrow:focus-visible{outline:2px solid var(--carousel-arrow-focus, var(--color-primary));outline-offset:2px}.ds-carousel__arrow--left{left:var(--carousel-arrow-offset, var(--space-4))}.ds-carousel__arrow--right{right:var(--carousel-arrow-offset, var(--space-4))}.ds-carousel__arrow fa-icon{font-size:var(--carousel-arrow-icon-size, var(--font-size-4))}.ds-carousel__dots{position:absolute;z-index:10;display:flex;gap:var(--carousel-dots-gap, var(--space-2));padding:var(--carousel-dots-padding, var(--space-4))}.ds-carousel--dots-bottom .ds-carousel__dots{bottom:0;left:50%;transform:translate(-50%);flex-direction:row}.ds-carousel--dots-top .ds-carousel__dots{top:0;left:50%;transform:translate(-50%);flex-direction:row}.ds-carousel--dots-left .ds-carousel__dots{top:50%;left:0;transform:translateY(-50%);flex-direction:column}.ds-carousel--dots-right .ds-carousel__dots{top:50%;right:0;transform:translateY(-50%);flex-direction:column}.ds-carousel__dot{padding:0;border:none;background:transparent;cursor:pointer;transition:all .3s ease}.ds-carousel__dot:focus-visible{outline:2px solid var(--carousel-dot-focus, var(--color-primary));outline-offset:2px;border-radius:50%}.ds-carousel__dot-inner{display:block;width:var(--carousel-dot-size, 10px);height:var(--carousel-dot-size, 10px);background-color:var(--carousel-dot-bg, rgba(255, 255, 255, .5));border-radius:50%;transition:all .3s ease}.ds-carousel__dot--active .ds-carousel__dot-inner{background-color:var(--carousel-dot-bg-active, var(--white));width:var(--carousel-dot-size-active, 12px);height:var(--carousel-dot-size-active, 12px)}.ds-carousel__dot:hover .ds-carousel__dot-inner{background-color:var(--carousel-dot-bg-hover, rgba(255, 255, 255, .8));transform:scale(1.2)}.ds-carousel--fade .ds-carousel__track{position:relative}.ds-carousel--fade .ds-carousel__slide{position:absolute;top:0;left:0}.ds-carousel--transitioning{-webkit-user-select:none;user-select:none}@media (max-width: 768px){.ds-carousel__container{height:300px}.ds-carousel__content{padding:var(--space-4)}.ds-carousel__title{font-size:var(--font-size-4)}.ds-carousel__description{font-size:var(--font-size-2)}.ds-carousel__arrow{width:32px;height:32px}.ds-carousel__arrow fa-icon{font-size:var(--font-size-3)}.ds-carousel__arrow--left,.ds-carousel__arrow--right{--carousel-arrow-offset: var(--space-2)}}@media (max-width: 480px){.ds-carousel__container{height:250px}.ds-carousel__arrow{width:28px;height:28px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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"] }] });
|
|
10934
|
+
}
|
|
10935
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsCarousel, decorators: [{
|
|
10936
|
+
type: Component,
|
|
10937
|
+
args: [{ selector: 'ds-carousel', imports: [CommonModule, FontAwesomeModule], template: "<div\n [class]=\"containerClasses()\"\n (mouseenter)=\"onMouseEnter()\"\n (mouseleave)=\"onMouseLeave()\"\n (keydown)=\"onKeydown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (touchmove)=\"onTouchMove($event)\"\n (touchend)=\"onTouchEnd($event)\"\n tabindex=\"0\"\n role=\"region\"\n aria-roledescription=\"carousel\"\n [attr.aria-label]=\"'Carousel with ' + slides().length + ' slides'\"\n>\n <!-- Arrows -->\n @if (arrows() && slides().length > 1) {\n <button\n class=\"ds-carousel__arrow ds-carousel__arrow--left\"\n (click)=\"prev()\"\n [attr.aria-label]=\"'Previous slide'\"\n type=\"button\"\n >\n <fa-icon [icon]=\"icons.left\" />\n </button>\n\n <button\n class=\"ds-carousel__arrow ds-carousel__arrow--right\"\n (click)=\"next()\"\n [attr.aria-label]=\"'Next slide'\"\n type=\"button\"\n >\n <fa-icon [icon]=\"icons.right\" />\n </button>\n }\n\n <!-- Slides container -->\n <div class=\"ds-carousel__container\">\n <div\n class=\"ds-carousel__track\"\n #track\n [ngStyle]=\"trackStyle()\"\n role=\"list\"\n >\n @for (slide of slides(); track slide.id; let i = $index) {\n <div\n class=\"{{ slideClasses(i) }}\"\n #slideElement\n role=\"listitem\"\n [attr.aria-hidden]=\"i !== internalActiveIndex()\"\n [attr.aria-label]=\"'Slide ' + (i + 1) + ' of ' + slides().length\"\n >\n @if (slide.image) {\n <img\n [src]=\"slide.image\"\n [alt]=\"slide.alt || slide.title || 'Slide ' + (i + 1)\"\n class=\"ds-carousel__image\"\n />\n }\n\n @if (slide.title || slide.description) {\n <div class=\"ds-carousel__content\">\n @if (slide.title) {\n <h3 class=\"ds-carousel__title\">{{ slide.title }}</h3>\n }\n @if (slide.description) {\n <p class=\"ds-carousel__description\">{{ slide.description }}</p>\n }\n </div>\n }\n\n <!-- Content projection for custom slides -->\n <ng-content select=\"[carousel-slide]\" />\n </div>\n }\n </div>\n </div>\n\n <!-- Dots -->\n @if (dots() && slides().length > 1) {\n <div\n class=\"ds-carousel__dots\"\n role=\"tablist\"\n [attr.aria-label]=\"'Carousel navigation'\"\n >\n @for (slide of slides(); track slide.id; let i = $index) {\n <button\n type=\"button\"\n [class]=\"dotClasses(i)\"\n (click)=\"goTo(i)\"\n role=\"tab\"\n [attr.aria-selected]=\"i === internalActiveIndex()\"\n [attr.aria-label]=\"'Go to slide ' + (i + 1)\"\n [attr.aria-controls]=\"'carousel-slide-' + i\"\n >\n <span class=\"ds-carousel__dot-inner\"></span>\n </button>\n }\n </div>\n }\n</div>\n", styles: [".ds-carousel{position:relative;width:100%;overflow:hidden;background-color:var(--carousel-bg, var(--gray-50));border-radius:var(--carousel-radius, var(--radius-2));outline:none}.ds-carousel__container{position:relative;width:100%;height:400px;overflow:hidden}.ds-carousel__track{display:flex;height:100%;transition:transform .3s ease-in-out}.ds-carousel__slide{position:relative;flex:0 0 100%;width:100%;height:100%;display:flex;align-items:center;justify-content:center;opacity:1;transition:opacity .3s ease-in-out}.ds-carousel__slide--fade{position:absolute;top:0;left:0;opacity:0;transition:opacity .5s ease-in-out}.ds-carousel__slide--fade.ds-carousel__slide--active{opacity:1;z-index:1}.ds-carousel__image{width:100%;height:100%;object-fit:cover;display:block}.ds-carousel__content{position:absolute;bottom:0;left:0;right:0;padding:var(--carousel-content-padding, var(--space-6));background:var(--carousel-content-bg, linear-gradient(to top, rgba(0, 0, 0, .7), transparent));color:var(--carousel-content-text, var(--white))}.ds-carousel__title{margin:0 0 var(--space-2) 0;font-size:var(--carousel-title-size, var(--font-size-5));font-weight:var(--font-weight-bold, 700);line-height:1.2}.ds-carousel__description{margin:0;font-size:var(--carousel-description-size, var(--font-size-3));line-height:1.5;opacity:.95}.ds-carousel__arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:10;display:flex;align-items:center;justify-content:center;width:var(--carousel-arrow-size, 40px);height:var(--carousel-arrow-size, 40px);padding:0;background-color:var(--carousel-arrow-bg, rgba(255, 255, 255, .9));color:var(--carousel-arrow-color, var(--gray-800));border:none;border-radius:var(--carousel-arrow-radius, 50%);cursor:pointer;transition:all .2s ease;box-shadow:var(--carousel-arrow-shadow, var(--shadow-md))}.ds-carousel__arrow:hover{background-color:var(--carousel-arrow-bg-hover, var(--white));color:var(--carousel-arrow-color-hover, var(--color-primary));transform:translateY(-50%) scale(1.1)}.ds-carousel__arrow:active{transform:translateY(-50%) scale(.95)}.ds-carousel__arrow:focus-visible{outline:2px solid var(--carousel-arrow-focus, var(--color-primary));outline-offset:2px}.ds-carousel__arrow--left{left:var(--carousel-arrow-offset, var(--space-4))}.ds-carousel__arrow--right{right:var(--carousel-arrow-offset, var(--space-4))}.ds-carousel__arrow fa-icon{font-size:var(--carousel-arrow-icon-size, var(--font-size-4))}.ds-carousel__dots{position:absolute;z-index:10;display:flex;gap:var(--carousel-dots-gap, var(--space-2));padding:var(--carousel-dots-padding, var(--space-4))}.ds-carousel--dots-bottom .ds-carousel__dots{bottom:0;left:50%;transform:translate(-50%);flex-direction:row}.ds-carousel--dots-top .ds-carousel__dots{top:0;left:50%;transform:translate(-50%);flex-direction:row}.ds-carousel--dots-left .ds-carousel__dots{top:50%;left:0;transform:translateY(-50%);flex-direction:column}.ds-carousel--dots-right .ds-carousel__dots{top:50%;right:0;transform:translateY(-50%);flex-direction:column}.ds-carousel__dot{padding:0;border:none;background:transparent;cursor:pointer;transition:all .3s ease}.ds-carousel__dot:focus-visible{outline:2px solid var(--carousel-dot-focus, var(--color-primary));outline-offset:2px;border-radius:50%}.ds-carousel__dot-inner{display:block;width:var(--carousel-dot-size, 10px);height:var(--carousel-dot-size, 10px);background-color:var(--carousel-dot-bg, rgba(255, 255, 255, .5));border-radius:50%;transition:all .3s ease}.ds-carousel__dot--active .ds-carousel__dot-inner{background-color:var(--carousel-dot-bg-active, var(--white));width:var(--carousel-dot-size-active, 12px);height:var(--carousel-dot-size-active, 12px)}.ds-carousel__dot:hover .ds-carousel__dot-inner{background-color:var(--carousel-dot-bg-hover, rgba(255, 255, 255, .8));transform:scale(1.2)}.ds-carousel--fade .ds-carousel__track{position:relative}.ds-carousel--fade .ds-carousel__slide{position:absolute;top:0;left:0}.ds-carousel--transitioning{-webkit-user-select:none;user-select:none}@media (max-width: 768px){.ds-carousel__container{height:300px}.ds-carousel__content{padding:var(--space-4)}.ds-carousel__title{font-size:var(--font-size-4)}.ds-carousel__description{font-size:var(--font-size-2)}.ds-carousel__arrow{width:32px;height:32px}.ds-carousel__arrow fa-icon{font-size:var(--font-size-3)}.ds-carousel__arrow--left,.ds-carousel__arrow--right{--carousel-arrow-offset: var(--space-2)}}@media (max-width: 480px){.ds-carousel__container{height:250px}.ds-carousel__arrow{width:28px;height:28px}}\n"] }]
|
|
10938
|
+
}], ctorParameters: () => [], propDecorators: { slides: [{ type: i0.Input, args: [{ isSignal: true, alias: "slides", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], autoplaySpeed: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplaySpeed", required: false }] }], effect: [{ type: i0.Input, args: [{ isSignal: true, alias: "effect", required: false }] }], dots: [{ type: i0.Input, args: [{ isSignal: true, alias: "dots", required: false }] }], dotsPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "dotsPosition", required: false }] }], arrows: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrows", required: false }] }], infinite: [{ type: i0.Input, args: [{ isSignal: true, alias: "infinite", required: false }] }], pauseOnHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "pauseOnHover", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }], slideChange: [{ type: i0.Output, args: ["slideChange"] }], trackElement: [{
|
|
10939
|
+
type: ViewChild,
|
|
10940
|
+
args: ['track', { static: false }]
|
|
10941
|
+
}], slideElements: [{
|
|
10942
|
+
type: ViewChildren,
|
|
10943
|
+
args: ['slideElement']
|
|
10944
|
+
}] } });
|
|
10945
|
+
|
|
10946
|
+
class DsNotificationService {
|
|
10947
|
+
notifications = signal([], ...(ngDevMode ? [{ debugName: "notifications" }] : []));
|
|
10948
|
+
nextId = 1;
|
|
10949
|
+
notifications$ = this.notifications.asReadonly();
|
|
10950
|
+
open(config) {
|
|
10951
|
+
const id = config.id || `notification-${this.nextId++}`;
|
|
10952
|
+
const notification = {
|
|
10953
|
+
...config,
|
|
10954
|
+
id,
|
|
10955
|
+
timestamp: Date.now(),
|
|
10956
|
+
closable: config.closable ?? true,
|
|
10957
|
+
duration: config.duration ?? 4500
|
|
10958
|
+
};
|
|
10959
|
+
// Set default icons based on type
|
|
10960
|
+
if (!notification.icon && notification.type) {
|
|
10961
|
+
notification.icon = this.getDefaultIcon(notification.type);
|
|
10962
|
+
}
|
|
10963
|
+
this.notifications.update(items => [...items, notification]);
|
|
10964
|
+
// Auto-dismiss if duration > 0
|
|
10965
|
+
if (notification.duration && notification.duration > 0) {
|
|
10966
|
+
setTimeout(() => {
|
|
10967
|
+
this.close(id);
|
|
10968
|
+
}, notification.duration);
|
|
10969
|
+
}
|
|
10970
|
+
return id;
|
|
10971
|
+
}
|
|
10972
|
+
info(title, message, config) {
|
|
10973
|
+
return this.open({
|
|
10974
|
+
...config,
|
|
10975
|
+
title,
|
|
10976
|
+
message,
|
|
10977
|
+
type: 'info'
|
|
10978
|
+
});
|
|
10979
|
+
}
|
|
10980
|
+
success(title, message, config) {
|
|
10981
|
+
return this.open({
|
|
10982
|
+
...config,
|
|
10983
|
+
title,
|
|
10984
|
+
message,
|
|
10985
|
+
type: 'success'
|
|
10986
|
+
});
|
|
10987
|
+
}
|
|
10988
|
+
warning(title, message, config) {
|
|
10989
|
+
return this.open({
|
|
10990
|
+
...config,
|
|
10991
|
+
title,
|
|
10992
|
+
message,
|
|
10993
|
+
type: 'warning'
|
|
10994
|
+
});
|
|
10995
|
+
}
|
|
10996
|
+
error(title, message, config) {
|
|
10997
|
+
return this.open({
|
|
10998
|
+
...config,
|
|
10999
|
+
title,
|
|
11000
|
+
message,
|
|
11001
|
+
type: 'error'
|
|
11002
|
+
});
|
|
11003
|
+
}
|
|
11004
|
+
close(id) {
|
|
11005
|
+
this.notifications.update(items => items.filter(item => item.id !== id));
|
|
11006
|
+
}
|
|
11007
|
+
closeAll() {
|
|
11008
|
+
this.notifications.set([]);
|
|
11009
|
+
}
|
|
11010
|
+
getDefaultIcon(type) {
|
|
11011
|
+
switch (type) {
|
|
11012
|
+
case 'info':
|
|
11013
|
+
return faCircleInfo;
|
|
11014
|
+
case 'success':
|
|
11015
|
+
return faCircleCheck;
|
|
11016
|
+
case 'warning':
|
|
11017
|
+
return faTriangleExclamation;
|
|
11018
|
+
case 'error':
|
|
11019
|
+
return faCircleXmark;
|
|
11020
|
+
default:
|
|
11021
|
+
return faCircleInfo;
|
|
11022
|
+
}
|
|
11023
|
+
}
|
|
11024
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsNotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
11025
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsNotificationService, providedIn: 'root' });
|
|
11026
|
+
}
|
|
11027
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsNotificationService, decorators: [{
|
|
11028
|
+
type: Injectable,
|
|
11029
|
+
args: [{
|
|
11030
|
+
providedIn: 'root'
|
|
11031
|
+
}]
|
|
11032
|
+
}] });
|
|
11033
|
+
|
|
11034
|
+
class DsNotificationItemComponent {
|
|
11035
|
+
notification = input.required(...(ngDevMode ? [{ debugName: "notification" }] : []));
|
|
11036
|
+
closeClick = output();
|
|
11037
|
+
actionClick = output();
|
|
11038
|
+
closeIcon = faXmark;
|
|
11039
|
+
notificationClasses = () => {
|
|
11040
|
+
const classes = ['ds-notification'];
|
|
11041
|
+
const notification = this.notification();
|
|
11042
|
+
if (notification.type) {
|
|
11043
|
+
classes.push(`ds-notification--${notification.type}`);
|
|
11044
|
+
}
|
|
11045
|
+
return classes;
|
|
11046
|
+
};
|
|
11047
|
+
onClose() {
|
|
11048
|
+
this.closeClick.emit(this.notification().id);
|
|
11049
|
+
}
|
|
11050
|
+
onActionClick(index) {
|
|
11051
|
+
const notification = this.notification();
|
|
11052
|
+
if (notification.actions && notification.actions[index]) {
|
|
11053
|
+
notification.actions[index].handler();
|
|
11054
|
+
this.actionClick.emit({ id: notification.id, actionIndex: index });
|
|
11055
|
+
}
|
|
11056
|
+
}
|
|
11057
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsNotificationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11058
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsNotificationItemComponent, isStandalone: true, selector: "ds-notification-item", inputs: { notification: { classPropertyName: "notification", publicName: "notification", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { closeClick: "closeClick", actionClick: "actionClick" }, ngImport: i0, template: "<div\n [class]=\"notificationClasses().join(' ')\"\n role=\"alert\"\n [attr.aria-live]=\"notification().type === 'error' ? 'assertive' : 'polite'\"\n [attr.aria-atomic]=\"true\"\n>\n <div class=\"ds-notification__header\">\n <div class=\"ds-notification__icon-title\">\n @if (notification().icon) {\n <fa-icon\n [icon]=\"notification().icon\"\n class=\"ds-notification__icon\"\n [attr.aria-hidden]=\"true\"\n />\n }\n <h4 class=\"ds-notification__title\">{{ notification().title }}</h4>\n </div>\n @if (notification().closable) {\n <button\n type=\"button\"\n class=\"ds-notification__close\"\n (click)=\"onClose()\"\n [attr.aria-label]=\"'Fermer la notification'\"\n >\n <fa-icon [icon]=\"closeIcon\" />\n </button>\n }\n </div>\n\n <div class=\"ds-notification__body\">\n <p class=\"ds-notification__message\">{{ notification().message }}</p>\n </div>\n\n @if (notification().actions && notification().actions!.length > 0) {\n <div class=\"ds-notification__actions\">\n @for (action of notification().actions!; track $index) {\n <button\n type=\"button\"\n class=\"ds-notification__action ds-notification__action--{{ action.variant || 'secondary' }}\"\n (click)=\"onActionClick($index)\"\n >\n {{ action.label }}\n </button>\n }\n </div>\n }\n</div>\n", styles: [".ds-notification-container{position:fixed;z-index:var(--notification-z-index, 1050);pointer-events:none;display:flex;flex-direction:column;gap:var(--notification-gap, var(--space-3, .75rem));max-width:var(--notification-max-width, 384px);width:100%}.ds-notification-container--topRight{top:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--topLeft{top:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomRight{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomLeft{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-wrapper{pointer-events:auto;animation:var(--notification-animation-in, slideInRight .3s ease-out)}@keyframes slideInRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slideInLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}.ds-notification{background:var(--notification-bg, var(--color-white, #ffffff));border:var(--notification-border-width, 1px) solid var(--notification-border-color, var(--gray-300, #d1d5db));border-radius:var(--notification-radius, var(--radius-2, .5rem));box-shadow:var(--notification-shadow, var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, .1)));padding:var(--notification-padding, var(--space-4, 1rem));display:flex;flex-direction:column;gap:var(--notification-gap-inner, var(--space-3, .75rem));width:100%}.ds-notification__header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-2, .5rem)}.ds-notification__icon-title{display:flex;align-items:center;gap:var(--notification-icon-gap, var(--space-2, .5rem));flex:1}.ds-notification__icon{font-size:var(--notification-icon-size, 1.25rem);flex-shrink:0;color:var(--notification-icon-color, var(--gray-500, #6b7280))}.ds-notification__title{margin:0;font-size:var(--notification-title-size, var(--font-size-base, 1rem));font-weight:var(--notification-title-weight, 600);color:var(--notification-title-color, var(--gray-900, #111827));line-height:1.4}.ds-notification__close{background:transparent;border:none;padding:var(--space-1, .25rem);cursor:pointer;color:var(--notification-close-color, var(--gray-400, #9ca3af));line-height:1;transition:color .2s ease;flex-shrink:0}.ds-notification__close:hover{color:var(--notification-close-hover-color, var(--gray-600, #4b5563))}.ds-notification__close:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px;border-radius:var(--radius-1, .25rem)}.ds-notification__body{padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__message{margin:0;font-size:var(--notification-message-size, var(--font-size-sm, .875rem));color:var(--notification-message-color, var(--gray-600, #4b5563));line-height:1.5}.ds-notification__actions{display:flex;gap:var(--space-2, .5rem);padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__action{padding:var(--space-2, .5rem) var(--space-3, .75rem);font-size:var(--font-size-sm, .875rem);font-weight:500;border-radius:var(--radius-1, .25rem);cursor:pointer;transition:all .2s ease;border:1px solid transparent}.ds-notification__action--primary{background:var(--color-primary, #3b82f6);color:var(--color-white, #ffffff);border-color:var(--color-primary, #3b82f6)}.ds-notification__action--primary:hover{background:var(--primary-600, #2563eb);border-color:var(--primary-600, #2563eb)}.ds-notification__action--secondary{background:var(--gray-100, #f3f4f6);color:var(--gray-700, #374151);border-color:var(--gray-300, #d1d5db)}.ds-notification__action--secondary:hover{background:var(--gray-200, #e5e7eb)}.ds-notification__action--ghost{background:transparent;color:var(--color-primary, #3b82f6)}.ds-notification__action--ghost:hover{background:var(--primary-50, #eff6ff)}.ds-notification__action:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px}.ds-notification--info .ds-notification__icon{color:var(--notification-info-icon, var(--color-primary, #3b82f6))}.ds-notification--success .ds-notification__icon{color:var(--notification-success-icon, var(--success, #10b981))}.ds-notification--warning .ds-notification__icon{color:var(--notification-warning-icon, var(--warning, #f59e0b))}.ds-notification--error .ds-notification__icon{color:var(--notification-error-icon, var(--error, #ef4444))}.ds-notification-container--topLeft .ds-notification-wrapper,.ds-notification-container--bottomLeft .ds-notification-wrapper{animation:slideInLeft .3s ease-out}\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"] }] });
|
|
11059
|
+
}
|
|
11060
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsNotificationItemComponent, decorators: [{
|
|
11061
|
+
type: Component,
|
|
11062
|
+
args: [{ selector: 'ds-notification-item', standalone: true, imports: [CommonModule, FontAwesomeModule], template: "<div\n [class]=\"notificationClasses().join(' ')\"\n role=\"alert\"\n [attr.aria-live]=\"notification().type === 'error' ? 'assertive' : 'polite'\"\n [attr.aria-atomic]=\"true\"\n>\n <div class=\"ds-notification__header\">\n <div class=\"ds-notification__icon-title\">\n @if (notification().icon) {\n <fa-icon\n [icon]=\"notification().icon\"\n class=\"ds-notification__icon\"\n [attr.aria-hidden]=\"true\"\n />\n }\n <h4 class=\"ds-notification__title\">{{ notification().title }}</h4>\n </div>\n @if (notification().closable) {\n <button\n type=\"button\"\n class=\"ds-notification__close\"\n (click)=\"onClose()\"\n [attr.aria-label]=\"'Fermer la notification'\"\n >\n <fa-icon [icon]=\"closeIcon\" />\n </button>\n }\n </div>\n\n <div class=\"ds-notification__body\">\n <p class=\"ds-notification__message\">{{ notification().message }}</p>\n </div>\n\n @if (notification().actions && notification().actions!.length > 0) {\n <div class=\"ds-notification__actions\">\n @for (action of notification().actions!; track $index) {\n <button\n type=\"button\"\n class=\"ds-notification__action ds-notification__action--{{ action.variant || 'secondary' }}\"\n (click)=\"onActionClick($index)\"\n >\n {{ action.label }}\n </button>\n }\n </div>\n }\n</div>\n", styles: [".ds-notification-container{position:fixed;z-index:var(--notification-z-index, 1050);pointer-events:none;display:flex;flex-direction:column;gap:var(--notification-gap, var(--space-3, .75rem));max-width:var(--notification-max-width, 384px);width:100%}.ds-notification-container--topRight{top:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--topLeft{top:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomRight{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomLeft{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-wrapper{pointer-events:auto;animation:var(--notification-animation-in, slideInRight .3s ease-out)}@keyframes slideInRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slideInLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}.ds-notification{background:var(--notification-bg, var(--color-white, #ffffff));border:var(--notification-border-width, 1px) solid var(--notification-border-color, var(--gray-300, #d1d5db));border-radius:var(--notification-radius, var(--radius-2, .5rem));box-shadow:var(--notification-shadow, var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, .1)));padding:var(--notification-padding, var(--space-4, 1rem));display:flex;flex-direction:column;gap:var(--notification-gap-inner, var(--space-3, .75rem));width:100%}.ds-notification__header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-2, .5rem)}.ds-notification__icon-title{display:flex;align-items:center;gap:var(--notification-icon-gap, var(--space-2, .5rem));flex:1}.ds-notification__icon{font-size:var(--notification-icon-size, 1.25rem);flex-shrink:0;color:var(--notification-icon-color, var(--gray-500, #6b7280))}.ds-notification__title{margin:0;font-size:var(--notification-title-size, var(--font-size-base, 1rem));font-weight:var(--notification-title-weight, 600);color:var(--notification-title-color, var(--gray-900, #111827));line-height:1.4}.ds-notification__close{background:transparent;border:none;padding:var(--space-1, .25rem);cursor:pointer;color:var(--notification-close-color, var(--gray-400, #9ca3af));line-height:1;transition:color .2s ease;flex-shrink:0}.ds-notification__close:hover{color:var(--notification-close-hover-color, var(--gray-600, #4b5563))}.ds-notification__close:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px;border-radius:var(--radius-1, .25rem)}.ds-notification__body{padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__message{margin:0;font-size:var(--notification-message-size, var(--font-size-sm, .875rem));color:var(--notification-message-color, var(--gray-600, #4b5563));line-height:1.5}.ds-notification__actions{display:flex;gap:var(--space-2, .5rem);padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__action{padding:var(--space-2, .5rem) var(--space-3, .75rem);font-size:var(--font-size-sm, .875rem);font-weight:500;border-radius:var(--radius-1, .25rem);cursor:pointer;transition:all .2s ease;border:1px solid transparent}.ds-notification__action--primary{background:var(--color-primary, #3b82f6);color:var(--color-white, #ffffff);border-color:var(--color-primary, #3b82f6)}.ds-notification__action--primary:hover{background:var(--primary-600, #2563eb);border-color:var(--primary-600, #2563eb)}.ds-notification__action--secondary{background:var(--gray-100, #f3f4f6);color:var(--gray-700, #374151);border-color:var(--gray-300, #d1d5db)}.ds-notification__action--secondary:hover{background:var(--gray-200, #e5e7eb)}.ds-notification__action--ghost{background:transparent;color:var(--color-primary, #3b82f6)}.ds-notification__action--ghost:hover{background:var(--primary-50, #eff6ff)}.ds-notification__action:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px}.ds-notification--info .ds-notification__icon{color:var(--notification-info-icon, var(--color-primary, #3b82f6))}.ds-notification--success .ds-notification__icon{color:var(--notification-success-icon, var(--success, #10b981))}.ds-notification--warning .ds-notification__icon{color:var(--notification-warning-icon, var(--warning, #f59e0b))}.ds-notification--error .ds-notification__icon{color:var(--notification-error-icon, var(--error, #ef4444))}.ds-notification-container--topLeft .ds-notification-wrapper,.ds-notification-container--bottomLeft .ds-notification-wrapper{animation:slideInLeft .3s ease-out}\n"] }]
|
|
11063
|
+
}], propDecorators: { notification: [{ type: i0.Input, args: [{ isSignal: true, alias: "notification", required: true }] }], closeClick: [{ type: i0.Output, args: ["closeClick"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }] } });
|
|
11064
|
+
|
|
11065
|
+
class DsNotificationContainerComponent {
|
|
11066
|
+
notificationService = inject(DsNotificationService);
|
|
11067
|
+
placement = input('topRight', ...(ngDevMode ? [{ debugName: "placement" }] : []));
|
|
11068
|
+
maxStack = input(5, ...(ngDevMode ? [{ debugName: "maxStack" }] : []));
|
|
11069
|
+
notifications = this.notificationService.notifications$;
|
|
11070
|
+
visibleNotifications = computed(() => {
|
|
11071
|
+
const all = this.notifications();
|
|
11072
|
+
const max = this.maxStack();
|
|
11073
|
+
return all.slice(-max);
|
|
11074
|
+
}, ...(ngDevMode ? [{ debugName: "visibleNotifications" }] : []));
|
|
11075
|
+
containerClasses = computed(() => {
|
|
11076
|
+
const classes = ['ds-notification-container'];
|
|
11077
|
+
classes.push(`ds-notification-container--${this.placement()}`);
|
|
11078
|
+
return classes.join(' ');
|
|
11079
|
+
}, ...(ngDevMode ? [{ debugName: "containerClasses" }] : []));
|
|
11080
|
+
onClose(id) {
|
|
11081
|
+
this.notificationService.close(id);
|
|
11082
|
+
}
|
|
11083
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsNotificationContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11084
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsNotificationContainerComponent, isStandalone: true, selector: "ds-notification-container", inputs: { placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, maxStack: { classPropertyName: "maxStack", publicName: "maxStack", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
11085
|
+
<div [class]="containerClasses()">
|
|
11086
|
+
@for (notification of visibleNotifications(); track notification.id) {
|
|
11087
|
+
<ds-notification-item
|
|
11088
|
+
[notification]="notification"
|
|
11089
|
+
(closeClick)="onClose($event)"
|
|
11090
|
+
class="ds-notification-wrapper"
|
|
11091
|
+
/>
|
|
11092
|
+
}
|
|
11093
|
+
</div>
|
|
11094
|
+
`, isInline: true, styles: [".ds-notification-container{position:fixed;z-index:var(--notification-z-index, 1050);pointer-events:none;display:flex;flex-direction:column;gap:var(--notification-gap, var(--space-3, .75rem));max-width:var(--notification-max-width, 384px);width:100%}.ds-notification-container--topRight{top:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--topLeft{top:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomRight{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomLeft{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-wrapper{pointer-events:auto;animation:var(--notification-animation-in, slideInRight .3s ease-out)}@keyframes slideInRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slideInLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}.ds-notification{background:var(--notification-bg, var(--color-white, #ffffff));border:var(--notification-border-width, 1px) solid var(--notification-border-color, var(--gray-300, #d1d5db));border-radius:var(--notification-radius, var(--radius-2, .5rem));box-shadow:var(--notification-shadow, var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, .1)));padding:var(--notification-padding, var(--space-4, 1rem));display:flex;flex-direction:column;gap:var(--notification-gap-inner, var(--space-3, .75rem));width:100%}.ds-notification__header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-2, .5rem)}.ds-notification__icon-title{display:flex;align-items:center;gap:var(--notification-icon-gap, var(--space-2, .5rem));flex:1}.ds-notification__icon{font-size:var(--notification-icon-size, 1.25rem);flex-shrink:0;color:var(--notification-icon-color, var(--gray-500, #6b7280))}.ds-notification__title{margin:0;font-size:var(--notification-title-size, var(--font-size-base, 1rem));font-weight:var(--notification-title-weight, 600);color:var(--notification-title-color, var(--gray-900, #111827));line-height:1.4}.ds-notification__close{background:transparent;border:none;padding:var(--space-1, .25rem);cursor:pointer;color:var(--notification-close-color, var(--gray-400, #9ca3af));line-height:1;transition:color .2s ease;flex-shrink:0}.ds-notification__close:hover{color:var(--notification-close-hover-color, var(--gray-600, #4b5563))}.ds-notification__close:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px;border-radius:var(--radius-1, .25rem)}.ds-notification__body{padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__message{margin:0;font-size:var(--notification-message-size, var(--font-size-sm, .875rem));color:var(--notification-message-color, var(--gray-600, #4b5563));line-height:1.5}.ds-notification__actions{display:flex;gap:var(--space-2, .5rem);padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__action{padding:var(--space-2, .5rem) var(--space-3, .75rem);font-size:var(--font-size-sm, .875rem);font-weight:500;border-radius:var(--radius-1, .25rem);cursor:pointer;transition:all .2s ease;border:1px solid transparent}.ds-notification__action--primary{background:var(--color-primary, #3b82f6);color:var(--color-white, #ffffff);border-color:var(--color-primary, #3b82f6)}.ds-notification__action--primary:hover{background:var(--primary-600, #2563eb);border-color:var(--primary-600, #2563eb)}.ds-notification__action--secondary{background:var(--gray-100, #f3f4f6);color:var(--gray-700, #374151);border-color:var(--gray-300, #d1d5db)}.ds-notification__action--secondary:hover{background:var(--gray-200, #e5e7eb)}.ds-notification__action--ghost{background:transparent;color:var(--color-primary, #3b82f6)}.ds-notification__action--ghost:hover{background:var(--primary-50, #eff6ff)}.ds-notification__action:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px}.ds-notification--info .ds-notification__icon{color:var(--notification-info-icon, var(--color-primary, #3b82f6))}.ds-notification--success .ds-notification__icon{color:var(--notification-success-icon, var(--success, #10b981))}.ds-notification--warning .ds-notification__icon{color:var(--notification-warning-icon, var(--warning, #f59e0b))}.ds-notification--error .ds-notification__icon{color:var(--notification-error-icon, var(--error, #ef4444))}.ds-notification-container--topLeft .ds-notification-wrapper,.ds-notification-container--bottomLeft .ds-notification-wrapper{animation:slideInLeft .3s ease-out}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsNotificationItemComponent, selector: "ds-notification-item", inputs: ["notification"], outputs: ["closeClick", "actionClick"] }] });
|
|
11095
|
+
}
|
|
11096
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsNotificationContainerComponent, decorators: [{
|
|
11097
|
+
type: Component,
|
|
11098
|
+
args: [{ selector: 'ds-notification-container', standalone: true, imports: [CommonModule, DsNotificationItemComponent], template: `
|
|
11099
|
+
<div [class]="containerClasses()">
|
|
11100
|
+
@for (notification of visibleNotifications(); track notification.id) {
|
|
11101
|
+
<ds-notification-item
|
|
11102
|
+
[notification]="notification"
|
|
11103
|
+
(closeClick)="onClose($event)"
|
|
11104
|
+
class="ds-notification-wrapper"
|
|
11105
|
+
/>
|
|
11106
|
+
}
|
|
11107
|
+
</div>
|
|
11108
|
+
`, styles: [".ds-notification-container{position:fixed;z-index:var(--notification-z-index, 1050);pointer-events:none;display:flex;flex-direction:column;gap:var(--notification-gap, var(--space-3, .75rem));max-width:var(--notification-max-width, 384px);width:100%}.ds-notification-container--topRight{top:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--topLeft{top:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomRight{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));right:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-container--bottomLeft{bottom:var(--notification-offset-y, var(--space-6, 1.5rem));left:var(--notification-offset-x, var(--space-6, 1.5rem))}.ds-notification-wrapper{pointer-events:auto;animation:var(--notification-animation-in, slideInRight .3s ease-out)}@keyframes slideInRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes slideInLeft{0%{transform:translate(-100%);opacity:0}to{transform:translate(0);opacity:1}}.ds-notification{background:var(--notification-bg, var(--color-white, #ffffff));border:var(--notification-border-width, 1px) solid var(--notification-border-color, var(--gray-300, #d1d5db));border-radius:var(--notification-radius, var(--radius-2, .5rem));box-shadow:var(--notification-shadow, var(--shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, .1)));padding:var(--notification-padding, var(--space-4, 1rem));display:flex;flex-direction:column;gap:var(--notification-gap-inner, var(--space-3, .75rem));width:100%}.ds-notification__header{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--space-2, .5rem)}.ds-notification__icon-title{display:flex;align-items:center;gap:var(--notification-icon-gap, var(--space-2, .5rem));flex:1}.ds-notification__icon{font-size:var(--notification-icon-size, 1.25rem);flex-shrink:0;color:var(--notification-icon-color, var(--gray-500, #6b7280))}.ds-notification__title{margin:0;font-size:var(--notification-title-size, var(--font-size-base, 1rem));font-weight:var(--notification-title-weight, 600);color:var(--notification-title-color, var(--gray-900, #111827));line-height:1.4}.ds-notification__close{background:transparent;border:none;padding:var(--space-1, .25rem);cursor:pointer;color:var(--notification-close-color, var(--gray-400, #9ca3af));line-height:1;transition:color .2s ease;flex-shrink:0}.ds-notification__close:hover{color:var(--notification-close-hover-color, var(--gray-600, #4b5563))}.ds-notification__close:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px;border-radius:var(--radius-1, .25rem)}.ds-notification__body{padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__message{margin:0;font-size:var(--notification-message-size, var(--font-size-sm, .875rem));color:var(--notification-message-color, var(--gray-600, #4b5563));line-height:1.5}.ds-notification__actions{display:flex;gap:var(--space-2, .5rem);padding-left:calc(var(--notification-icon-size, 1.25rem) + var(--notification-icon-gap, var(--space-2, .5rem)))}.ds-notification__action{padding:var(--space-2, .5rem) var(--space-3, .75rem);font-size:var(--font-size-sm, .875rem);font-weight:500;border-radius:var(--radius-1, .25rem);cursor:pointer;transition:all .2s ease;border:1px solid transparent}.ds-notification__action--primary{background:var(--color-primary, #3b82f6);color:var(--color-white, #ffffff);border-color:var(--color-primary, #3b82f6)}.ds-notification__action--primary:hover{background:var(--primary-600, #2563eb);border-color:var(--primary-600, #2563eb)}.ds-notification__action--secondary{background:var(--gray-100, #f3f4f6);color:var(--gray-700, #374151);border-color:var(--gray-300, #d1d5db)}.ds-notification__action--secondary:hover{background:var(--gray-200, #e5e7eb)}.ds-notification__action--ghost{background:transparent;color:var(--color-primary, #3b82f6)}.ds-notification__action--ghost:hover{background:var(--primary-50, #eff6ff)}.ds-notification__action:focus-visible{outline:2px solid var(--color-primary, #3b82f6);outline-offset:2px}.ds-notification--info .ds-notification__icon{color:var(--notification-info-icon, var(--color-primary, #3b82f6))}.ds-notification--success .ds-notification__icon{color:var(--notification-success-icon, var(--success, #10b981))}.ds-notification--warning .ds-notification__icon{color:var(--notification-warning-icon, var(--warning, #f59e0b))}.ds-notification--error .ds-notification__icon{color:var(--notification-error-icon, var(--error, #ef4444))}.ds-notification-container--topLeft .ds-notification-wrapper,.ds-notification-container--bottomLeft .ds-notification-wrapper{animation:slideInLeft .3s ease-out}\n"] }]
|
|
11109
|
+
}], propDecorators: { placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], maxStack: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxStack", required: false }] }] } });
|
|
11110
|
+
|
|
11111
|
+
/**
|
|
11112
|
+
* DsCalendar - Composant calendrier mensuel/annuel avec gestion d'événements
|
|
11113
|
+
*
|
|
11114
|
+
* @example
|
|
11115
|
+
* ```html
|
|
11116
|
+
* <ds-calendar
|
|
11117
|
+
* [value]="currentDate"
|
|
11118
|
+
* [events]="calendarEvents"
|
|
11119
|
+
* (dateSelect)="onDateSelect($event)"
|
|
11120
|
+
* (eventClick)="onEventClick($event)">
|
|
11121
|
+
* </ds-calendar>
|
|
11122
|
+
* ```
|
|
11123
|
+
*/
|
|
11124
|
+
class DsCalendar {
|
|
11125
|
+
// =========================================================================
|
|
11126
|
+
// INPUTS (Signals Angular 20)
|
|
11127
|
+
// =========================================================================
|
|
11128
|
+
/**
|
|
11129
|
+
* Date courante affichée
|
|
11130
|
+
*/
|
|
11131
|
+
value = input(new Date(), ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
11132
|
+
/**
|
|
11133
|
+
* Mode d'affichage (month ou year)
|
|
11134
|
+
*/
|
|
11135
|
+
mode = input('month', ...(ngDevMode ? [{ debugName: "mode" }] : []));
|
|
11136
|
+
/**
|
|
11137
|
+
* Événements à afficher dans le calendrier
|
|
11138
|
+
*/
|
|
11139
|
+
events = input([], ...(ngDevMode ? [{ debugName: "events" }] : []));
|
|
11140
|
+
/**
|
|
11141
|
+
* Taille du calendrier
|
|
11142
|
+
*/
|
|
11143
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
11144
|
+
/**
|
|
11145
|
+
* Locale pour les noms de jours et mois
|
|
11146
|
+
*/
|
|
11147
|
+
locale = input('fr-FR', ...(ngDevMode ? [{ debugName: "locale" }] : []));
|
|
11148
|
+
/**
|
|
11149
|
+
* Premier jour de la semaine (0=dimanche, 1=lundi)
|
|
11150
|
+
*/
|
|
11151
|
+
firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : []));
|
|
11152
|
+
/**
|
|
11153
|
+
* Fonction pour désactiver certaines dates
|
|
11154
|
+
*/
|
|
11155
|
+
disabledDate = input(undefined, ...(ngDevMode ? [{ debugName: "disabledDate" }] : []));
|
|
11156
|
+
// =========================================================================
|
|
11157
|
+
// OUTPUTS
|
|
11158
|
+
// =========================================================================
|
|
11159
|
+
/**
|
|
11160
|
+
* Émis lors de la sélection d'une date
|
|
11161
|
+
*/
|
|
11162
|
+
dateSelect = output();
|
|
11163
|
+
/**
|
|
11164
|
+
* Émis lors du changement de mois
|
|
11165
|
+
*/
|
|
11166
|
+
monthChange = output();
|
|
11167
|
+
/**
|
|
11168
|
+
* Émis lors du changement de mode
|
|
11169
|
+
*/
|
|
11170
|
+
modeChange = output();
|
|
11171
|
+
/**
|
|
11172
|
+
* Émis lors du clic sur un événement
|
|
11173
|
+
*/
|
|
11174
|
+
eventClick = output();
|
|
11175
|
+
// =========================================================================
|
|
11176
|
+
// ÉTAT INTERNE
|
|
11177
|
+
// =========================================================================
|
|
11178
|
+
/**
|
|
11179
|
+
* Date actuellement affichée (mois/année)
|
|
11180
|
+
*/
|
|
11181
|
+
displayDate = signal(new Date(), ...(ngDevMode ? [{ debugName: "displayDate" }] : []));
|
|
11182
|
+
/**
|
|
11183
|
+
* Mode actuel (interne)
|
|
11184
|
+
*/
|
|
11185
|
+
currentMode = signal('month', ...(ngDevMode ? [{ debugName: "currentMode" }] : []));
|
|
11186
|
+
// =========================================================================
|
|
11187
|
+
// ICÔNES FONTAWESOME
|
|
11188
|
+
// =========================================================================
|
|
11189
|
+
icons = {
|
|
11190
|
+
chevronLeft: faChevronLeft,
|
|
11191
|
+
chevronRight: faChevronRight,
|
|
11192
|
+
};
|
|
11193
|
+
// =========================================================================
|
|
11194
|
+
// COMPUTED SIGNALS
|
|
11195
|
+
// =========================================================================
|
|
11196
|
+
/**
|
|
11197
|
+
* Classes CSS de l'hôte
|
|
11198
|
+
*/
|
|
11199
|
+
hostClasses = computed(() => {
|
|
11200
|
+
const classes = ['ds-calendar'];
|
|
11201
|
+
classes.push(`ds-calendar--${this.size()}`);
|
|
11202
|
+
classes.push(`ds-calendar--${this.currentMode()}`);
|
|
11203
|
+
return classes.join(' ');
|
|
11204
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
|
|
11205
|
+
/**
|
|
11206
|
+
* Titre du calendrier (mois + année)
|
|
11207
|
+
*/
|
|
11208
|
+
calendarTitle = computed(() => {
|
|
11209
|
+
const date = this.displayDate();
|
|
11210
|
+
const locale = this.locale();
|
|
11211
|
+
if (this.currentMode() === 'year') {
|
|
11212
|
+
return date.getFullYear().toString();
|
|
11213
|
+
}
|
|
11214
|
+
const monthName = date.toLocaleDateString(locale, { month: 'long' });
|
|
11215
|
+
const year = date.getFullYear();
|
|
11216
|
+
return `${monthName.charAt(0).toUpperCase() + monthName.slice(1)} ${year}`;
|
|
11217
|
+
}, ...(ngDevMode ? [{ debugName: "calendarTitle" }] : []));
|
|
11218
|
+
/**
|
|
11219
|
+
* Noms des jours de la semaine
|
|
11220
|
+
*/
|
|
11221
|
+
weekDays = computed(() => {
|
|
11222
|
+
const locale = this.locale();
|
|
11223
|
+
const firstDay = this.firstDayOfWeek();
|
|
11224
|
+
const days = [];
|
|
11225
|
+
// Générer les noms des jours à partir du premier jour de la semaine
|
|
11226
|
+
for (let i = 0; i < 7; i++) {
|
|
11227
|
+
const date = new Date(2024, 0, firstDay + i); // Année 2024 (lundi = 1er janvier)
|
|
11228
|
+
const dayName = date.toLocaleDateString(locale, { weekday: 'short' });
|
|
11229
|
+
days.push(dayName.charAt(0).toUpperCase() + dayName.slice(1));
|
|
11230
|
+
}
|
|
11231
|
+
return days;
|
|
11232
|
+
}, ...(ngDevMode ? [{ debugName: "weekDays" }] : []));
|
|
11233
|
+
/**
|
|
11234
|
+
* Grille des jours du mois (6 semaines)
|
|
11235
|
+
*/
|
|
11236
|
+
calendarGrid = computed(() => {
|
|
11237
|
+
const date = this.displayDate();
|
|
11238
|
+
const firstDay = this.firstDayOfWeek();
|
|
11239
|
+
const events = this.events();
|
|
11240
|
+
const disabledFn = this.disabledDate();
|
|
11241
|
+
const today = new Date();
|
|
11242
|
+
today.setHours(0, 0, 0, 0);
|
|
11243
|
+
const year = date.getFullYear();
|
|
11244
|
+
const month = date.getMonth();
|
|
11245
|
+
// Premier jour du mois
|
|
11246
|
+
const firstDayOfMonth = new Date(year, month, 1);
|
|
11247
|
+
let startDay = firstDayOfMonth.getDay() - firstDay;
|
|
11248
|
+
if (startDay < 0)
|
|
11249
|
+
startDay += 7;
|
|
11250
|
+
// Calculer la date de début de la grille (peut être dans le mois précédent)
|
|
11251
|
+
const startDate = new Date(year, month, 1 - startDay);
|
|
11252
|
+
const days = [];
|
|
11253
|
+
// Générer 42 jours (6 semaines x 7 jours)
|
|
11254
|
+
for (let i = 0; i < 42; i++) {
|
|
11255
|
+
const currentDate = new Date(startDate);
|
|
11256
|
+
currentDate.setDate(startDate.getDate() + i);
|
|
11257
|
+
currentDate.setHours(0, 0, 0, 0);
|
|
11258
|
+
const isCurrentMonth = currentDate.getMonth() === month;
|
|
11259
|
+
const isToday = currentDate.getTime() === today.getTime();
|
|
11260
|
+
const isDisabled = disabledFn ? disabledFn(currentDate) : false;
|
|
11261
|
+
// Trouver les événements pour ce jour
|
|
11262
|
+
const dayEvents = events.filter((event) => {
|
|
11263
|
+
const eventDate = new Date(event.date);
|
|
11264
|
+
eventDate.setHours(0, 0, 0, 0);
|
|
11265
|
+
return eventDate.getTime() === currentDate.getTime();
|
|
11266
|
+
});
|
|
11267
|
+
days.push({
|
|
11268
|
+
date: currentDate,
|
|
11269
|
+
isCurrentMonth,
|
|
11270
|
+
isToday,
|
|
11271
|
+
isDisabled,
|
|
11272
|
+
events: dayEvents,
|
|
11273
|
+
});
|
|
11274
|
+
}
|
|
11275
|
+
return days;
|
|
11276
|
+
}, ...(ngDevMode ? [{ debugName: "calendarGrid" }] : []));
|
|
11277
|
+
/**
|
|
11278
|
+
* Grille des mois (vue année)
|
|
11279
|
+
*/
|
|
11280
|
+
monthGrid = computed(() => {
|
|
11281
|
+
const date = this.displayDate();
|
|
11282
|
+
const locale = this.locale();
|
|
11283
|
+
const currentMonth = new Date().getMonth();
|
|
11284
|
+
const currentYear = new Date().getFullYear();
|
|
11285
|
+
const displayYear = date.getFullYear();
|
|
11286
|
+
const months = [];
|
|
11287
|
+
for (let i = 0; i < 12; i++) {
|
|
11288
|
+
const monthDate = new Date(displayYear, i, 1);
|
|
11289
|
+
const monthName = monthDate.toLocaleDateString(locale, { month: 'long' });
|
|
11290
|
+
months.push({
|
|
11291
|
+
monthIndex: i,
|
|
11292
|
+
label: monthName.charAt(0).toUpperCase() + monthName.slice(1),
|
|
11293
|
+
isCurrentMonth: i === currentMonth && displayYear === currentYear,
|
|
11294
|
+
});
|
|
11295
|
+
}
|
|
11296
|
+
return months;
|
|
11297
|
+
}, ...(ngDevMode ? [{ debugName: "monthGrid" }] : []));
|
|
11298
|
+
// =========================================================================
|
|
11299
|
+
// EFFECTS
|
|
11300
|
+
// =========================================================================
|
|
11301
|
+
constructor() {
|
|
11302
|
+
// Synchroniser displayDate avec value au démarrage
|
|
11303
|
+
effect(() => {
|
|
11304
|
+
const value = this.value();
|
|
11305
|
+
this.displayDate.set(new Date(value));
|
|
11306
|
+
}, { allowSignalWrites: true });
|
|
11307
|
+
// Synchroniser currentMode avec mode
|
|
11308
|
+
effect(() => {
|
|
11309
|
+
this.currentMode.set(this.mode());
|
|
11310
|
+
}, { allowSignalWrites: true });
|
|
11311
|
+
}
|
|
11312
|
+
// =========================================================================
|
|
11313
|
+
// MÉTHODES PUBLIQUES
|
|
11314
|
+
// =========================================================================
|
|
11315
|
+
/**
|
|
11316
|
+
* Navigue vers le mois précédent
|
|
11317
|
+
*/
|
|
11318
|
+
previousMonth() {
|
|
11319
|
+
const current = this.displayDate();
|
|
11320
|
+
const newDate = new Date(current.getFullYear(), current.getMonth() - 1, 1);
|
|
11321
|
+
this.displayDate.set(newDate);
|
|
11322
|
+
this.monthChange.emit(newDate);
|
|
11323
|
+
}
|
|
11324
|
+
/**
|
|
11325
|
+
* Navigue vers le mois suivant
|
|
11326
|
+
*/
|
|
11327
|
+
nextMonth() {
|
|
11328
|
+
const current = this.displayDate();
|
|
11329
|
+
const newDate = new Date(current.getFullYear(), current.getMonth() + 1, 1);
|
|
11330
|
+
this.displayDate.set(newDate);
|
|
11331
|
+
this.monthChange.emit(newDate);
|
|
11332
|
+
}
|
|
11333
|
+
/**
|
|
11334
|
+
* Navigue vers l'année précédente
|
|
11335
|
+
*/
|
|
11336
|
+
previousYear() {
|
|
11337
|
+
const current = this.displayDate();
|
|
11338
|
+
const newDate = new Date(current.getFullYear() - 1, current.getMonth(), 1);
|
|
11339
|
+
this.displayDate.set(newDate);
|
|
11340
|
+
this.monthChange.emit(newDate);
|
|
11341
|
+
}
|
|
11342
|
+
/**
|
|
11343
|
+
* Navigue vers l'année suivante
|
|
11344
|
+
*/
|
|
11345
|
+
nextYear() {
|
|
11346
|
+
const current = this.displayDate();
|
|
11347
|
+
const newDate = new Date(current.getFullYear() + 1, current.getMonth(), 1);
|
|
11348
|
+
this.displayDate.set(newDate);
|
|
11349
|
+
this.monthChange.emit(newDate);
|
|
11350
|
+
}
|
|
11351
|
+
/**
|
|
11352
|
+
* Sélectionne une date
|
|
11353
|
+
*/
|
|
11354
|
+
selectDate(day) {
|
|
11355
|
+
if (day.isDisabled)
|
|
11356
|
+
return;
|
|
11357
|
+
this.dateSelect.emit(new Date(day.date));
|
|
11358
|
+
}
|
|
11359
|
+
/**
|
|
11360
|
+
* Sélectionne un mois (en mode année)
|
|
11361
|
+
*/
|
|
11362
|
+
selectMonth(month) {
|
|
11363
|
+
const current = this.displayDate();
|
|
11364
|
+
const newDate = new Date(current.getFullYear(), month.monthIndex, 1);
|
|
11365
|
+
this.displayDate.set(newDate);
|
|
11366
|
+
this.currentMode.set('month');
|
|
11367
|
+
this.modeChange.emit('month');
|
|
11368
|
+
}
|
|
11369
|
+
/**
|
|
11370
|
+
* Toggle entre mode mois et année
|
|
11371
|
+
*/
|
|
11372
|
+
toggleMode() {
|
|
11373
|
+
const newMode = this.currentMode() === 'month' ? 'year' : 'month';
|
|
11374
|
+
this.currentMode.set(newMode);
|
|
11375
|
+
this.modeChange.emit(newMode);
|
|
11376
|
+
}
|
|
11377
|
+
/**
|
|
11378
|
+
* Gère le clic sur un événement
|
|
11379
|
+
*/
|
|
11380
|
+
onEventClick(event, mouseEvent) {
|
|
11381
|
+
mouseEvent.stopPropagation();
|
|
11382
|
+
this.eventClick.emit(event);
|
|
11383
|
+
}
|
|
11384
|
+
/**
|
|
11385
|
+
* Retourne les classes CSS d'un jour
|
|
11386
|
+
*/
|
|
11387
|
+
getDayClasses(day) {
|
|
11388
|
+
const classes = ['ds-calendar__day'];
|
|
11389
|
+
if (!day.isCurrentMonth) {
|
|
11390
|
+
classes.push('ds-calendar__day--other-month');
|
|
11391
|
+
}
|
|
11392
|
+
if (day.isToday) {
|
|
11393
|
+
classes.push('ds-calendar__day--today');
|
|
11394
|
+
}
|
|
11395
|
+
if (day.isDisabled) {
|
|
11396
|
+
classes.push('ds-calendar__day--disabled');
|
|
11397
|
+
}
|
|
11398
|
+
if (day.events.length > 0) {
|
|
11399
|
+
classes.push('ds-calendar__day--has-events');
|
|
11400
|
+
}
|
|
11401
|
+
return classes.join(' ');
|
|
11402
|
+
}
|
|
11403
|
+
/**
|
|
11404
|
+
* Retourne les classes CSS d'un mois
|
|
11405
|
+
*/
|
|
11406
|
+
getMonthClasses(month) {
|
|
11407
|
+
const classes = ['ds-calendar__month'];
|
|
11408
|
+
if (month.isCurrentMonth) {
|
|
11409
|
+
classes.push('ds-calendar__month--current');
|
|
11410
|
+
}
|
|
11411
|
+
return classes.join(' ');
|
|
11412
|
+
}
|
|
11413
|
+
/**
|
|
11414
|
+
* Retourne les classes CSS d'un événement
|
|
11415
|
+
*/
|
|
11416
|
+
getEventClasses(event) {
|
|
11417
|
+
const classes = ['ds-calendar__event'];
|
|
11418
|
+
if (event.type) {
|
|
11419
|
+
classes.push(`ds-calendar__event--${event.type}`);
|
|
11420
|
+
}
|
|
11421
|
+
return classes.join(' ');
|
|
11422
|
+
}
|
|
11423
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsCalendar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11424
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DsCalendar, isStandalone: true, selector: "ds-calendar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, disabledDate: { classPropertyName: "disabledDate", publicName: "disabledDate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateSelect: "dateSelect", monthChange: "monthChange", modeChange: "modeChange", eventClick: "eventClick" }, host: { properties: { "class": "hostClasses()" }, classAttribute: "ds-calendar" }, ngImport: i0, template: "<div class=\"ds-calendar__container\">\n <!-- Header avec navigation et s\u00E9lecteur mode -->\n <div class=\"ds-calendar__header\">\n <div class=\"ds-calendar__nav\">\n @if (currentMode() === 'month') {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"previousMonth()\"\n aria-label=\"Mois pr\u00E9c\u00E9dent\"\n >\n <fa-icon [icon]=\"icons.chevronLeft\"></fa-icon>\n </button>\n } @else {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"previousYear()\"\n aria-label=\"Ann\u00E9e pr\u00E9c\u00E9dente\"\n >\n <fa-icon [icon]=\"icons.chevronLeft\"></fa-icon>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"ds-calendar__title\"\n (click)=\"toggleMode()\"\n [attr.aria-label]=\"currentMode() === 'month' ? 'Voir l\\'ann\u00E9e' : 'Voir le mois'\"\n >\n {{ calendarTitle() }}\n </button>\n\n @if (currentMode() === 'month') {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"nextMonth()\"\n aria-label=\"Mois suivant\"\n >\n <fa-icon [icon]=\"icons.chevronRight\"></fa-icon>\n </button>\n } @else {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"nextYear()\"\n aria-label=\"Ann\u00E9e suivante\"\n >\n <fa-icon [icon]=\"icons.chevronRight\"></fa-icon>\n </button>\n }\n </div>\n\n <div class=\"ds-calendar__mode-selector\">\n <button\n type=\"button\"\n class=\"ds-calendar__mode-btn\"\n [class.ds-calendar__mode-btn--active]=\"currentMode() === 'month'\"\n (click)=\"currentMode() === 'year' && toggleMode()\"\n >\n Mois\n </button>\n <button\n type=\"button\"\n class=\"ds-calendar__mode-btn\"\n [class.ds-calendar__mode-btn--active]=\"currentMode() === 'year'\"\n (click)=\"currentMode() === 'month' && toggleMode()\"\n >\n Ann\u00E9e\n </button>\n </div>\n </div>\n\n <!-- Vue mois -->\n @if (currentMode() === 'month') {\n <div class=\"ds-calendar__month-view\">\n <!-- Noms des jours de la semaine -->\n <div class=\"ds-calendar__weekdays\">\n @for (day of weekDays(); track day) {\n <div class=\"ds-calendar__weekday\">{{ day }}</div>\n }\n </div>\n\n <!-- Grille des jours -->\n <div class=\"ds-calendar__grid\">\n @for (day of calendarGrid(); track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"getDayClasses(day)\"\n [disabled]=\"day.isDisabled\"\n (click)=\"selectDate(day)\"\n [attr.aria-label]=\"day.date.toLocaleDateString(locale())\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n >\n <span class=\"ds-calendar__day-number\">{{ day.date.getDate() }}</span>\n\n @if (day.events.length > 0) {\n <div class=\"ds-calendar__events\">\n @for (event of day.events; track event.id) {\n <div\n [class]=\"getEventClasses(event)\"\n [title]=\"event.title\"\n (click)=\"onEventClick(event, $event)\"\n role=\"button\"\n [attr.aria-label]=\"event.title\"\n >\n <span class=\"ds-calendar__event-dot\"></span>\n @if (size() === 'lg') {\n <span class=\"ds-calendar__event-title\">{{ event.title }}</span>\n }\n </div>\n }\n </div>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Vue ann\u00E9e -->\n @if (currentMode() === 'year') {\n <div class=\"ds-calendar__year-view\">\n <div class=\"ds-calendar__months-grid\">\n @for (month of monthGrid(); track month.monthIndex) {\n <button\n type=\"button\"\n [class]=\"getMonthClasses(month)\"\n (click)=\"selectMonth(month)\"\n [attr.aria-label]=\"month.label\"\n [attr.aria-current]=\"month.isCurrentMonth ? 'true' : null\"\n >\n {{ month.label }}\n </button>\n }\n </div>\n </div>\n }\n</div>\n", styles: [".ds-calendar{display:block;width:100%}.ds-calendar__container{background:var(--calendar-bg, var(--white));border:1px solid var(--calendar-border, var(--gray-200));border-radius:var(--calendar-radius, var(--radius-2));overflow:hidden}.ds-calendar__header{display:flex;align-items:center;justify-content:space-between;padding:var(--calendar-header-padding, var(--space-4));border-bottom:1px solid var(--calendar-border, var(--gray-200));background:var(--calendar-header-bg, var(--gray-50))}.ds-calendar__nav{display:flex;align-items:center;gap:var(--calendar-nav-gap, var(--space-2))}.ds-calendar__nav-btn{display:inline-flex;align-items:center;justify-content:center;width:var(--calendar-nav-btn-size, 32px);height:var(--calendar-nav-btn-size, 32px);padding:0;background:transparent;border:1px solid var(--calendar-nav-btn-border, var(--gray-300));border-radius:var(--calendar-nav-btn-radius, var(--radius-1));color:var(--calendar-nav-btn-color, var(--gray-700));font-size:var(--calendar-nav-btn-font-size, var(--font-size-3));cursor:pointer;transition:all .2s ease}.ds-calendar__nav-btn:hover:not(:disabled){background:var(--calendar-nav-btn-hover-bg, var(--gray-100));border-color:var(--calendar-nav-btn-hover-border, var(--gray-400));color:var(--calendar-nav-btn-hover-color, var(--gray-900))}.ds-calendar__nav-btn:active:not(:disabled){transform:scale(.95)}.ds-calendar__nav-btn:disabled{opacity:.5;cursor:not-allowed}.ds-calendar__title{padding:var(--calendar-title-padding, var(--space-2) var(--space-3));background:transparent;border:1px solid transparent;border-radius:var(--calendar-title-radius, var(--radius-1));color:var(--calendar-title-color, var(--gray-900));font-size:var(--calendar-title-font-size, var(--font-size-4));font-weight:var(--calendar-title-font-weight, 600);cursor:pointer;transition:all .2s ease}.ds-calendar__title:hover{background:var(--calendar-title-hover-bg, var(--gray-100));border-color:var(--calendar-title-hover-border, var(--gray-300))}.ds-calendar__mode-selector{display:flex;gap:var(--calendar-mode-gap, var(--space-1));background:var(--calendar-mode-bg, var(--white));border:1px solid var(--calendar-mode-border, var(--gray-300));border-radius:var(--calendar-mode-radius, var(--radius-1));padding:var(--calendar-mode-padding, 2px)}.ds-calendar__mode-btn{padding:var(--calendar-mode-btn-padding, var(--space-1) var(--space-3));background:transparent;border:none;border-radius:var(--calendar-mode-btn-radius, var(--radius-1));color:var(--calendar-mode-btn-color, var(--gray-700));font-size:var(--calendar-mode-btn-font-size, var(--font-size-2));cursor:pointer;transition:all .2s ease}.ds-calendar__mode-btn:hover{color:var(--calendar-mode-btn-hover-color, var(--gray-900))}.ds-calendar__mode-btn--active{background:var(--calendar-mode-btn-active-bg, var(--color-primary));color:var(--calendar-mode-btn-active-color, var(--white))}.ds-calendar__month-view{padding:var(--calendar-month-view-padding, var(--space-4))}.ds-calendar__weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--calendar-weekday-gap, var(--space-1));margin-bottom:var(--calendar-weekday-margin, var(--space-2))}.ds-calendar__weekday{text-align:center;color:var(--calendar-weekday-color, var(--gray-600));font-size:var(--calendar-weekday-font-size, var(--font-size-2));font-weight:var(--calendar-weekday-font-weight, 600);text-transform:uppercase;padding:var(--calendar-weekday-padding, var(--space-2) 0)}.ds-calendar__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--calendar-grid-gap, var(--space-1))}.ds-calendar__day{position:relative;aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;padding:var(--calendar-day-padding, var(--space-2));background:var(--calendar-day-bg, transparent);border:1px solid var(--calendar-day-border, transparent);border-radius:var(--calendar-day-radius, var(--radius-1));color:var(--calendar-day-color, var(--gray-900));font-size:var(--calendar-day-font-size, var(--font-size-3));cursor:pointer;transition:all .2s ease}.ds-calendar__day:hover:not(:disabled){background:var(--calendar-day-hover-bg, var(--gray-100));border-color:var(--calendar-day-hover-border, var(--gray-300))}.ds-calendar__day--other-month{color:var(--calendar-day-other-month-color, var(--gray-400))}.ds-calendar__day--today{background:var(--calendar-day-today-bg, var(--blue-50));border-color:var(--calendar-day-today-border, var(--color-primary));color:var(--calendar-day-today-color, var(--color-primary));font-weight:600}.ds-calendar__day--disabled{opacity:.4;cursor:not-allowed;background:var(--calendar-day-disabled-bg, var(--gray-50))}.ds-calendar__day--has-events .ds-calendar__day-number{font-weight:600}.ds-calendar__day-number{line-height:1;margin-bottom:var(--calendar-day-number-margin, var(--space-1))}.ds-calendar__events{display:flex;flex-direction:column;gap:var(--calendar-events-gap, 2px);width:100%;margin-top:auto}.ds-calendar__event{display:flex;align-items:center;gap:var(--calendar-event-gap, var(--space-1));padding:var(--calendar-event-padding, 2px);border-radius:var(--calendar-event-radius, var(--radius-1));cursor:pointer;transition:all .2s ease}.ds-calendar__event:hover{transform:scale(1.05)}.ds-calendar__event-dot{width:var(--calendar-event-dot-size, 6px);height:var(--calendar-event-dot-size, 6px);border-radius:50%;background:var(--calendar-event-dot-color, var(--gray-500));flex-shrink:0}.ds-calendar__event-title{font-size:var(--calendar-event-title-font-size, var(--font-size-1));color:var(--calendar-event-title-color, var(--gray-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ds-calendar__event--success .ds-calendar__event-dot{background:var(--calendar-event-success-color, var(--success))}.ds-calendar__event--warning .ds-calendar__event-dot{background:var(--calendar-event-warning-color, var(--warning))}.ds-calendar__event--error .ds-calendar__event-dot{background:var(--calendar-event-error-color, var(--error))}.ds-calendar__year-view{padding:var(--calendar-year-view-padding, var(--space-4))}.ds-calendar__months-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--calendar-months-gap, var(--space-3))}.ds-calendar__month{padding:var(--calendar-month-padding, var(--space-4));background:var(--calendar-month-bg, transparent);border:1px solid var(--calendar-month-border, var(--gray-200));border-radius:var(--calendar-month-radius, var(--radius-2));color:var(--calendar-month-color, var(--gray-900));font-size:var(--calendar-month-font-size, var(--font-size-3));font-weight:500;cursor:pointer;transition:all .2s ease;text-align:center}.ds-calendar__month:hover{background:var(--calendar-month-hover-bg, var(--gray-50));border-color:var(--calendar-month-hover-border, var(--gray-300))}.ds-calendar__month--current{background:var(--calendar-month-current-bg, var(--blue-50));border-color:var(--calendar-month-current-border, var(--color-primary));color:var(--calendar-month-current-color, var(--color-primary));font-weight:600}.ds-calendar--sm .ds-calendar__header{padding:var(--calendar-header-padding-sm, var(--space-2))}.ds-calendar--sm .ds-calendar__title{font-size:var(--calendar-title-font-size-sm, var(--font-size-3))}.ds-calendar--sm .ds-calendar__weekday{font-size:var(--calendar-weekday-font-size-sm, var(--font-size-1))}.ds-calendar--sm .ds-calendar__day{padding:var(--calendar-day-padding-sm, var(--space-1));font-size:var(--calendar-day-font-size-sm, var(--font-size-2))}.ds-calendar--sm .ds-calendar__month{padding:var(--calendar-month-padding-sm, var(--space-2));font-size:var(--calendar-month-font-size-sm, var(--font-size-2))}.ds-calendar--lg .ds-calendar__header{padding:var(--calendar-header-padding-lg, var(--space-6))}.ds-calendar--lg .ds-calendar__title{font-size:var(--calendar-title-font-size-lg, var(--font-size-5))}.ds-calendar--lg .ds-calendar__weekday{font-size:var(--calendar-weekday-font-size-lg, var(--font-size-3))}.ds-calendar--lg .ds-calendar__day{padding:var(--calendar-day-padding-lg, var(--space-3));font-size:var(--calendar-day-font-size-lg, var(--font-size-4))}.ds-calendar--lg .ds-calendar__month{padding:var(--calendar-month-padding-lg, var(--space-6));font-size:var(--calendar-month-font-size-lg, var(--font-size-4))}\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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
11425
|
+
}
|
|
11426
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DsCalendar, decorators: [{
|
|
11427
|
+
type: Component,
|
|
11428
|
+
args: [{ selector: 'ds-calendar', standalone: true, imports: [CommonModule, FontAwesomeModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
11429
|
+
class: 'ds-calendar',
|
|
11430
|
+
'[class]': 'hostClasses()',
|
|
11431
|
+
}, template: "<div class=\"ds-calendar__container\">\n <!-- Header avec navigation et s\u00E9lecteur mode -->\n <div class=\"ds-calendar__header\">\n <div class=\"ds-calendar__nav\">\n @if (currentMode() === 'month') {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"previousMonth()\"\n aria-label=\"Mois pr\u00E9c\u00E9dent\"\n >\n <fa-icon [icon]=\"icons.chevronLeft\"></fa-icon>\n </button>\n } @else {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"previousYear()\"\n aria-label=\"Ann\u00E9e pr\u00E9c\u00E9dente\"\n >\n <fa-icon [icon]=\"icons.chevronLeft\"></fa-icon>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"ds-calendar__title\"\n (click)=\"toggleMode()\"\n [attr.aria-label]=\"currentMode() === 'month' ? 'Voir l\\'ann\u00E9e' : 'Voir le mois'\"\n >\n {{ calendarTitle() }}\n </button>\n\n @if (currentMode() === 'month') {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"nextMonth()\"\n aria-label=\"Mois suivant\"\n >\n <fa-icon [icon]=\"icons.chevronRight\"></fa-icon>\n </button>\n } @else {\n <button\n type=\"button\"\n class=\"ds-calendar__nav-btn\"\n (click)=\"nextYear()\"\n aria-label=\"Ann\u00E9e suivante\"\n >\n <fa-icon [icon]=\"icons.chevronRight\"></fa-icon>\n </button>\n }\n </div>\n\n <div class=\"ds-calendar__mode-selector\">\n <button\n type=\"button\"\n class=\"ds-calendar__mode-btn\"\n [class.ds-calendar__mode-btn--active]=\"currentMode() === 'month'\"\n (click)=\"currentMode() === 'year' && toggleMode()\"\n >\n Mois\n </button>\n <button\n type=\"button\"\n class=\"ds-calendar__mode-btn\"\n [class.ds-calendar__mode-btn--active]=\"currentMode() === 'year'\"\n (click)=\"currentMode() === 'month' && toggleMode()\"\n >\n Ann\u00E9e\n </button>\n </div>\n </div>\n\n <!-- Vue mois -->\n @if (currentMode() === 'month') {\n <div class=\"ds-calendar__month-view\">\n <!-- Noms des jours de la semaine -->\n <div class=\"ds-calendar__weekdays\">\n @for (day of weekDays(); track day) {\n <div class=\"ds-calendar__weekday\">{{ day }}</div>\n }\n </div>\n\n <!-- Grille des jours -->\n <div class=\"ds-calendar__grid\">\n @for (day of calendarGrid(); track day.date.getTime()) {\n <button\n type=\"button\"\n [class]=\"getDayClasses(day)\"\n [disabled]=\"day.isDisabled\"\n (click)=\"selectDate(day)\"\n [attr.aria-label]=\"day.date.toLocaleDateString(locale())\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n >\n <span class=\"ds-calendar__day-number\">{{ day.date.getDate() }}</span>\n\n @if (day.events.length > 0) {\n <div class=\"ds-calendar__events\">\n @for (event of day.events; track event.id) {\n <div\n [class]=\"getEventClasses(event)\"\n [title]=\"event.title\"\n (click)=\"onEventClick(event, $event)\"\n role=\"button\"\n [attr.aria-label]=\"event.title\"\n >\n <span class=\"ds-calendar__event-dot\"></span>\n @if (size() === 'lg') {\n <span class=\"ds-calendar__event-title\">{{ event.title }}</span>\n }\n </div>\n }\n </div>\n }\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Vue ann\u00E9e -->\n @if (currentMode() === 'year') {\n <div class=\"ds-calendar__year-view\">\n <div class=\"ds-calendar__months-grid\">\n @for (month of monthGrid(); track month.monthIndex) {\n <button\n type=\"button\"\n [class]=\"getMonthClasses(month)\"\n (click)=\"selectMonth(month)\"\n [attr.aria-label]=\"month.label\"\n [attr.aria-current]=\"month.isCurrentMonth ? 'true' : null\"\n >\n {{ month.label }}\n </button>\n }\n </div>\n </div>\n }\n</div>\n", styles: [".ds-calendar{display:block;width:100%}.ds-calendar__container{background:var(--calendar-bg, var(--white));border:1px solid var(--calendar-border, var(--gray-200));border-radius:var(--calendar-radius, var(--radius-2));overflow:hidden}.ds-calendar__header{display:flex;align-items:center;justify-content:space-between;padding:var(--calendar-header-padding, var(--space-4));border-bottom:1px solid var(--calendar-border, var(--gray-200));background:var(--calendar-header-bg, var(--gray-50))}.ds-calendar__nav{display:flex;align-items:center;gap:var(--calendar-nav-gap, var(--space-2))}.ds-calendar__nav-btn{display:inline-flex;align-items:center;justify-content:center;width:var(--calendar-nav-btn-size, 32px);height:var(--calendar-nav-btn-size, 32px);padding:0;background:transparent;border:1px solid var(--calendar-nav-btn-border, var(--gray-300));border-radius:var(--calendar-nav-btn-radius, var(--radius-1));color:var(--calendar-nav-btn-color, var(--gray-700));font-size:var(--calendar-nav-btn-font-size, var(--font-size-3));cursor:pointer;transition:all .2s ease}.ds-calendar__nav-btn:hover:not(:disabled){background:var(--calendar-nav-btn-hover-bg, var(--gray-100));border-color:var(--calendar-nav-btn-hover-border, var(--gray-400));color:var(--calendar-nav-btn-hover-color, var(--gray-900))}.ds-calendar__nav-btn:active:not(:disabled){transform:scale(.95)}.ds-calendar__nav-btn:disabled{opacity:.5;cursor:not-allowed}.ds-calendar__title{padding:var(--calendar-title-padding, var(--space-2) var(--space-3));background:transparent;border:1px solid transparent;border-radius:var(--calendar-title-radius, var(--radius-1));color:var(--calendar-title-color, var(--gray-900));font-size:var(--calendar-title-font-size, var(--font-size-4));font-weight:var(--calendar-title-font-weight, 600);cursor:pointer;transition:all .2s ease}.ds-calendar__title:hover{background:var(--calendar-title-hover-bg, var(--gray-100));border-color:var(--calendar-title-hover-border, var(--gray-300))}.ds-calendar__mode-selector{display:flex;gap:var(--calendar-mode-gap, var(--space-1));background:var(--calendar-mode-bg, var(--white));border:1px solid var(--calendar-mode-border, var(--gray-300));border-radius:var(--calendar-mode-radius, var(--radius-1));padding:var(--calendar-mode-padding, 2px)}.ds-calendar__mode-btn{padding:var(--calendar-mode-btn-padding, var(--space-1) var(--space-3));background:transparent;border:none;border-radius:var(--calendar-mode-btn-radius, var(--radius-1));color:var(--calendar-mode-btn-color, var(--gray-700));font-size:var(--calendar-mode-btn-font-size, var(--font-size-2));cursor:pointer;transition:all .2s ease}.ds-calendar__mode-btn:hover{color:var(--calendar-mode-btn-hover-color, var(--gray-900))}.ds-calendar__mode-btn--active{background:var(--calendar-mode-btn-active-bg, var(--color-primary));color:var(--calendar-mode-btn-active-color, var(--white))}.ds-calendar__month-view{padding:var(--calendar-month-view-padding, var(--space-4))}.ds-calendar__weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--calendar-weekday-gap, var(--space-1));margin-bottom:var(--calendar-weekday-margin, var(--space-2))}.ds-calendar__weekday{text-align:center;color:var(--calendar-weekday-color, var(--gray-600));font-size:var(--calendar-weekday-font-size, var(--font-size-2));font-weight:var(--calendar-weekday-font-weight, 600);text-transform:uppercase;padding:var(--calendar-weekday-padding, var(--space-2) 0)}.ds-calendar__grid{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--calendar-grid-gap, var(--space-1))}.ds-calendar__day{position:relative;aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;padding:var(--calendar-day-padding, var(--space-2));background:var(--calendar-day-bg, transparent);border:1px solid var(--calendar-day-border, transparent);border-radius:var(--calendar-day-radius, var(--radius-1));color:var(--calendar-day-color, var(--gray-900));font-size:var(--calendar-day-font-size, var(--font-size-3));cursor:pointer;transition:all .2s ease}.ds-calendar__day:hover:not(:disabled){background:var(--calendar-day-hover-bg, var(--gray-100));border-color:var(--calendar-day-hover-border, var(--gray-300))}.ds-calendar__day--other-month{color:var(--calendar-day-other-month-color, var(--gray-400))}.ds-calendar__day--today{background:var(--calendar-day-today-bg, var(--blue-50));border-color:var(--calendar-day-today-border, var(--color-primary));color:var(--calendar-day-today-color, var(--color-primary));font-weight:600}.ds-calendar__day--disabled{opacity:.4;cursor:not-allowed;background:var(--calendar-day-disabled-bg, var(--gray-50))}.ds-calendar__day--has-events .ds-calendar__day-number{font-weight:600}.ds-calendar__day-number{line-height:1;margin-bottom:var(--calendar-day-number-margin, var(--space-1))}.ds-calendar__events{display:flex;flex-direction:column;gap:var(--calendar-events-gap, 2px);width:100%;margin-top:auto}.ds-calendar__event{display:flex;align-items:center;gap:var(--calendar-event-gap, var(--space-1));padding:var(--calendar-event-padding, 2px);border-radius:var(--calendar-event-radius, var(--radius-1));cursor:pointer;transition:all .2s ease}.ds-calendar__event:hover{transform:scale(1.05)}.ds-calendar__event-dot{width:var(--calendar-event-dot-size, 6px);height:var(--calendar-event-dot-size, 6px);border-radius:50%;background:var(--calendar-event-dot-color, var(--gray-500));flex-shrink:0}.ds-calendar__event-title{font-size:var(--calendar-event-title-font-size, var(--font-size-1));color:var(--calendar-event-title-color, var(--gray-700));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ds-calendar__event--success .ds-calendar__event-dot{background:var(--calendar-event-success-color, var(--success))}.ds-calendar__event--warning .ds-calendar__event-dot{background:var(--calendar-event-warning-color, var(--warning))}.ds-calendar__event--error .ds-calendar__event-dot{background:var(--calendar-event-error-color, var(--error))}.ds-calendar__year-view{padding:var(--calendar-year-view-padding, var(--space-4))}.ds-calendar__months-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--calendar-months-gap, var(--space-3))}.ds-calendar__month{padding:var(--calendar-month-padding, var(--space-4));background:var(--calendar-month-bg, transparent);border:1px solid var(--calendar-month-border, var(--gray-200));border-radius:var(--calendar-month-radius, var(--radius-2));color:var(--calendar-month-color, var(--gray-900));font-size:var(--calendar-month-font-size, var(--font-size-3));font-weight:500;cursor:pointer;transition:all .2s ease;text-align:center}.ds-calendar__month:hover{background:var(--calendar-month-hover-bg, var(--gray-50));border-color:var(--calendar-month-hover-border, var(--gray-300))}.ds-calendar__month--current{background:var(--calendar-month-current-bg, var(--blue-50));border-color:var(--calendar-month-current-border, var(--color-primary));color:var(--calendar-month-current-color, var(--color-primary));font-weight:600}.ds-calendar--sm .ds-calendar__header{padding:var(--calendar-header-padding-sm, var(--space-2))}.ds-calendar--sm .ds-calendar__title{font-size:var(--calendar-title-font-size-sm, var(--font-size-3))}.ds-calendar--sm .ds-calendar__weekday{font-size:var(--calendar-weekday-font-size-sm, var(--font-size-1))}.ds-calendar--sm .ds-calendar__day{padding:var(--calendar-day-padding-sm, var(--space-1));font-size:var(--calendar-day-font-size-sm, var(--font-size-2))}.ds-calendar--sm .ds-calendar__month{padding:var(--calendar-month-padding-sm, var(--space-2));font-size:var(--calendar-month-font-size-sm, var(--font-size-2))}.ds-calendar--lg .ds-calendar__header{padding:var(--calendar-header-padding-lg, var(--space-6))}.ds-calendar--lg .ds-calendar__title{font-size:var(--calendar-title-font-size-lg, var(--font-size-5))}.ds-calendar--lg .ds-calendar__weekday{font-size:var(--calendar-weekday-font-size-lg, var(--font-size-3))}.ds-calendar--lg .ds-calendar__day{padding:var(--calendar-day-padding-lg, var(--space-3));font-size:var(--calendar-day-font-size-lg, var(--font-size-4))}.ds-calendar--lg .ds-calendar__month{padding:var(--calendar-month-padding-lg, var(--space-6));font-size:var(--calendar-month-font-size-lg, var(--font-size-4))}\n"] }]
|
|
11432
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], events: [{ type: i0.Input, args: [{ isSignal: true, alias: "events", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], disabledDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDate", required: false }] }], dateSelect: [{ type: i0.Output, args: ["dateSelect"] }], monthChange: [{ type: i0.Output, args: ["monthChange"] }], modeChange: [{ type: i0.Output, args: ["modeChange"] }], eventClick: [{ type: i0.Output, args: ["eventClick"] }] } });
|
|
11433
|
+
|
|
8559
11434
|
/*
|
|
8560
11435
|
* Components barrel export
|
|
8561
11436
|
*/
|
|
@@ -9127,5 +12002,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
|
|
|
9127
12002
|
* Generated bundle index. Do not edit.
|
|
9128
12003
|
*/
|
|
9129
12004
|
|
|
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 };
|
|
12005
|
+
export { AUTOCOMPLETE_POSITIONS, BUTTON_APPEARANCE_OPTIONS, BUTTON_SIZE_OPTIONS, BUTTON_VARIANT_OPTIONS, DROPDOWN_POSITIONS, DsAccordion, DsAlert, DsAvatar, DsBadge, DsBreadcrumb, DsButton, DsCalendar, DsCard, DsCarousel, DsCheckbox, DsChip, DsCombobox, DsContainer, DsDatePicker, DsDivider, DsDrawer, DsDropdown, DsEmpty, DsFileUpload, DsI18nService, DsInputField, DsInputTextarea, DsMenu, DsModalComponent, DsNotificationContainerComponent, DsNotificationItemComponent, DsNotificationService, DsPagination, DsPasswordStrength, DsPopover, DsPopoverComponent, DsProgressBar, DsRadioGroup, DsRating, DsSearchInput, DsSelect, DsSkeleton, DsSlider, DsStepper, DsTable, DsTabs, DsTimePicker, DsTimeline, DsToastComponent, DsToastContainerComponent, DsToastService, DsToggle, DsTooltip, DsTooltipComponent, DsTransfer, DsTree, IconRegistryService, POPOVER_POSITIONS, PrimitiveBadge, PrimitiveButton, PrimitiveCheckbox, PrimitiveInput, PrimitiveRadio, PrimitiveTextarea, PrimitiveToggle, TOOLTIP_POSITIONS, buildButtonArgTypes, buildButtonArgs, createSizeRender, createVariantRender };
|
|
9131
12006
|
//# sourceMappingURL=kksdev-ds-angular.mjs.map
|