@elasticias/ui 1.0.2 → 1.0.4

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.
@@ -16,13 +16,13 @@ import { MultiSelectModule } from 'primeng/multiselect';
16
16
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
17
17
  import * as i1$4 from 'primeng/inputnumber';
18
18
  import { InputNumberModule } from 'primeng/inputnumber';
19
- import * as i2$2 from 'primeng/tooltip';
20
- import { TooltipModule } from 'primeng/tooltip';
21
- import * as i1$5 from 'primeng/dialog';
19
+ import * as i1$5 from 'primeng/tooltip';
20
+ import { TooltipModule, Tooltip } from 'primeng/tooltip';
21
+ import * as i1$6 from 'primeng/dialog';
22
22
  import { DialogModule } from 'primeng/dialog';
23
- import * as i1$6 from 'primeng/fieldset';
23
+ import * as i1$7 from 'primeng/fieldset';
24
24
  import { FieldsetModule } from 'primeng/fieldset';
25
- import * as i2$3 from 'primeng/accordion';
25
+ import * as i2$2 from 'primeng/accordion';
26
26
  import { AccordionModule } from 'primeng/accordion';
27
27
  import * as i3 from 'primeng/badge';
28
28
  import { BadgeModule } from 'primeng/badge';
@@ -39,28 +39,30 @@ import { InputTextModule } from 'primeng/inputtext';
39
39
  import * as i5$1 from 'primeng/card';
40
40
  import { CardModule } from 'primeng/card';
41
41
  import { MenuModule } from 'primeng/menu';
42
- import * as i2$4 from 'primeng/api';
43
- import * as i1$7 from 'primeng/buttongroup';
42
+ import * as i2$3 from 'primeng/api';
43
+ import * as i1$8 from 'primeng/confirmdialog';
44
+ import { ConfirmDialogModule } from 'primeng/confirmdialog';
45
+ import { EfThemeConfigService, EF_BUILD_INFO, EfPermissionService, EfActiveModuleService, EF_SESSION, EfViewportService, EfToastService } from '@elasticias/core';
46
+ import * as i1$9 from 'primeng/buttongroup';
44
47
  import { ButtonGroupModule } from 'primeng/buttongroup';
45
- import * as i1$8 from 'primeng/toolbar';
48
+ import * as i1$a from 'primeng/toolbar';
46
49
  import { ToolbarModule } from 'primeng/toolbar';
47
50
  import { ScreenStateEnum, SCREEN_REF_DATA_SERVICE } from '@elasticias/screens';
48
51
  import { Router, RouterLink, RouterLinkActive } from '@angular/router';
49
52
  import { Permissions } from '@elasticias/types';
50
- import { EfPermissionService, EfActiveModuleService, EfViewportService, EfToastService, EfThemeConfigService } from '@elasticias/core';
51
- import * as i1$9 from 'primeng/blockui';
53
+ import * as i1$b from 'primeng/blockui';
52
54
  import { BlockUIModule } from 'primeng/blockui';
53
55
  import { DomSanitizer } from '@angular/platform-browser';
54
- import { Chart, ArcElement, BarController, BarElement, CategoryScale, DoughnutController, Filler, Legend, LineController, LineElement, LinearScale, PointElement, Tooltip } from 'chart.js';
55
- import * as i1$a from 'primeng/toggleswitch';
56
+ import { Chart, ArcElement, BarController, BarElement, CategoryScale, DoughnutController, Filler, Legend, LineController, LineElement, LinearScale, PointElement, Tooltip as Tooltip$1 } from 'chart.js';
57
+ import * as i1$c from 'primeng/toggleswitch';
56
58
  import { ToggleSwitchModule } from 'primeng/toggleswitch';
57
- import * as i1$b from 'primeng/datepicker';
59
+ import * as i1$d from 'primeng/datepicker';
58
60
  import { DatePickerModule } from 'primeng/datepicker';
59
- import * as i1$c from 'primeng/password';
61
+ import * as i1$e from 'primeng/password';
60
62
  import { PasswordModule } from 'primeng/password';
61
- import * as i1$d from 'primeng/selectbutton';
63
+ import * as i1$f from 'primeng/selectbutton';
62
64
  import { SelectButtonModule, SelectButton } from 'primeng/selectbutton';
63
- import * as i2$5 from 'primeng/table';
65
+ import * as i2$4 from 'primeng/table';
64
66
  import { TableModule } from 'primeng/table';
65
67
  import { updatePreset, updateSurfacePalette, $t } from '@primeng/themes';
66
68
  import Aura from '@primeng/themes/aura';
@@ -1050,7 +1052,7 @@ class EfSelectComponent extends AbstractEfFormControl {
1050
1052
  provide: NG_VALUE_ACCESSOR,
1051
1053
  useExisting: forwardRef(() => EfSelectComponent),
1052
1054
  multi: true,
1053
- }], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true }, { propertyName: "selectedItemTemplate", first: true, predicate: ["selectedItem"], descendants: true }, { propertyName: "groupTemplate", first: true, predicate: ["group"], descendants: true }, { propertyName: "headerTemplate", first: true, predicate: ["header"], descendants: true }, { propertyName: "footerTemplate", first: true, predicate: ["footer"], descendants: true }, { propertyName: "emptyTemplate", first: true, predicate: ["empty"], descendants: true }, { propertyName: "emptyFilterTemplate", first: true, predicate: ["emptyFilter"], descendants: true }, { propertyName: "filterTemplate", first: true, predicate: ["filter"], descendants: true }, { propertyName: "loaderTemplate", first: true, predicate: ["loader"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n <!-- Comptoir variant \u2014 native <select> against the\n .ef-select-native pattern. No filter / virtualization /\n multi / templates; use the PrimeNG variant for those. -->\n <select\n class=\"ef-select-native\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [disabled]=\"isDisabled()\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (change)=\"handleNativeSelectChange($any($event.target).value)\"\n >\n @if (effectivePlaceholder) {\n <option value=\"\" [selected]=\"value === null || value === undefined\">\u2014 {{ effectivePlaceholder }} \u2014</option>\n }\n @for (opt of filteredOptions; track $index) {\n <option\n [value]=\"optionValue ? opt[optionValue] : opt\"\n [selected]=\"(optionValue ? opt[optionValue] : opt) === value\"\n >\n {{ opt[optionLabel] }}\n </option>\n }\n </select>\n } @else if (multiple) {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG multi-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-multiselect\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onPanelShow)=\"handlePanelShow()\"\n (onPanelHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [filter]=\"filter\"\n [filterPlaceHolder]=\"effectiveFilterPlaceholder\"\n [autofocusFilter]=\"autofocusFilter\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [showClear]=\"showClear\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [display]=\"multiDisplay\"\n [showToggleAll]=\"showToggleAll\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItems let-items>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: items }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-multiselect>\n } @else {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG single-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-select\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onShow)=\"handlePanelShow()\"\n (onHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [filter]=\"filter\"\n [filterPlaceholder]=\"effectiveFilterPlaceholder\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [autofocusFilter]=\"autofocusFilter\"\n [showClear]=\"showClear\"\n [editable]=\"editable\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItem let-item>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-select>\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: SelectModule }, { kind: "component", type: i1$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i2.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
1055
+ }], queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true }, { propertyName: "selectedItemTemplate", first: true, predicate: ["selectedItem"], descendants: true }, { propertyName: "groupTemplate", first: true, predicate: ["group"], descendants: true }, { propertyName: "headerTemplate", first: true, predicate: ["header"], descendants: true }, { propertyName: "footerTemplate", first: true, predicate: ["footer"], descendants: true }, { propertyName: "emptyTemplate", first: true, predicate: ["empty"], descendants: true }, { propertyName: "emptyFilterTemplate", first: true, predicate: ["emptyFilter"], descendants: true }, { propertyName: "filterTemplate", first: true, predicate: ["filter"], descendants: true }, { propertyName: "loaderTemplate", first: true, predicate: ["loader"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n <!-- Comptoir variant \u2014 native <select> against the\n .ef-select-native pattern. No filter / virtualization /\n multi / templates; use the PrimeNG variant for those. -->\n <select\n class=\"ef-select-native\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [disabled]=\"isDisabled()\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (change)=\"handleNativeSelectChange($any($event.target).value)\"\n >\n @if (effectivePlaceholder) {\n <option value=\"\" [selected]=\"value === null || value === undefined\">\u2014 {{ effectivePlaceholder }} \u2014</option>\n }\n @for (opt of filteredOptions; track $index) {\n <option\n [value]=\"optionValue ? opt[optionValue] : opt\"\n [selected]=\"(optionValue ? opt[optionValue] : opt) === value\"\n >\n {{ opt[optionLabel] }}\n </option>\n }\n </select>\n } @else if (multiple) {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG multi-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-multiselect\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onPanelShow)=\"handlePanelShow()\"\n (onPanelHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [filter]=\"filter\"\n [filterPlaceHolder]=\"effectiveFilterPlaceholder\"\n [autofocusFilter]=\"autofocusFilter\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [showClear]=\"showClear()\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [display]=\"multiDisplay\"\n [showToggleAll]=\"showToggleAll\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItems let-items>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: items }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-multiselect>\n } @else {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG single-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-select\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onShow)=\"handlePanelShow()\"\n (onHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [filter]=\"filter\"\n [filterPlaceholder]=\"effectiveFilterPlaceholder\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [autofocusFilter]=\"autofocusFilter\"\n [showClear]=\"showClear()\"\n [editable]=\"editable\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItem let-item>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-select>\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: SelectModule }, { kind: "component", type: i1$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i2.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
1054
1056
  }
1055
1057
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfSelectComponent, decorators: [{
1056
1058
  type: Component,
@@ -1065,7 +1067,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
1065
1067
  provide: NG_VALUE_ACCESSOR,
1066
1068
  useExisting: forwardRef(() => EfSelectComponent),
1067
1069
  multi: true,
1068
- }], template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n <!-- Comptoir variant \u2014 native <select> against the\n .ef-select-native pattern. No filter / virtualization /\n multi / templates; use the PrimeNG variant for those. -->\n <select\n class=\"ef-select-native\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [disabled]=\"isDisabled()\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (change)=\"handleNativeSelectChange($any($event.target).value)\"\n >\n @if (effectivePlaceholder) {\n <option value=\"\" [selected]=\"value === null || value === undefined\">\u2014 {{ effectivePlaceholder }} \u2014</option>\n }\n @for (opt of filteredOptions; track $index) {\n <option\n [value]=\"optionValue ? opt[optionValue] : opt\"\n [selected]=\"(optionValue ? opt[optionValue] : opt) === value\"\n >\n {{ opt[optionLabel] }}\n </option>\n }\n </select>\n } @else if (multiple) {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG multi-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-multiselect\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onPanelShow)=\"handlePanelShow()\"\n (onPanelHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [filter]=\"filter\"\n [filterPlaceHolder]=\"effectiveFilterPlaceholder\"\n [autofocusFilter]=\"autofocusFilter\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [showClear]=\"showClear\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [display]=\"multiDisplay\"\n [showToggleAll]=\"showToggleAll\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItems let-items>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: items }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-multiselect>\n } @else {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG single-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-select\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onShow)=\"handlePanelShow()\"\n (onHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [filter]=\"filter\"\n [filterPlaceholder]=\"effectiveFilterPlaceholder\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [autofocusFilter]=\"autofocusFilter\"\n [showClear]=\"showClear\"\n [editable]=\"editable\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItem let-item>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-select>\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"] }]
1070
+ }], template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n <!-- Comptoir variant \u2014 native <select> against the\n .ef-select-native pattern. No filter / virtualization /\n multi / templates; use the PrimeNG variant for those. -->\n <select\n class=\"ef-select-native\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [disabled]=\"isDisabled()\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (change)=\"handleNativeSelectChange($any($event.target).value)\"\n >\n @if (effectivePlaceholder) {\n <option value=\"\" [selected]=\"value === null || value === undefined\">\u2014 {{ effectivePlaceholder }} \u2014</option>\n }\n @for (opt of filteredOptions; track $index) {\n <option\n [value]=\"optionValue ? opt[optionValue] : opt\"\n [selected]=\"(optionValue ? opt[optionValue] : opt) === value\"\n >\n {{ opt[optionLabel] }}\n </option>\n }\n </select>\n } @else if (multiple) {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG multi-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-multiselect\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onPanelShow)=\"handlePanelShow()\"\n (onPanelHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [filter]=\"filter\"\n [filterPlaceHolder]=\"effectiveFilterPlaceholder\"\n [autofocusFilter]=\"autofocusFilter\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [showClear]=\"showClear()\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [display]=\"multiDisplay\"\n [showToggleAll]=\"showToggleAll\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItems let-items>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: items }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-multiselect>\n } @else {\n <!-- \u2500\u2500\u2500\u2500\u2500 PrimeNG single-select branch \u2500\u2500\u2500\u2500\u2500 -->\n <p-select\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleSelectionChange($event)\"\n (onClear)=\"handleClear()\"\n (onFilter)=\"handleFilter($event)\"\n (onShow)=\"handlePanelShow()\"\n (onHide)=\"handlePanelHide()\"\n [options]=\"filteredOptions\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [optionDisabled]=\"optionDisabled\"\n [dataKey]=\"dataKey\"\n [group]=\"group\"\n [optionGroupLabel]=\"optionGroupLabel\"\n [optionGroupChildren]=\"optionGroupChildren\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [filter]=\"filter\"\n [filterPlaceholder]=\"effectiveFilterPlaceholder\"\n [filterBy]=\"filterBy ?? optionLabel\"\n [autofocusFilter]=\"autofocusFilter\"\n [showClear]=\"showClear()\"\n [editable]=\"editable\"\n [disabled]=\"isDisabled()\"\n [appendTo]=\"appendTo\"\n [styleClass]=\"effectiveStyleClass\"\n [panelStyleClass]=\"effectivePanelStyleClass\"\n [scrollHeight]=\"scrollHeight\"\n [virtualScroll]=\"virtualScroll\"\n [virtualScrollItemSize]=\"virtualScrollItemSize\"\n [loading]=\"loading\"\n [emptyMessage]=\"effectiveEmptyMessage\"\n [emptyFilterMessage]=\"effectiveEmptyFilterMessage\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n fluid\n >\n @if (itemTemplate) {\n <ng-template #item let-item>\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (selectedItemTemplate) {\n <ng-template #selectedItem let-item>\n <ng-container *ngTemplateOutlet=\"selectedItemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n @if (groupTemplate) {\n <ng-template #group let-group>\n <ng-container *ngTemplateOutlet=\"groupTemplate; context: { $implicit: group }\" />\n </ng-template>\n }\n @if (headerTemplate) {\n <ng-template #header>\n <ng-container *ngTemplateOutlet=\"headerTemplate\" />\n </ng-template>\n }\n @if (footerTemplate) {\n <ng-template #footer>\n <ng-container *ngTemplateOutlet=\"footerTemplate\" />\n </ng-template>\n }\n @if (emptyTemplate) {\n <ng-template #empty>\n <ng-container *ngTemplateOutlet=\"emptyTemplate\" />\n </ng-template>\n }\n @if (emptyFilterTemplate) {\n <ng-template #emptyfilter>\n <ng-container *ngTemplateOutlet=\"emptyFilterTemplate\" />\n </ng-template>\n }\n @if (filterTemplate) {\n <ng-template #filter let-options=\"options\">\n <ng-container *ngTemplateOutlet=\"filterTemplate; context: { $implicit: options }\" />\n </ng-template>\n }\n @if (loaderTemplate) {\n <ng-template #loader>\n <ng-container *ngTemplateOutlet=\"loaderTemplate\" />\n </ng-template>\n }\n <ng-template #clearicon>\n <span class=\"es-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n <ng-template #dropdownicon>\n <svg class=\"ef-chevron\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n </ng-template>\n </p-select>\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"] }]
1069
1071
  }], propDecorators: { options: [{
1070
1072
  type: Input
1071
1073
  }], optionLabel: [{
@@ -1638,6 +1640,12 @@ class EfDatepickerAdvancedComponent extends AbstractEfFormControl {
1638
1640
  const anchor = this.draftStart() ?? new Date();
1639
1641
  this.visibleMonth.set(this.startOfMonth(anchor));
1640
1642
  }
1643
+ else if (this.activePreset() === 'custom') {
1644
+ // The active range was hand-picked, so the preset list has
1645
+ // nothing selected to show. Reopen where it was chosen, with
1646
+ // the calendar already sitting on those dates.
1647
+ this.openCustomView();
1648
+ }
1641
1649
  else {
1642
1650
  this.view.set('presets');
1643
1651
  this.seedDraftFromValue();
@@ -2389,11 +2397,11 @@ class EfInputNumberComponent extends AbstractEfFormControl {
2389
2397
  this.handleClear();
2390
2398
  }
2391
2399
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfInputNumberComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2392
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfInputNumberComponent, isStandalone: true, selector: "ef-inputnumber", inputs: { value: "value", invalid: "invalid", format: "format", showButtons: ["showButtons", "showButtons", booleanAttribute], buttonLayout: "buttonLayout", incrementButtonClass: "incrementButtonClass", decrementButtonClass: "decrementButtonClass", incrementButtonIcon: "incrementButtonIcon", decrementButtonIcon: "decrementButtonIcon", prefix: "prefix", suffix: "suffix", currency: "currency", currencyDisplay: "currencyDisplay", locale: "locale", localeMatcher: "localeMatcher", mode: "mode", useGrouping: "useGrouping", minFractionDigits: "minFractionDigits", maxFractionDigits: "maxFractionDigits", min: "min", max: "max", step: "step", allowEmpty: "allowEmpty", inputSize: "inputSize", size: "size", maxlength: "maxlength", minlength: "minlength", pattern: "pattern", tabindex: "tabindex", title: "title", ariaLabelledBy: "ariaLabelledBy", inputStyle: "inputStyle", inputStyleClass: "inputStyleClass", style: "style", styleClass: "styleClass", primeNgVariant: "primeNgVariant", autofocus: ["autofocus", "autofocus", booleanAttribute], autocomplete: "autocomplete", fluid: "fluid", inline: ["inline", "inline", booleanAttribute], variant: "variant", pt: "pt", ptOptions: "ptOptions", dt: "dt", unstyled: "unstyled" }, outputs: { inputEvent: "inputEvent", valueChangeEvent: "valueChangeEvent", focusEvent: "focusEvent", blurEvent: "blurEvent", keyDownEvent: "keyDownEvent", clearEvent: "clearEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, viewQueries: [{ propertyName: "inputNumber", first: true, predicate: ["inputNumber"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n @if (prefix || suffix || showButtons) {\n <!-- Comptoir variant \u2014 native text input (inputmode=decimal, accepts\n \",\" or \".\" as decimal separator) wrapped in .ef-input-group when\n there's a prefix / suffix / stepper. min/max are enforced by\n blur-time clamping in the component (text inputs have no native\n range semantics). -->\n <div class=\"ef-input-group\" [class.is-invalid]=\"isInvalid\">\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (min !== undefined && (value ?? 0) <= min)\"\n (click)=\"step$(-1)\"\n [attr.aria-label]=\"('ef_input_decrement' | translate) || 'Decrease'\"\n >\n <i class=\"pi pi-minus\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (prefix) {\n <span class=\"ef-input-addon is-prefix\" aria-hidden=\"true\">{{ prefix }}</span>\n }\n <input\n type=\"text\"\n inputmode=\"decimal\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-group-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n @if (suffix) {\n <span class=\"ef-input-addon is-suffix\" aria-hidden=\"true\">{{ suffix }}</span>\n }\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (max !== undefined && (value ?? 0) >= max)\"\n (click)=\"step$(1)\"\n [attr.aria-label]=\"('ef_input_increment' | translate) || 'Increase'\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n } @else {\n <!-- Comptoir variant \u2014 bare native text input (inputmode=decimal,\n accepts \",\" or \".\" as decimal separator; optional inline clear).\n min/max are enforced by blur-time clamping in the component. -->\n <div class=\"ef-input-wrap\">\n <input\n type=\"text\"\n inputmode=\"decimal\"\n class=\"ef-input\"\n [class.has-clear]=\"canClear\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-input-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n </div>\n }\n } @else {\n <!-- PrimeNG variant (default) \u2014 full locale-aware formatting. -->\n <p-inputnumber\n #inputNumber\n [(ngModel)]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n [invalid]=\"isInvalid\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [format]=\"format\"\n [showButtons]=\"showButtons\"\n [buttonLayout]=\"buttonLayout\"\n [incrementButtonClass]=\"incrementButtonClass\"\n [decrementButtonClass]=\"decrementButtonClass\"\n [incrementButtonIcon]=\"incrementButtonIcon\"\n [decrementButtonIcon]=\"decrementButtonIcon\"\n [prefix]=\"prefix\"\n [suffix]=\"suffix\"\n [currency]=\"currency\"\n [currencyDisplay]=\"currencyDisplay\"\n [locale]=\"locale\"\n [localeMatcher]=\"localeMatcher\"\n [mode]=\"mode\"\n [useGrouping]=\"useGrouping\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [allowEmpty]=\"allowEmpty\"\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [placeholder]=\"effectivePlaceholder\"\n [inputSize]=\"inputSize\"\n [size]=\"size\"\n [maxlength]=\"maxlength\"\n [minlength]=\"minlength\"\n [pattern]=\"pattern\"\n [tabindex]=\"tabindex\"\n [title]=\"title\"\n [ariaLabel]=\"effectiveAriaLabel\"\n [ariaLabelledBy]=\"ariaLabelledBy\"\n [ariaRequired]=\"required()\"\n [inputStyle]=\"inputStyle\"\n [inputStyleClass]=\"inputStyleClass\"\n [style]=\"style\"\n [styleClass]=\"styleClass\"\n [showClear]=\"showClear\"\n [variant]=\"primeNgVariant\"\n [autofocus]=\"autofocus\"\n [autocomplete]=\"autocomplete\"\n [fluid]=\"fluid\"\n [pt]=\"pt\"\n [ptOptions]=\"ptOptions\"\n [dt]=\"dt\"\n [unstyled]=\"unstyled\"\n (onInput)=\"handleInput($event)\"\n (onFocus)=\"handleFocus($event)\"\n (onBlur)=\"handleBlur($event)\"\n (onKeyDown)=\"handleKeyDown($event)\"\n (onClear)=\"handleClear()\"\n />\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}:host(.ef-inputnumber-small) ::ng-deep .p-inputnumber-input{font-size:.875rem;padding:.375rem .5rem}:host(.ef-inputnumber-large) ::ng-deep .p-inputnumber-input{font-size:1.125rem;padding:.75rem 1rem}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input{border-color:var(--red-500, #ef4444)}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input:focus,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input:focus{box-shadow:0 0 0 .2rem #ef444440}\n"], dependencies: [{ kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i1$4.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i2$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2$1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "component", type: EfClearButtonComponent, selector: "ef-clear-button", inputs: ["ariaLabel", "disabled"], outputs: ["clear"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
2400
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfInputNumberComponent, isStandalone: true, selector: "ef-inputnumber", inputs: { value: "value", invalid: "invalid", format: "format", showButtons: ["showButtons", "showButtons", booleanAttribute], buttonLayout: "buttonLayout", incrementButtonClass: "incrementButtonClass", decrementButtonClass: "decrementButtonClass", incrementButtonIcon: "incrementButtonIcon", decrementButtonIcon: "decrementButtonIcon", prefix: "prefix", suffix: "suffix", currency: "currency", currencyDisplay: "currencyDisplay", locale: "locale", localeMatcher: "localeMatcher", mode: "mode", useGrouping: "useGrouping", minFractionDigits: "minFractionDigits", maxFractionDigits: "maxFractionDigits", min: "min", max: "max", step: "step", allowEmpty: "allowEmpty", inputSize: "inputSize", size: "size", maxlength: "maxlength", minlength: "minlength", pattern: "pattern", tabindex: "tabindex", title: "title", ariaLabelledBy: "ariaLabelledBy", inputStyle: "inputStyle", inputStyleClass: "inputStyleClass", style: "style", styleClass: "styleClass", primeNgVariant: "primeNgVariant", autofocus: ["autofocus", "autofocus", booleanAttribute], autocomplete: "autocomplete", fluid: "fluid", inline: ["inline", "inline", booleanAttribute], variant: "variant", pt: "pt", ptOptions: "ptOptions", dt: "dt", unstyled: "unstyled" }, outputs: { inputEvent: "inputEvent", valueChangeEvent: "valueChangeEvent", focusEvent: "focusEvent", blurEvent: "blurEvent", keyDownEvent: "keyDownEvent", clearEvent: "clearEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, viewQueries: [{ propertyName: "inputNumber", first: true, predicate: ["inputNumber"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n @if (prefix || suffix || showButtons) {\n <!-- Comptoir variant \u2014 native text input (inputmode=decimal, accepts\n \",\" or \".\" as decimal separator) wrapped in .ef-input-group when\n there's a prefix / suffix / stepper. min/max are enforced by\n blur-time clamping in the component (text inputs have no native\n range semantics). -->\n <div class=\"ef-input-group\" [class.is-invalid]=\"isInvalid\">\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (min !== undefined && (value ?? 0) <= min)\"\n (click)=\"step$(-1)\"\n [attr.aria-label]=\"('ef_input_decrement' | translate) || 'Decrease'\"\n >\n <i class=\"pi pi-minus\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (prefix) {\n <span class=\"ef-input-addon is-prefix\" aria-hidden=\"true\">{{ prefix }}</span>\n }\n <input\n type=\"text\"\n inputmode=\"decimal\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-group-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n @if (suffix) {\n <span class=\"ef-input-addon is-suffix\" aria-hidden=\"true\">{{ suffix }}</span>\n }\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (max !== undefined && (value ?? 0) >= max)\"\n (click)=\"step$(1)\"\n [attr.aria-label]=\"('ef_input_increment' | translate) || 'Increase'\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n } @else {\n <!-- Comptoir variant \u2014 bare native text input (inputmode=decimal,\n accepts \",\" or \".\" as decimal separator; optional inline clear).\n min/max are enforced by blur-time clamping in the component. -->\n <div class=\"ef-input-wrap\">\n <input\n type=\"text\"\n inputmode=\"decimal\"\n class=\"ef-input\"\n [class.has-clear]=\"canClear\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-input-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n </div>\n }\n } @else {\n <!-- PrimeNG variant (default) \u2014 full locale-aware formatting. -->\n <p-inputnumber\n #inputNumber\n [(ngModel)]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n [invalid]=\"isInvalid\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [format]=\"format\"\n [showButtons]=\"showButtons\"\n [buttonLayout]=\"buttonLayout\"\n [incrementButtonClass]=\"incrementButtonClass\"\n [decrementButtonClass]=\"decrementButtonClass\"\n [incrementButtonIcon]=\"incrementButtonIcon\"\n [decrementButtonIcon]=\"decrementButtonIcon\"\n [prefix]=\"prefix\"\n [suffix]=\"suffix\"\n [currency]=\"currency\"\n [currencyDisplay]=\"currencyDisplay\"\n [locale]=\"locale\"\n [localeMatcher]=\"localeMatcher\"\n [mode]=\"mode\"\n [useGrouping]=\"useGrouping\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [allowEmpty]=\"allowEmpty\"\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [placeholder]=\"effectivePlaceholder\"\n [inputSize]=\"inputSize\"\n [size]=\"size\"\n [maxlength]=\"maxlength\"\n [minlength]=\"minlength\"\n [pattern]=\"pattern\"\n [tabindex]=\"tabindex\"\n [title]=\"title\"\n [ariaLabel]=\"effectiveAriaLabel\"\n [ariaLabelledBy]=\"ariaLabelledBy\"\n [ariaRequired]=\"required()\"\n [inputStyle]=\"inputStyle\"\n [inputStyleClass]=\"inputStyleClass\"\n [style]=\"style\"\n [styleClass]=\"styleClass\"\n [showClear]=\"showClear()\"\n [variant]=\"primeNgVariant\"\n [autofocus]=\"autofocus\"\n [autocomplete]=\"autocomplete\"\n [fluid]=\"fluid\"\n [pt]=\"pt\"\n [ptOptions]=\"ptOptions\"\n [dt]=\"dt\"\n [unstyled]=\"unstyled\"\n (onInput)=\"handleInput($event)\"\n (onFocus)=\"handleFocus($event)\"\n (onBlur)=\"handleBlur($event)\"\n (onKeyDown)=\"handleKeyDown($event)\"\n (onClear)=\"handleClear()\"\n />\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}:host(.ef-inputnumber-small) ::ng-deep .p-inputnumber-input{font-size:.875rem;padding:.375rem .5rem}:host(.ef-inputnumber-large) ::ng-deep .p-inputnumber-input{font-size:1.125rem;padding:.75rem 1rem}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input{border-color:var(--red-500, #ef4444)}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input:focus,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input:focus{box-shadow:0 0 0 .2rem #ef444440}\n"], dependencies: [{ kind: "ngmodule", type: InputNumberModule }, { kind: "component", type: i1$4.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2$1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i2$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2$1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "component", type: EfClearButtonComponent, selector: "ef-clear-button", inputs: ["ariaLabel", "disabled"], outputs: ["clear"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
2393
2401
  }
2394
2402
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfInputNumberComponent, decorators: [{
2395
2403
  type: Component,
2396
- args: [{ selector: 'ef-inputnumber', standalone: true, imports: [InputNumberModule, FormsModule, TranslateModule, EfLabelComponent, EfClearButtonComponent], template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n @if (prefix || suffix || showButtons) {\n <!-- Comptoir variant \u2014 native text input (inputmode=decimal, accepts\n \",\" or \".\" as decimal separator) wrapped in .ef-input-group when\n there's a prefix / suffix / stepper. min/max are enforced by\n blur-time clamping in the component (text inputs have no native\n range semantics). -->\n <div class=\"ef-input-group\" [class.is-invalid]=\"isInvalid\">\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (min !== undefined && (value ?? 0) <= min)\"\n (click)=\"step$(-1)\"\n [attr.aria-label]=\"('ef_input_decrement' | translate) || 'Decrease'\"\n >\n <i class=\"pi pi-minus\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (prefix) {\n <span class=\"ef-input-addon is-prefix\" aria-hidden=\"true\">{{ prefix }}</span>\n }\n <input\n type=\"text\"\n inputmode=\"decimal\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-group-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n @if (suffix) {\n <span class=\"ef-input-addon is-suffix\" aria-hidden=\"true\">{{ suffix }}</span>\n }\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (max !== undefined && (value ?? 0) >= max)\"\n (click)=\"step$(1)\"\n [attr.aria-label]=\"('ef_input_increment' | translate) || 'Increase'\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n } @else {\n <!-- Comptoir variant \u2014 bare native text input (inputmode=decimal,\n accepts \",\" or \".\" as decimal separator; optional inline clear).\n min/max are enforced by blur-time clamping in the component. -->\n <div class=\"ef-input-wrap\">\n <input\n type=\"text\"\n inputmode=\"decimal\"\n class=\"ef-input\"\n [class.has-clear]=\"canClear\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-input-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n </div>\n }\n } @else {\n <!-- PrimeNG variant (default) \u2014 full locale-aware formatting. -->\n <p-inputnumber\n #inputNumber\n [(ngModel)]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n [invalid]=\"isInvalid\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [format]=\"format\"\n [showButtons]=\"showButtons\"\n [buttonLayout]=\"buttonLayout\"\n [incrementButtonClass]=\"incrementButtonClass\"\n [decrementButtonClass]=\"decrementButtonClass\"\n [incrementButtonIcon]=\"incrementButtonIcon\"\n [decrementButtonIcon]=\"decrementButtonIcon\"\n [prefix]=\"prefix\"\n [suffix]=\"suffix\"\n [currency]=\"currency\"\n [currencyDisplay]=\"currencyDisplay\"\n [locale]=\"locale\"\n [localeMatcher]=\"localeMatcher\"\n [mode]=\"mode\"\n [useGrouping]=\"useGrouping\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [allowEmpty]=\"allowEmpty\"\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [placeholder]=\"effectivePlaceholder\"\n [inputSize]=\"inputSize\"\n [size]=\"size\"\n [maxlength]=\"maxlength\"\n [minlength]=\"minlength\"\n [pattern]=\"pattern\"\n [tabindex]=\"tabindex\"\n [title]=\"title\"\n [ariaLabel]=\"effectiveAriaLabel\"\n [ariaLabelledBy]=\"ariaLabelledBy\"\n [ariaRequired]=\"required()\"\n [inputStyle]=\"inputStyle\"\n [inputStyleClass]=\"inputStyleClass\"\n [style]=\"style\"\n [styleClass]=\"styleClass\"\n [showClear]=\"showClear\"\n [variant]=\"primeNgVariant\"\n [autofocus]=\"autofocus\"\n [autocomplete]=\"autocomplete\"\n [fluid]=\"fluid\"\n [pt]=\"pt\"\n [ptOptions]=\"ptOptions\"\n [dt]=\"dt\"\n [unstyled]=\"unstyled\"\n (onInput)=\"handleInput($event)\"\n (onFocus)=\"handleFocus($event)\"\n (onBlur)=\"handleBlur($event)\"\n (onKeyDown)=\"handleKeyDown($event)\"\n (onClear)=\"handleClear()\"\n />\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}:host(.ef-inputnumber-small) ::ng-deep .p-inputnumber-input{font-size:.875rem;padding:.375rem .5rem}:host(.ef-inputnumber-large) ::ng-deep .p-inputnumber-input{font-size:1.125rem;padding:.75rem 1rem}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input{border-color:var(--red-500, #ef4444)}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input:focus,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input:focus{box-shadow:0 0 0 .2rem #ef444440}\n"] }]
2404
+ args: [{ selector: 'ef-inputnumber', standalone: true, imports: [InputNumberModule, FormsModule, TranslateModule, EfLabelComponent, EfClearButtonComponent], template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n @if (variant === 'comptoir') {\n @if (prefix || suffix || showButtons) {\n <!-- Comptoir variant \u2014 native text input (inputmode=decimal, accepts\n \",\" or \".\" as decimal separator) wrapped in .ef-input-group when\n there's a prefix / suffix / stepper. min/max are enforced by\n blur-time clamping in the component (text inputs have no native\n range semantics). -->\n <div class=\"ef-input-group\" [class.is-invalid]=\"isInvalid\">\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (min !== undefined && (value ?? 0) <= min)\"\n (click)=\"step$(-1)\"\n [attr.aria-label]=\"('ef_input_decrement' | translate) || 'Decrease'\"\n >\n <i class=\"pi pi-minus\" aria-hidden=\"true\"></i>\n </button>\n }\n @if (prefix) {\n <span class=\"ef-input-addon is-prefix\" aria-hidden=\"true\">{{ prefix }}</span>\n }\n <input\n type=\"text\"\n inputmode=\"decimal\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-group-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n @if (suffix) {\n <span class=\"ef-input-addon is-suffix\" aria-hidden=\"true\">{{ suffix }}</span>\n }\n @if (showButtons) {\n <button\n type=\"button\"\n class=\"ef-input-addon is-stepper\"\n [disabled]=\"isDisabled() || (max !== undefined && (value ?? 0) >= max)\"\n (click)=\"step$(1)\"\n [attr.aria-label]=\"('ef_input_increment' | translate) || 'Increase'\"\n >\n <i class=\"pi pi-plus\" aria-hidden=\"true\"></i>\n </button>\n }\n </div>\n } @else {\n <!-- Comptoir variant \u2014 bare native text input (inputmode=decimal,\n accepts \",\" or \".\" as decimal separator; optional inline clear).\n min/max are enforced by blur-time clamping in the component. -->\n <div class=\"ef-input-wrap\">\n <input\n type=\"text\"\n inputmode=\"decimal\"\n class=\"ef-input\"\n [class.has-clear]=\"canClear\"\n [id]=\"effectiveId\"\n [attr.name]=\"name() || null\"\n [value]=\"value ?? ''\"\n [attr.placeholder]=\"effectivePlaceholder || null\"\n [readonly]=\"readonly()\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete ?? 'off'\"\n [class.is-invalid]=\"isInvalid\"\n [attr.aria-label]=\"effectiveAriaLabel\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : null\"\n [attr.aria-describedby]=\"(showRequired || serverErrors) ? errorsId : null\"\n (input)=\"handleNativeInput($any($event.target).value)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeyDown($event)\"\n />\n @if (canClear) {\n <ef-clear-button\n class=\"ef-input-clear\"\n [ariaLabel]=\"'action.clear' | translate\"\n (clear)=\"clearValue()\"\n />\n }\n </div>\n }\n } @else {\n <!-- PrimeNG variant (default) \u2014 full locale-aware formatting. -->\n <p-inputnumber\n #inputNumber\n [(ngModel)]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n [invalid]=\"isInvalid\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n [format]=\"format\"\n [showButtons]=\"showButtons\"\n [buttonLayout]=\"buttonLayout\"\n [incrementButtonClass]=\"incrementButtonClass\"\n [decrementButtonClass]=\"decrementButtonClass\"\n [incrementButtonIcon]=\"incrementButtonIcon\"\n [decrementButtonIcon]=\"decrementButtonIcon\"\n [prefix]=\"prefix\"\n [suffix]=\"suffix\"\n [currency]=\"currency\"\n [currencyDisplay]=\"currencyDisplay\"\n [locale]=\"locale\"\n [localeMatcher]=\"localeMatcher\"\n [mode]=\"mode\"\n [useGrouping]=\"useGrouping\"\n [minFractionDigits]=\"minFractionDigits\"\n [maxFractionDigits]=\"maxFractionDigits\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [allowEmpty]=\"allowEmpty\"\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [placeholder]=\"effectivePlaceholder\"\n [inputSize]=\"inputSize\"\n [size]=\"size\"\n [maxlength]=\"maxlength\"\n [minlength]=\"minlength\"\n [pattern]=\"pattern\"\n [tabindex]=\"tabindex\"\n [title]=\"title\"\n [ariaLabel]=\"effectiveAriaLabel\"\n [ariaLabelledBy]=\"ariaLabelledBy\"\n [ariaRequired]=\"required()\"\n [inputStyle]=\"inputStyle\"\n [inputStyleClass]=\"inputStyleClass\"\n [style]=\"style\"\n [styleClass]=\"styleClass\"\n [showClear]=\"showClear()\"\n [variant]=\"primeNgVariant\"\n [autofocus]=\"autofocus\"\n [autocomplete]=\"autocomplete\"\n [fluid]=\"fluid\"\n [pt]=\"pt\"\n [ptOptions]=\"ptOptions\"\n [dt]=\"dt\"\n [unstyled]=\"unstyled\"\n (onInput)=\"handleInput($event)\"\n (onFocus)=\"handleFocus($event)\"\n (onBlur)=\"handleBlur($event)\"\n (onKeyDown)=\"handleKeyDown($event)\"\n (onClear)=\"handleClear()\"\n />\n }\n @if (showRequired || serverErrors) {\n <div [id]=\"errorsId\" role=\"alert\" aria-live=\"polite\">\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}:host(.ef-inputnumber-small) ::ng-deep .p-inputnumber-input{font-size:.875rem;padding:.375rem .5rem}:host(.ef-inputnumber-large) ::ng-deep .p-inputnumber-input{font-size:1.125rem;padding:.75rem 1rem}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input{border-color:var(--red-500, #ef4444)}:host(.ng-invalid.ng-touched) ::ng-deep .p-inputnumber-input:focus,:host(.ng-invalid.ng-dirty) ::ng-deep .p-inputnumber-input:focus{box-shadow:0 0 0 .2rem #ef444440}\n"] }]
2397
2405
  }], ctorParameters: () => [], propDecorators: { inputNumber: [{
2398
2406
  type: ViewChild,
2399
2407
  args: ['inputNumber', { static: false }]
@@ -2741,7 +2749,7 @@ class EfButtonComponent {
2741
2749
  this.clickEvent.emit(event);
2742
2750
  }
2743
2751
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2744
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfButtonComponent, isStandalone: true, selector: "ef-button", inputs: { label: "label", labelKey: "labelKey", icon: "icon", variant: "variant", severity: "severity", size: "size", disabled: ["disabled", "disabled", booleanAttribute], rounded: ["rounded", "rounded", booleanAttribute], outlined: ["outlined", "outlined", booleanAttribute], raised: ["raised", "raised", booleanAttribute], text: ["text", "text", booleanAttribute], loading: ["loading", "loading", booleanAttribute], styleClass: "styleClass", type: "type", badge: "badge", badgeSeverity: "badgeSeverity", tooltip: "tooltip", tooltipKey: "tooltipKey", tooltipPosition: "tooltipPosition" }, outputs: { clickEvent: "clickEvent" }, ngImport: i0, template: "@if (variant === 'comptoir') {\n <!-- Comptoir variant \u2014 native button against the `.btn` pattern\n in `@elasticias/ui/styles/patterns`. PrimeNG severities\n (success/info/warn/help/contrast/secondary) fall through to\n this branch only when explicitly passed with variant='comptoir';\n they render as ghost since they have no Comptoir equivalent. -->\n <button\n [type]=\"type\"\n [class]=\"comptoirClass\"\n [disabled]=\"disabled || loading\"\n [style.color]=\"comptoirInlineColor\"\n [pTooltip]=\"effectiveTooltipKey ? (effectiveTooltipKey | translate) : effectiveTooltip\"\n [tooltipPosition]=\"tooltipPosition\"\n (click)=\"handleClick($event)\"\n >\n @if (loading) {\n <i class=\"pi pi-spinner pi-spin\" aria-hidden=\"true\"></i>\n } @else if (icon) {\n <i [class]=\"icon\" aria-hidden=\"true\"></i>\n }\n @if (labelKey || label) {\n <span>{{ labelKey ? (labelKey | translate) : label }}</span>\n }\n </button>\n} @else {\n <!-- PrimeNG variant (default) \u2014 v1 styling via <p-button>. -->\n <p-button\n [label]=\"labelKey ? (labelKey | translate) : label\"\n [icon]=\"icon\"\n [severity]=\"$any(severity)\"\n [size]=\"size\"\n [disabled]=\"disabled\"\n [rounded]=\"rounded\"\n [outlined]=\"outlined\"\n [raised]=\"raised\"\n [text]=\"text\"\n [loading]=\"loading\"\n [styleClass]=\"styleClass\"\n [type]=\"type\"\n [badge]=\"badge\"\n [badgeSeverity]=\"badgeSeverity\"\n [pTooltip]=\"effectiveTooltipKey ? (effectiveTooltipKey | translate) : effectiveTooltip\"\n [tooltipPosition]=\"tooltipPosition\"\n (onClick)=\"handleClick($event)\"\n />\n}\n", dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
2752
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfButtonComponent, isStandalone: true, selector: "ef-button", inputs: { label: "label", labelKey: "labelKey", icon: "icon", variant: "variant", severity: "severity", size: "size", disabled: ["disabled", "disabled", booleanAttribute], rounded: ["rounded", "rounded", booleanAttribute], outlined: ["outlined", "outlined", booleanAttribute], raised: ["raised", "raised", booleanAttribute], text: ["text", "text", booleanAttribute], loading: ["loading", "loading", booleanAttribute], styleClass: "styleClass", type: "type", badge: "badge", badgeSeverity: "badgeSeverity", tooltip: "tooltip", tooltipKey: "tooltipKey", tooltipPosition: "tooltipPosition" }, outputs: { clickEvent: "clickEvent" }, ngImport: i0, template: "@if (variant === 'comptoir') {\n <!-- Comptoir variant \u2014 native button against the `.btn` pattern\n in `@elasticias/ui/styles/patterns`. PrimeNG severities\n (success/info/warn/help/contrast/secondary) fall through to\n this branch only when explicitly passed with variant='comptoir';\n they render as ghost since they have no Comptoir equivalent. -->\n <button\n [type]=\"type\"\n [class]=\"comptoirClass\"\n [disabled]=\"disabled || loading\"\n [style.color]=\"comptoirInlineColor\"\n [pTooltip]=\"effectiveTooltipKey ? (effectiveTooltipKey | translate) : effectiveTooltip\"\n [tooltipPosition]=\"tooltipPosition\"\n (click)=\"handleClick($event)\"\n >\n @if (loading) {\n <i class=\"pi pi-spinner pi-spin\" aria-hidden=\"true\"></i>\n } @else if (icon) {\n <i [class]=\"icon\" aria-hidden=\"true\"></i>\n }\n @if (labelKey || label) {\n <span>{{ labelKey ? (labelKey | translate) : label }}</span>\n }\n </button>\n} @else {\n <!-- PrimeNG variant (default) \u2014 v1 styling via <p-button>. -->\n <p-button\n [label]=\"labelKey ? (labelKey | translate) : label\"\n [icon]=\"icon\"\n [severity]=\"$any(severity)\"\n [size]=\"size\"\n [disabled]=\"disabled\"\n [rounded]=\"rounded\"\n [outlined]=\"outlined\"\n [raised]=\"raised\"\n [text]=\"text\"\n [loading]=\"loading\"\n [styleClass]=\"styleClass\"\n [type]=\"type\"\n [badge]=\"badge\"\n [badgeSeverity]=\"badgeSeverity\"\n [pTooltip]=\"effectiveTooltipKey ? (effectiveTooltipKey | translate) : effectiveTooltip\"\n [tooltipPosition]=\"tooltipPosition\"\n (onClick)=\"handleClick($event)\"\n />\n}\n", dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
2745
2753
  }
2746
2754
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfButtonComponent, decorators: [{
2747
2755
  type: Component,
@@ -3316,7 +3324,7 @@ class EfDialogComponent {
3316
3324
  this.saveAction.emit();
3317
3325
  }
3318
3326
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3319
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDialogComponent, isStandalone: true, selector: "ef-dialog", inputs: { header: "header", headerKey: "headerKey", subtitle: "subtitle", subtitleKey: "subtitleKey", visible: ["visible", "visible", booleanAttribute], modal: ["modal", "modal", booleanAttribute], closable: ["closable", "closable", booleanAttribute], draggable: ["draggable", "draggable", booleanAttribute], resizable: ["resizable", "resizable", booleanAttribute], dismissableMask: ["dismissableMask", "dismissableMask", booleanAttribute], closeOnEscape: ["closeOnEscape", "closeOnEscape", booleanAttribute], severity: "severity", icon: "icon", size: "size", style: "style", styleClass: "styleClass", position: "position", appendTo: "appendTo", variant: "variant", actions: "actions", defaultActions: ["defaultActions", "defaultActions", booleanAttribute], saveLabelKey: "saveLabelKey", cancelLabelKey: "cancelLabelKey", saveLabel: "saveLabel", cancelLabel: "cancelLabel", saveIcon: "saveIcon", cancelIcon: "cancelIcon", saveDisabled: ["saveDisabled", "saveDisabled", booleanAttribute], saveStyleClass: "saveStyleClass", cancelStyleClass: "cancelStyleClass", saveSeverity: "saveSeverity", cancelSeverity: "cancelSeverity" }, outputs: { visibleChange: "visibleChange", showEvent: "showEvent", hideEvent: "hideEvent", saveAction: "saveAction", cancelAction: "cancelAction", actionClick: "actionClick" }, viewQueries: [{ propertyName: "defaultFooterTpl", first: true, predicate: ["defaultFooter"], descendants: true, static: true }], ngImport: i0, template: "<p-dialog\n [visible]=\"visible\"\n (visibleChange)=\"handleVisibleChange($event)\"\n [modal]=\"modal\"\n [draggable]=\"draggable\"\n [resizable]=\"resizable\"\n [dismissableMask]=\"dismissableMask\"\n [closeOnEscape]=\"closeOnEscape\"\n [style]=\"style\"\n [styleClass]=\"effectiveStyleClass\"\n [position]=\"position\"\n [appendTo]=\"appendTo\"\n [header]=\"variant === 'primeng' ? effectiveTitle : null\"\n [closable]=\"variant === 'primeng' ? closable : false\"\n [footerTemplate]=\"variant === 'primeng' && !useDynamicActions && defaultActions ? defaultFooterTpl : null\"\n (onShow)=\"handleShow()\"\n (onHide)=\"handleHide()\"\n>\n <!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 COMPTOIR HEADER (content-child #header) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Replaces PrimeNG's default header strip with our icon + title\n + subtitle + close X structure. Skipped in 'primeng' variant\n (which uses the [header] string input + native close). -->\n @if (variant === 'comptoir') {\n <ng-template #header>\n @if (effectiveIcon) {\n <span class=\"es-dialog__icon\" aria-hidden=\"true\">\n <i [class]=\"effectiveIcon\"></i>\n </span>\n }\n <div class=\"es-dialog__title-block\">\n <div class=\"es-dialog__title\">{{ effectiveTitle }}</div>\n @if (effectiveSubtitle) {\n <div class=\"es-dialog__sub\">{{ effectiveSubtitle }}</div>\n }\n </div>\n @if (closable) {\n <button\n type=\"button\"\n class=\"es-dialog__close\"\n [attr.aria-label]=\"'common_close' | translate\"\n (click)=\"handleVisibleChange(false)\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n }\n </ng-template>\n }\n\n <!-- Body \u2014 projected from <ef-dialog>\u2026</ef-dialog> -->\n <ng-content />\n\n <!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 COMPTOIR FOOTER (content-child #footer) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Dynamic [actions] path takes precedence; falls back to the\n backward-compat save+cancel pair when defaultActions is on. -->\n @if (variant === 'comptoir' && hasFooter) {\n <ng-template #footer>\n @if (useDynamicActions) {\n @for (a of actions; track $index) {\n <button\n type=\"button\"\n [class]=\"actionClass(a)\"\n [disabled]=\"a.disabled || a.loading\"\n (click)=\"handleActionClick(a, $index)\"\n >\n @if (a.icon) {\n <i [class]=\"a.icon\"></i>\n }\n {{ actionLabel(a) }}\n </button>\n }\n } @else {\n <ef-button\n variant=\"comptoir\"\n [severity]=\"cancelSeverity\"\n [labelKey]=\"cancelLabelKey\"\n [label]=\"cancelLabel\"\n [icon]=\"cancelIcon\"\n [styleClass]=\"cancelStyleClass\"\n (clickEvent)=\"onDefaultCancel()\"\n />\n <ef-button\n variant=\"comptoir\"\n [severity]=\"saveSeverity\"\n [labelKey]=\"saveLabelKey\"\n [label]=\"saveLabel\"\n [icon]=\"saveIcon\"\n [styleClass]=\"saveStyleClass\"\n [disabled]=\"saveDisabled\"\n (clickEvent)=\"onDefaultSave()\"\n />\n }\n </ng-template>\n }\n</p-dialog>\n\n<!-- Default-action footer template for the 'primeng' variant (legacy path).\n Declared outside <p-dialog> because the comptoir branch above already\n provides its own content-child footer; this template is only consumed\n when variant === 'primeng' via [footerTemplate] input binding. -->\n<ng-template #defaultFooter>\n <ef-button\n variant=\"primeng\"\n [severity]=\"cancelSeverity\"\n [labelKey]=\"cancelLabelKey\"\n [label]=\"cancelLabel\"\n [icon]=\"cancelIcon\"\n [styleClass]=\"cancelStyleClass\"\n (clickEvent)=\"onDefaultCancel()\"\n />\n <ef-button\n variant=\"primeng\"\n [severity]=\"saveSeverity\"\n [labelKey]=\"saveLabelKey\"\n [label]=\"saveLabel\"\n [icon]=\"saveIcon\"\n [styleClass]=\"saveStyleClass\"\n [disabled]=\"saveDisabled\"\n (clickEvent)=\"onDefaultSave()\"\n />\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$5.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfButtonComponent, selector: "ef-button", inputs: ["label", "labelKey", "icon", "variant", "severity", "size", "disabled", "rounded", "outlined", "raised", "text", "loading", "styleClass", "type", "badge", "badgeSeverity", "tooltip", "tooltipKey", "tooltipPosition"], outputs: ["clickEvent"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
3327
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDialogComponent, isStandalone: true, selector: "ef-dialog", inputs: { header: "header", headerKey: "headerKey", subtitle: "subtitle", subtitleKey: "subtitleKey", visible: ["visible", "visible", booleanAttribute], modal: ["modal", "modal", booleanAttribute], closable: ["closable", "closable", booleanAttribute], draggable: ["draggable", "draggable", booleanAttribute], resizable: ["resizable", "resizable", booleanAttribute], dismissableMask: ["dismissableMask", "dismissableMask", booleanAttribute], closeOnEscape: ["closeOnEscape", "closeOnEscape", booleanAttribute], severity: "severity", icon: "icon", size: "size", style: "style", styleClass: "styleClass", position: "position", appendTo: "appendTo", variant: "variant", actions: "actions", defaultActions: ["defaultActions", "defaultActions", booleanAttribute], saveLabelKey: "saveLabelKey", cancelLabelKey: "cancelLabelKey", saveLabel: "saveLabel", cancelLabel: "cancelLabel", saveIcon: "saveIcon", cancelIcon: "cancelIcon", saveDisabled: ["saveDisabled", "saveDisabled", booleanAttribute], saveStyleClass: "saveStyleClass", cancelStyleClass: "cancelStyleClass", saveSeverity: "saveSeverity", cancelSeverity: "cancelSeverity" }, outputs: { visibleChange: "visibleChange", showEvent: "showEvent", hideEvent: "hideEvent", saveAction: "saveAction", cancelAction: "cancelAction", actionClick: "actionClick" }, viewQueries: [{ propertyName: "defaultFooterTpl", first: true, predicate: ["defaultFooter"], descendants: true, static: true }], ngImport: i0, template: "<p-dialog\n [visible]=\"visible\"\n (visibleChange)=\"handleVisibleChange($event)\"\n [modal]=\"modal\"\n [draggable]=\"draggable\"\n [resizable]=\"resizable\"\n [dismissableMask]=\"dismissableMask\"\n [closeOnEscape]=\"closeOnEscape\"\n [style]=\"style\"\n [styleClass]=\"effectiveStyleClass\"\n [position]=\"position\"\n [appendTo]=\"appendTo\"\n [header]=\"variant === 'primeng' ? effectiveTitle : null\"\n [closable]=\"variant === 'primeng' ? closable : false\"\n [footerTemplate]=\"variant === 'primeng' && !useDynamicActions && defaultActions ? defaultFooterTpl : null\"\n (onShow)=\"handleShow()\"\n (onHide)=\"handleHide()\"\n>\n <!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 COMPTOIR HEADER (content-child #header) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Replaces PrimeNG's default header strip with our icon + title\n + subtitle + close X structure. Skipped in 'primeng' variant\n (which uses the [header] string input + native close). -->\n @if (variant === 'comptoir') {\n <ng-template #header>\n @if (effectiveIcon) {\n <span class=\"es-dialog__icon\" aria-hidden=\"true\">\n <i [class]=\"effectiveIcon\"></i>\n </span>\n }\n <div class=\"es-dialog__title-block\">\n <div class=\"es-dialog__title\">{{ effectiveTitle }}</div>\n @if (effectiveSubtitle) {\n <div class=\"es-dialog__sub\">{{ effectiveSubtitle }}</div>\n }\n </div>\n @if (closable) {\n <button\n type=\"button\"\n class=\"es-dialog__close\"\n [attr.aria-label]=\"'common_close' | translate\"\n (click)=\"handleVisibleChange(false)\"\n >\n <i class=\"pi pi-times\"></i>\n </button>\n }\n </ng-template>\n }\n\n <!-- Body \u2014 projected from <ef-dialog>\u2026</ef-dialog> -->\n <ng-content />\n\n <!-- \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 COMPTOIR FOOTER (content-child #footer) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Dynamic [actions] path takes precedence; falls back to the\n backward-compat save+cancel pair when defaultActions is on. -->\n @if (variant === 'comptoir' && hasFooter) {\n <ng-template #footer>\n @if (useDynamicActions) {\n @for (a of actions; track $index) {\n <button\n type=\"button\"\n [class]=\"actionClass(a)\"\n [disabled]=\"a.disabled || a.loading\"\n (click)=\"handleActionClick(a, $index)\"\n >\n @if (a.icon) {\n <i [class]=\"a.icon\"></i>\n }\n {{ actionLabel(a) }}\n </button>\n }\n } @else {\n <ef-button\n variant=\"comptoir\"\n [severity]=\"cancelSeverity\"\n [labelKey]=\"cancelLabelKey\"\n [label]=\"cancelLabel\"\n [icon]=\"cancelIcon\"\n [styleClass]=\"cancelStyleClass\"\n (clickEvent)=\"onDefaultCancel()\"\n />\n <ef-button\n variant=\"comptoir\"\n [severity]=\"saveSeverity\"\n [labelKey]=\"saveLabelKey\"\n [label]=\"saveLabel\"\n [icon]=\"saveIcon\"\n [styleClass]=\"saveStyleClass\"\n [disabled]=\"saveDisabled\"\n (clickEvent)=\"onDefaultSave()\"\n />\n }\n </ng-template>\n }\n</p-dialog>\n\n<!-- Default-action footer template for the 'primeng' variant (legacy path).\n Declared outside <p-dialog> because the comptoir branch above already\n provides its own content-child footer; this template is only consumed\n when variant === 'primeng' via [footerTemplate] input binding. -->\n<ng-template #defaultFooter>\n <ef-button\n variant=\"primeng\"\n [severity]=\"cancelSeverity\"\n [labelKey]=\"cancelLabelKey\"\n [label]=\"cancelLabel\"\n [icon]=\"cancelIcon\"\n [styleClass]=\"cancelStyleClass\"\n (clickEvent)=\"onDefaultCancel()\"\n />\n <ef-button\n variant=\"primeng\"\n [severity]=\"saveSeverity\"\n [labelKey]=\"saveLabelKey\"\n [label]=\"saveLabel\"\n [icon]=\"saveIcon\"\n [styleClass]=\"saveStyleClass\"\n [disabled]=\"saveDisabled\"\n (clickEvent)=\"onDefaultSave()\"\n />\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1$6.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfButtonComponent, selector: "ef-button", inputs: ["label", "labelKey", "icon", "variant", "severity", "size", "disabled", "rounded", "outlined", "raised", "text", "loading", "styleClass", "type", "badge", "badgeSeverity", "tooltip", "tooltipKey", "tooltipPosition"], outputs: ["clickEvent"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
3320
3328
  }
3321
3329
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDialogComponent, decorators: [{
3322
3330
  type: Component,
@@ -4190,7 +4198,7 @@ class EfOrderSummaryComponent {
4190
4198
  */
4191
4199
  hasGroups = computed(() => this.groupedCounts().length > 0, ...(ngDevMode ? [{ debugName: "hasGroups" }] : /* istanbul ignore next */ []));
4192
4200
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfOrderSummaryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4193
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfOrderSummaryComponent, isStandalone: true, selector: "ef-order-summary", inputs: { orderLines: { classPropertyName: "orderLines", publicName: "orderLines", isSignal: true, isRequired: true, transformFunction: null }, countGroupLabels: { classPropertyName: "countGroupLabels", publicName: "countGroupLabels", isSignal: true, isRequired: false, transformFunction: null }, legend: { classPropertyName: "legend", publicName: "legend", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (hasGroups()) {\n <p-fieldset [legend]=\"legend()\">\n <div class=\"ef-order-summary\">\n <div class=\"ef-order-summary__content\">\n @for (column of columnGroups(); track $index) {\n <div class=\"ef-order-summary__column\">\n @for (group of column; track group.code) {\n <div class=\"ef-order-summary__item\">\n <span class=\"ef-order-summary__label\">{{ group.label }}:</span>\n <span class=\"ef-order-summary__count\">{{ group.count }}</span>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"ef-order-summary__footer\">\n <span class=\"ef-order-summary__total-label\">Total:</span>\n <span class=\"ef-order-summary__total-count\">{{ totalCount() }}</span>\n </div>\n </div>\n </p-fieldset>\n}\n", styles: [".ef-order-summary__content{display:flex;gap:2rem;padding:1rem .25rem}.ef-order-summary__column{flex:1;display:flex;flex-direction:column;gap:.25rem}.ef-order-summary__column:not(:last-child){border-right:1px solid var(--p-surface-200);padding-right:2rem}.ef-order-summary__item{display:flex;justify-content:space-between;align-items:center;font-size:.875rem}.ef-order-summary__label{font-weight:600;color:var(--p-surface-700)}:host-context(.dark) .ef-order-summary__label{color:var(--p-surface-300)}.ef-order-summary__count{font-weight:500;color:var(--p-surface-900)}:host-context(.dark) .ef-order-summary__count{color:var(--p-surface-100)}.ef-order-summary__footer{display:flex;justify-content:space-between;align-items:center;padding-top:.75rem;border-top:1px solid var(--p-surface-300)}.ef-order-summary__total-label,.ef-order-summary__total-count{font-size:1rem;font-weight:700;color:var(--p-primary-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FieldsetModule }, { kind: "component", type: i1$6.Fieldset, selector: "p-fieldset", inputs: ["legend", "toggleable", "style", "styleClass", "transitionOptions", "motionOptions", "collapsed"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }] });
4201
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfOrderSummaryComponent, isStandalone: true, selector: "ef-order-summary", inputs: { orderLines: { classPropertyName: "orderLines", publicName: "orderLines", isSignal: true, isRequired: true, transformFunction: null }, countGroupLabels: { classPropertyName: "countGroupLabels", publicName: "countGroupLabels", isSignal: true, isRequired: false, transformFunction: null }, legend: { classPropertyName: "legend", publicName: "legend", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (hasGroups()) {\n <p-fieldset [legend]=\"legend()\">\n <div class=\"ef-order-summary\">\n <div class=\"ef-order-summary__content\">\n @for (column of columnGroups(); track $index) {\n <div class=\"ef-order-summary__column\">\n @for (group of column; track group.code) {\n <div class=\"ef-order-summary__item\">\n <span class=\"ef-order-summary__label\">{{ group.label }}:</span>\n <span class=\"ef-order-summary__count\">{{ group.count }}</span>\n </div>\n }\n </div>\n }\n </div>\n <div class=\"ef-order-summary__footer\">\n <span class=\"ef-order-summary__total-label\">Total:</span>\n <span class=\"ef-order-summary__total-count\">{{ totalCount() }}</span>\n </div>\n </div>\n </p-fieldset>\n}\n", styles: [".ef-order-summary__content{display:flex;gap:2rem;padding:1rem .25rem}.ef-order-summary__column{flex:1;display:flex;flex-direction:column;gap:.25rem}.ef-order-summary__column:not(:last-child){border-right:1px solid var(--p-surface-200);padding-right:2rem}.ef-order-summary__item{display:flex;justify-content:space-between;align-items:center;font-size:.875rem}.ef-order-summary__label{font-weight:600;color:var(--p-surface-700)}:host-context(.dark) .ef-order-summary__label{color:var(--p-surface-300)}.ef-order-summary__count{font-weight:500;color:var(--p-surface-900)}:host-context(.dark) .ef-order-summary__count{color:var(--p-surface-100)}.ef-order-summary__footer{display:flex;justify-content:space-between;align-items:center;padding-top:.75rem;border-top:1px solid var(--p-surface-300)}.ef-order-summary__total-label,.ef-order-summary__total-count{font-size:1rem;font-weight:700;color:var(--p-primary-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FieldsetModule }, { kind: "component", type: i1$7.Fieldset, selector: "p-fieldset", inputs: ["legend", "toggleable", "style", "styleClass", "transitionOptions", "motionOptions", "collapsed"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }] });
4194
4202
  }
4195
4203
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfOrderSummaryComponent, decorators: [{
4196
4204
  type: Component,
@@ -4274,7 +4282,7 @@ class EfProductCatalogueFilterComponent {
4274
4282
  return (group.children?.length || 0) > 5;
4275
4283
  }
4276
4284
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfProductCatalogueFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4277
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfProductCatalogueFilterComponent, isStandalone: true, selector: "ef-product-catalogue-filter", inputs: { categoryGroups: { classPropertyName: "categoryGroups", publicName: "categoryGroups", isSignal: true, isRequired: true, transformFunction: null }, products: { classPropertyName: "products", publicName: "products", isSignal: true, isRequired: true, transformFunction: null }, selectedFilters: { classPropertyName: "selectedFilters", publicName: "selectedFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedFilters: "selectedFiltersChange", filtersChanged: "filtersChanged" }, ngImport: i0, template: "<div class=\"flex w-80 shrink-0 flex-col items-start justify-start sticky top-4 max-h-[calc(100vh-2rem)] overflow-y-auto\">\n <div\n class=\"mb-4 flex flex-col items-start justify-center gap-2 self-stretch border-b border-surface-200 px-2 pb-4 dark:border-surface-700\"\n >\n <div class=\"flex items-center justify-between gap-2 self-stretch\">\n <div\n class=\"text-base font-semibold leading-tight text-surface-900 dark:text-surface-0\"\n >\n Filters\n </div>\n <p-button\n size=\"small\"\n severity=\"secondary\"\n [text]=\"true\"\n class=\"py-1! px-2! text-base! font-normal!\"\n (clickEvent)=\"clearAllFilters()\"\n >\n <span pButtonLabel>\n <i class=\"pi pi-eraser\"></i>\n Clear\n </span>\n </p-button>\n </div>\n @if (selectedFilters().length > 0) {\n <div\n class=\"flex flex-wrap items-start justify-start gap-2 self-stretch\"\n >\n @for (filter of selectedFilters(); track filter.type + filter.code) {\n <p-chip\n [label]=\"filter.label\"\n [removable]=\"true\"\n size=\"small\"\n class=\"h-auto rounded-full px-6\"\n removeIcon=\"pi pi-times\"\n (onRemove)=\"removeFilter(filter)\"\n ></p-chip>\n }\n </div>\n }\n </div>\n\n <p-accordion\n [multiple]=\"true\"\n [value]=\"expandedPanels()\"\n class=\"w-full\"\n >\n @for (group of categoryGroups(); track group.code) {\n @if (group.children && group.children.length > 0) {\n <p-accordion-panel [value]=\"group.code\">\n <p-accordion-header>\n <span\n class=\"text-base font-semibold leading-tight text-surface-900 dark:text-surface-0\"\n >{{ group.label }}</span>\n </p-accordion-header>\n <p-accordion-content>\n <div class=\"flex flex-col gap-4\">\n @if (shouldShowSearch(group)) {\n <p-iconfield iconPosition=\"left\" class=\"w-full\">\n <p-inputicon class=\"pi pi-search\"></p-inputicon>\n <input\n pInputText\n size=\"small\"\n [ngModel]=\"searchTerms()[group.code] || ''\"\n (ngModelChange)=\"updateSearchTerm(group.code, $event)\"\n [placeholder]=\"'Rechercher ' + group.label.toLowerCase()\"\n class=\"w-full\"\n />\n </p-iconfield>\n }\n\n @for (item of getFilteredChildren(group); track item.code) {\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"flex flex-1 items-center gap-2\">\n <p-checkbox\n size=\"small\"\n [inputId]=\"group.code + '_' + item.code\"\n [binary]=\"true\"\n [ngModel]=\"isFilterSelected(group.code, item.code)\"\n (ngModelChange)=\"toggleFilter(group, item)\"\n ></p-checkbox>\n @if (getColorClass(item)) {\n <div\n class=\"h-5 w-5 rounded-full\"\n [class]=\"getColorClass(item)\"\n ></div>\n }\n <ef-label\n [label]=\"item.label\"\n [for]=\"group.code + '_' + item.code\"\n styleClass=\"cursor-pointer text-base font-normal leading-tight text-surface-700 dark:text-surface-300\"\n />\n </div>\n @if (getItemCount(group.code, item.code) > 0) {\n <p-badge\n [value]=\"getItemCount(group.code, item.code)\"\n size=\"small\"\n class=\"rounded-xl! h-6! min-w-6!\"\n severity=\"secondary\"\n ></p-badge>\n }\n </div>\n }\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n }\n }\n </p-accordion>\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AccordionModule }, { kind: "component", type: i2$3.Accordion, selector: "p-accordion", inputs: ["value", "multiple", "styleClass", "expandIcon", "collapseIcon", "selectOnFocus", "transitionOptions", "motionOptions"], outputs: ["valueChange", "onClose", "onOpen"] }, { kind: "component", type: i2$3.AccordionPanel, selector: "p-accordion-panel, p-accordionpanel", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: i2$3.AccordionHeader, selector: "p-accordion-header, p-accordionheader" }, { kind: "component", type: i2$3.AccordionContent, selector: "p-accordion-content, p-accordioncontent" }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i3.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i1.ButtonLabel, selector: "[pButtonLabel]", inputs: ["ptButtonLabel", "pButtonLabelPT", "pButtonLabelUnstyled"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i5.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ChipModule }, { kind: "component", type: i6.Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i7.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i8.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i9.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4285
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfProductCatalogueFilterComponent, isStandalone: true, selector: "ef-product-catalogue-filter", inputs: { categoryGroups: { classPropertyName: "categoryGroups", publicName: "categoryGroups", isSignal: true, isRequired: true, transformFunction: null }, products: { classPropertyName: "products", publicName: "products", isSignal: true, isRequired: true, transformFunction: null }, selectedFilters: { classPropertyName: "selectedFilters", publicName: "selectedFilters", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedFilters: "selectedFiltersChange", filtersChanged: "filtersChanged" }, ngImport: i0, template: "<div class=\"flex w-80 shrink-0 flex-col items-start justify-start sticky top-4 max-h-[calc(100vh-2rem)] overflow-y-auto\">\n <div\n class=\"mb-4 flex flex-col items-start justify-center gap-2 self-stretch border-b border-surface-200 px-2 pb-4 dark:border-surface-700\"\n >\n <div class=\"flex items-center justify-between gap-2 self-stretch\">\n <div\n class=\"text-base font-semibold leading-tight text-surface-900 dark:text-surface-0\"\n >\n Filters\n </div>\n <p-button\n size=\"small\"\n severity=\"secondary\"\n [text]=\"true\"\n class=\"py-1! px-2! text-base! font-normal!\"\n (clickEvent)=\"clearAllFilters()\"\n >\n <span pButtonLabel>\n <i class=\"pi pi-eraser\"></i>\n Clear\n </span>\n </p-button>\n </div>\n @if (selectedFilters().length > 0) {\n <div\n class=\"flex flex-wrap items-start justify-start gap-2 self-stretch\"\n >\n @for (filter of selectedFilters(); track filter.type + filter.code) {\n <p-chip\n [label]=\"filter.label\"\n [removable]=\"true\"\n size=\"small\"\n class=\"h-auto rounded-full px-6\"\n removeIcon=\"pi pi-times\"\n (onRemove)=\"removeFilter(filter)\"\n ></p-chip>\n }\n </div>\n }\n </div>\n\n <p-accordion\n [multiple]=\"true\"\n [value]=\"expandedPanels()\"\n class=\"w-full\"\n >\n @for (group of categoryGroups(); track group.code) {\n @if (group.children && group.children.length > 0) {\n <p-accordion-panel [value]=\"group.code\">\n <p-accordion-header>\n <span\n class=\"text-base font-semibold leading-tight text-surface-900 dark:text-surface-0\"\n >{{ group.label }}</span>\n </p-accordion-header>\n <p-accordion-content>\n <div class=\"flex flex-col gap-4\">\n @if (shouldShowSearch(group)) {\n <p-iconfield iconPosition=\"left\" class=\"w-full\">\n <p-inputicon class=\"pi pi-search\"></p-inputicon>\n <input\n pInputText\n size=\"small\"\n [ngModel]=\"searchTerms()[group.code] || ''\"\n (ngModelChange)=\"updateSearchTerm(group.code, $event)\"\n [placeholder]=\"'Rechercher ' + group.label.toLowerCase()\"\n class=\"w-full\"\n />\n </p-iconfield>\n }\n\n @for (item of getFilteredChildren(group); track item.code) {\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"flex flex-1 items-center gap-2\">\n <p-checkbox\n size=\"small\"\n [inputId]=\"group.code + '_' + item.code\"\n [binary]=\"true\"\n [ngModel]=\"isFilterSelected(group.code, item.code)\"\n (ngModelChange)=\"toggleFilter(group, item)\"\n ></p-checkbox>\n @if (getColorClass(item)) {\n <div\n class=\"h-5 w-5 rounded-full\"\n [class]=\"getColorClass(item)\"\n ></div>\n }\n <ef-label\n [label]=\"item.label\"\n [for]=\"group.code + '_' + item.code\"\n styleClass=\"cursor-pointer text-base font-normal leading-tight text-surface-700 dark:text-surface-300\"\n />\n </div>\n @if (getItemCount(group.code, item.code) > 0) {\n <p-badge\n [value]=\"getItemCount(group.code, item.code)\"\n size=\"small\"\n class=\"rounded-xl! h-6! min-w-6!\"\n severity=\"secondary\"\n ></p-badge>\n }\n </div>\n }\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n }\n }\n </p-accordion>\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AccordionModule }, { kind: "component", type: i2$2.Accordion, selector: "p-accordion", inputs: ["value", "multiple", "styleClass", "expandIcon", "collapseIcon", "selectOnFocus", "transitionOptions", "motionOptions"], outputs: ["valueChange", "onClose", "onOpen"] }, { kind: "component", type: i2$2.AccordionPanel, selector: "p-accordion-panel, p-accordionpanel", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: i2$2.AccordionHeader, selector: "p-accordion-header, p-accordionheader" }, { kind: "component", type: i2$2.AccordionContent, selector: "p-accordion-content, p-accordioncontent" }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i3.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i1.ButtonLabel, selector: "[pButtonLabel]", inputs: ["ptButtonLabel", "pButtonLabelPT", "pButtonLabelUnstyled"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i5.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ChipModule }, { kind: "component", type: i6.Chip, selector: "p-chip", inputs: ["label", "icon", "image", "alt", "styleClass", "disabled", "removable", "removeIcon", "chipProps"], outputs: ["onRemove", "onImageError"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i7.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i8.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i9.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4278
4286
  }
4279
4287
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfProductCatalogueFilterComponent, decorators: [{
4280
4288
  type: Component,
@@ -4591,7 +4599,7 @@ class EfProductCatalogueComponent {
4591
4599
  return (this.currencyPipe.transform(value, this.currencyCode(), 'symbol-narrow', '1.2-2') || '');
4592
4600
  }
4593
4601
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfProductCatalogueComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4594
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfProductCatalogueComponent, isStandalone: true, selector: "ef-product-catalogue", inputs: { products: { classPropertyName: "products", publicName: "products", isSignal: true, isRequired: false, transformFunction: null }, categoryGroups: { classPropertyName: "categoryGroups", publicName: "categoryGroups", isSignal: true, isRequired: false, transformFunction: null }, initialSelectedItems: { classPropertyName: "initialSelectedItems", publicName: "initialSelectedItems", isSignal: true, isRequired: false, transformFunction: null }, defaultFilters: { classPropertyName: "defaultFilters", publicName: "defaultFilters", isSignal: true, isRequired: false, transformFunction: null }, trackByField: { classPropertyName: "trackByField", publicName: "trackByField", isSignal: true, isRequired: false, transformFunction: null }, currencyCode: { classPropertyName: "currencyCode", publicName: "currencyCode", isSignal: true, isRequired: false, transformFunction: null }, localeCode: { classPropertyName: "localeCode", publicName: "localeCode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { productsValidated: "productsValidated" }, queries: [{ propertyName: "productThumbnailTpl", first: true, predicate: ["productThumbnail"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "sortMenu", first: true, predicate: ["sortMenu"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"bg-surface-0 dark:bg-surface-950\">\n <div class=\"flex flex-row gap-4\">\n <!-- Filter Sidebar -->\n <ef-product-catalogue-filter\n [categoryGroups]=\"categoryGroups()\"\n [products]=\"products()\"\n [(selectedFilters)]=\"selectedFilters\"\n (filtersChanged)=\"onFiltersChanged($event)\"\n />\n\n <!-- Product Grid -->\n <div\n class=\"min-h-96 flex-1 rounded-md border-2 border-dotted border-surface-200 bg-surface-50 p-4 dark:border-surface-700 dark:bg-surface-800\"\n >\n <div class=\"sticky top-0 z-10 w-full mb-4 bg-surface-50 dark:bg-surface-800 pb-2 -mt-4 pt-4 -mx-4 px-4\">\n <p-iconfield iconPosition=\"left\" class=\"w-full\">\n <p-inputicon class=\"pi pi-search\"></p-inputicon>\n <input\n pInputText\n size=\"small\"\n [(ngModel)]=\"productSearch\"\n [placeholder]=\"'placeholder.search_products' | translate\"\n class=\"w-full\"\n />\n </p-iconfield>\n </div>\n <div class=\"grid grid-cols-2 gap-4 lg:grid-cols-3 xl:grid-cols-4\">\n @for (product of filteredProducts(); track trackKey(product)) {\n <p-card\n [header]=\"''\"\n [class.border-2]=\"true\"\n [class.border-blue-100]=\"getProductQuantity(product) > 0\"\n [class.!bg-blue-100]=\"getProductQuantity(product) > 0\"\n [class.dark:!border-blue-900]=\"getProductQuantity(product) > 0\"\n [class.dark:!bg-blue-900]=\"getProductQuantity(product) > 0\"\n [class.border-transparent]=\"getProductQuantity(product) === 0\"\n class=\"cursor-pointer hover:shadow-md dark:hover:shadow-md dark:hover:shadow-gray-300/50\"\n >\n <ng-template pTemplate=\"header\">\n <div class=\"w-full\">\n @if (productThumbnailTpl()) {\n <ng-container *ngTemplateOutlet=\"productThumbnailTpl(); context: { $implicit: product }\"></ng-container>\n } @else {\n <!-- Default fallback thumbnail -->\n <div class=\"flex h-[13rem] items-center justify-center bg-surface-100 text-3xl text-surface-400 dark:bg-surface-800\">\n <i class=\"pi pi-box\"></i>\n </div>\n }\n </div>\n </ng-template>\n <ng-template pTemplate=\"content\">\n <div [innerHTML]=\"product.displayName\" class=\"h-14 font-semibold\"></div>\n </ng-template>\n <ng-template pTemplate=\"footer\">\n @if (isVariableProduct(product)) {\n <!-- Variable product: variant selector + per-variant quantities -->\n <div class=\"flex items-center justify-between mb-2\">\n <p-badge\n severity=\"secondary\"\n [value]=\"getActiveVariants(product).length + ' ' + ('catalogue.variants' | translate)\"\n badgeSize=\"small\"\n />\n <div class=\"text-lg font-bold\">\n {{ formatPrice(product) }}\n </div>\n </div>\n\n <!-- Variant selector -->\n <p-select\n [options]=\"getActiveVariants(product)\"\n optionLabel=\"title\"\n optionValue=\"variantId\"\n [ngModel]=\"getSelectedVariantId(product)\"\n (ngModelChange)=\"setSelectedVariant(product, $event)\"\n size=\"small\"\n styleClass=\"w-full mb-3\"\n [placeholder]=\"'placeholder.select_variant' | translate\"\n />\n\n <!-- Add button or quantity stepper for selected variant -->\n <div class=\"mt-2\">\n @if (getProductQuantity(product) > 0) {\n <!-- Show per-variant breakdown -->\n @for (entry of selectedProducts(); track $index) {\n @if (productKey(entry.product) === productKey(product) && entry.variantId) {\n <div class=\"flex items-center justify-center gap-2 mb-2\">\n <span class=\"text-xs font-medium text-surface-600 dark:text-surface-400 min-w-12 text-center\">\n {{ getVariantTitle(product, entry.variantId) }}\n </span>\n <ef-quantity-stepper\n [ngModel]=\"entry.quantity\"\n (ngModelChange)=\"updateVariantQuantity(product, entry.variantId!, $event)\"\n [min]=\"0\"\n [max]=\"1000\"\n [maxFractionDigits]=\"4\"\n [locale]=\"localeCode()\"\n />\n <ef-button\n icon=\"pi pi-times\"\n severity=\"danger\"\n styleClass=\"!rounded-full !w-7 !h-7 !p-0\"\n size=\"small\"\n (clickEvent)=\"removeVariantSelection(product, entry.variantId!)\"\n />\n </div>\n }\n }\n <!-- Add another variant button -->\n <ef-button\n icon=\"pi pi-plus\"\n [label]=\"'button.add_variant' | translate\"\n severity=\"primary\"\n styleClass=\"w-full !rounded-full !h-10 mt-1\"\n size=\"small\"\n (clickEvent)=\"addProduct(product)\"\n />\n } @else {\n <ef-button\n [label]=\"'button.add' | translate\"\n icon=\"pi pi-shopping-cart\"\n severity=\"primary\"\n styleClass=\"w-full !rounded-full !h-12\"\n (clickEvent)=\"addProduct(product)\"\n />\n }\n </div>\n } @else {\n <!-- Simple product: original behavior -->\n <div class=\"flex items-center justify-between\">\n <p-badge\n severity=\"secondary\"\n [value]=\"getPackagingLabel(product)\"\n badgeSize=\"small\"\n />\n <div class=\"text-lg font-bold\">\n {{ formatPrice(product) }}\n </div>\n </div>\n <div class=\"mt-4\">\n @if (getProductQuantity(product) > 0) {\n <div class=\"flex items-center justify-between\">\n <ef-button\n icon=\"pi pi-trash\"\n severity=\"primary\"\n styleClass=\"!rounded-full\"\n (clickEvent)=\"removeProduct(product)\"\n />\n <ef-quantity-stepper\n [ngModel]=\"getProductQuantity(product)\"\n (ngModelChange)=\"updateProductQuantity(product, $event)\"\n [min]=\"0\"\n [max]=\"1000\"\n [maxFractionDigits]=\"4\"\n [locale]=\"localeCode()\"\n />\n </div>\n } @else {\n <ef-button\n [label]=\"'button.add' | translate\"\n icon=\"pi pi-shopping-cart\"\n severity=\"primary\"\n styleClass=\"w-full !rounded-full !h-12\"\n (clickEvent)=\"addProduct(product)\"\n />\n }\n </div>\n }\n </ng-template>\n </p-card>\n } @empty {\n <div class=\"p-2\">{{ 'message.no_products_found' | translate }}</div>\n }\n </div>\n </div>\n </div>\n</div>\n", styles: [".p-accordion-header-link{border:0!important;padding:.25rem 0!important;box-shadow:none!important}.p-accordion-panel{border:0!important;border-bottom:1px solid var(--surface-200)!important}:host-context(.dark) .p-accordion-panel{border-bottom-color:var(--surface-700)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i3.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: EfButtonComponent, selector: "ef-button", inputs: ["label", "labelKey", "icon", "variant", "severity", "size", "disabled", "rounded", "outlined", "raised", "text", "loading", "styleClass", "type", "badge", "badgeSeverity", "tooltip", "tooltipKey", "tooltipPosition"], outputs: ["clickEvent"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i5$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i7.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i8.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i9.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i1$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: EfQuantityStepperComponent, selector: "ef-quantity-stepper", inputs: ["value", "min", "max", "step", "minFractionDigits", "maxFractionDigits", "locale", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: EfProductCatalogueFilterComponent, selector: "ef-product-catalogue-filter", inputs: ["categoryGroups", "products", "selectedFilters"], outputs: ["selectedFiltersChange", "filtersChanged"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4602
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfProductCatalogueComponent, isStandalone: true, selector: "ef-product-catalogue", inputs: { products: { classPropertyName: "products", publicName: "products", isSignal: true, isRequired: false, transformFunction: null }, categoryGroups: { classPropertyName: "categoryGroups", publicName: "categoryGroups", isSignal: true, isRequired: false, transformFunction: null }, initialSelectedItems: { classPropertyName: "initialSelectedItems", publicName: "initialSelectedItems", isSignal: true, isRequired: false, transformFunction: null }, defaultFilters: { classPropertyName: "defaultFilters", publicName: "defaultFilters", isSignal: true, isRequired: false, transformFunction: null }, trackByField: { classPropertyName: "trackByField", publicName: "trackByField", isSignal: true, isRequired: false, transformFunction: null }, currencyCode: { classPropertyName: "currencyCode", publicName: "currencyCode", isSignal: true, isRequired: false, transformFunction: null }, localeCode: { classPropertyName: "localeCode", publicName: "localeCode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { productsValidated: "productsValidated" }, queries: [{ propertyName: "productThumbnailTpl", first: true, predicate: ["productThumbnail"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "sortMenu", first: true, predicate: ["sortMenu"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"bg-surface-0 dark:bg-surface-950\">\n <div class=\"flex flex-row gap-4\">\n <!-- Filter Sidebar -->\n <ef-product-catalogue-filter\n [categoryGroups]=\"categoryGroups()\"\n [products]=\"products()\"\n [(selectedFilters)]=\"selectedFilters\"\n (filtersChanged)=\"onFiltersChanged($event)\"\n />\n\n <!-- Product Grid -->\n <div\n class=\"min-h-96 flex-1 rounded-md border-2 border-dotted border-surface-200 bg-surface-50 p-4 dark:border-surface-700 dark:bg-surface-800\"\n >\n <div class=\"sticky top-0 z-10 w-full mb-4 bg-surface-50 dark:bg-surface-800 pb-2 -mt-4 pt-4 -mx-4 px-4\">\n <p-iconfield iconPosition=\"left\" class=\"w-full\">\n <p-inputicon class=\"pi pi-search\"></p-inputicon>\n <input\n pInputText\n size=\"small\"\n [(ngModel)]=\"productSearch\"\n [placeholder]=\"'placeholder.search_products' | translate\"\n class=\"w-full\"\n />\n </p-iconfield>\n </div>\n <div class=\"grid grid-cols-2 gap-4 lg:grid-cols-3 xl:grid-cols-4\">\n @for (product of filteredProducts(); track trackKey(product)) {\n <p-card\n [header]=\"''\"\n [class.border-2]=\"true\"\n [class.border-blue-100]=\"getProductQuantity(product) > 0\"\n [class.!bg-blue-100]=\"getProductQuantity(product) > 0\"\n [class.dark:!border-blue-900]=\"getProductQuantity(product) > 0\"\n [class.dark:!bg-blue-900]=\"getProductQuantity(product) > 0\"\n [class.border-transparent]=\"getProductQuantity(product) === 0\"\n class=\"cursor-pointer hover:shadow-md dark:hover:shadow-md dark:hover:shadow-gray-300/50\"\n >\n <ng-template pTemplate=\"header\">\n <div class=\"w-full\">\n @if (productThumbnailTpl()) {\n <ng-container *ngTemplateOutlet=\"productThumbnailTpl(); context: { $implicit: product }\"></ng-container>\n } @else {\n <!-- Default fallback thumbnail -->\n <div class=\"flex h-[13rem] items-center justify-center bg-surface-100 text-3xl text-surface-400 dark:bg-surface-800\">\n <i class=\"pi pi-box\"></i>\n </div>\n }\n </div>\n </ng-template>\n <ng-template pTemplate=\"content\">\n <div [innerHTML]=\"product.displayName\" class=\"h-14 font-semibold\"></div>\n </ng-template>\n <ng-template pTemplate=\"footer\">\n @if (isVariableProduct(product)) {\n <!-- Variable product: variant selector + per-variant quantities -->\n <div class=\"flex items-center justify-between mb-2\">\n <p-badge\n severity=\"secondary\"\n [value]=\"getActiveVariants(product).length + ' ' + ('catalogue.variants' | translate)\"\n badgeSize=\"small\"\n />\n <div class=\"text-lg font-bold\">\n {{ formatPrice(product) }}\n </div>\n </div>\n\n <!-- Variant selector -->\n <p-select\n [options]=\"getActiveVariants(product)\"\n optionLabel=\"title\"\n optionValue=\"variantId\"\n [ngModel]=\"getSelectedVariantId(product)\"\n (ngModelChange)=\"setSelectedVariant(product, $event)\"\n size=\"small\"\n styleClass=\"w-full mb-3\"\n [placeholder]=\"'placeholder.select_variant' | translate\"\n />\n\n <!-- Add button or quantity stepper for selected variant -->\n <div class=\"mt-2\">\n @if (getProductQuantity(product) > 0) {\n <!-- Show per-variant breakdown -->\n @for (entry of selectedProducts(); track $index) {\n @if (productKey(entry.product) === productKey(product) && entry.variantId) {\n <div class=\"flex items-center justify-center gap-2 mb-2\">\n <span class=\"text-xs font-medium text-surface-600 dark:text-surface-400 min-w-12 text-center\">\n {{ getVariantTitle(product, entry.variantId) }}\n </span>\n <ef-quantity-stepper\n [ngModel]=\"entry.quantity\"\n (ngModelChange)=\"updateVariantQuantity(product, entry.variantId!, $event)\"\n [min]=\"0\"\n [max]=\"1000\"\n [maxFractionDigits]=\"4\"\n [locale]=\"localeCode()\"\n />\n <ef-button\n icon=\"pi pi-times\"\n severity=\"danger\"\n styleClass=\"!rounded-full !w-7 !h-7 !p-0\"\n size=\"small\"\n (clickEvent)=\"removeVariantSelection(product, entry.variantId!)\"\n />\n </div>\n }\n }\n <!-- Add another variant button -->\n <ef-button\n icon=\"pi pi-plus\"\n [label]=\"'button.add_variant' | translate\"\n severity=\"primary\"\n styleClass=\"w-full !rounded-full !h-10 mt-1\"\n size=\"small\"\n (clickEvent)=\"addProduct(product)\"\n />\n } @else {\n <ef-button\n [label]=\"'button.add' | translate\"\n icon=\"pi pi-shopping-cart\"\n severity=\"primary\"\n styleClass=\"w-full !rounded-full !h-12\"\n (clickEvent)=\"addProduct(product)\"\n />\n }\n </div>\n } @else {\n <!-- Simple product: original behavior -->\n <div class=\"flex items-center justify-between\">\n <p-badge\n severity=\"secondary\"\n [value]=\"getPackagingLabel(product)\"\n badgeSize=\"small\"\n />\n <div class=\"text-lg font-bold\">\n {{ formatPrice(product) }}\n </div>\n </div>\n <div class=\"mt-4\">\n @if (getProductQuantity(product) > 0) {\n <div class=\"flex items-center justify-between\">\n <ef-button\n icon=\"pi pi-trash\"\n severity=\"primary\"\n styleClass=\"!rounded-full\"\n (clickEvent)=\"removeProduct(product)\"\n />\n <ef-quantity-stepper\n [ngModel]=\"getProductQuantity(product)\"\n (ngModelChange)=\"updateProductQuantity(product, $event)\"\n [min]=\"0\"\n [max]=\"1000\"\n [maxFractionDigits]=\"4\"\n [locale]=\"localeCode()\"\n />\n </div>\n } @else {\n <ef-button\n [label]=\"'button.add' | translate\"\n icon=\"pi pi-shopping-cart\"\n severity=\"primary\"\n styleClass=\"w-full !rounded-full !h-12\"\n (clickEvent)=\"addProduct(product)\"\n />\n }\n </div>\n }\n </ng-template>\n </p-card>\n } @empty {\n <div class=\"p-2\">{{ 'message.no_products_found' | translate }}</div>\n }\n </div>\n </div>\n </div>\n</div>\n", styles: [".p-accordion-header-link{border:0!important;padding:.25rem 0!important;box-shadow:none!important}.p-accordion-panel{border:0!important;border-bottom:1px solid var(--surface-200)!important}:host-context(.dark) .p-accordion-panel{border-bottom-color:var(--surface-700)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i3.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: EfButtonComponent, selector: "ef-button", inputs: ["label", "labelKey", "icon", "variant", "severity", "size", "disabled", "rounded", "outlined", "raised", "text", "loading", "styleClass", "type", "badge", "badgeSeverity", "tooltip", "tooltipKey", "tooltipPosition"], outputs: ["clickEvent"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i5$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i7.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i8.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i9.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: MenuModule }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i1$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: EfQuantityStepperComponent, selector: "ef-quantity-stepper", inputs: ["value", "min", "max", "step", "minFractionDigits", "maxFractionDigits", "locale", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: EfProductCatalogueFilterComponent, selector: "ef-product-catalogue-filter", inputs: ["categoryGroups", "products", "selectedFilters"], outputs: ["selectedFiltersChange", "filtersChanged"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4595
4603
  }
4596
4604
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfProductCatalogueComponent, decorators: [{
4597
4605
  type: Component,
@@ -4615,6 +4623,211 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
4615
4623
  args: ['sortMenu']
4616
4624
  }], productsValidated: [{ type: i0.Output, args: ["productsValidated"] }] } });
4617
4625
 
4626
+ /**
4627
+ * The app-wide confirmation modal, wearing the same skin as `ef-dialog`.
4628
+ *
4629
+ * PrimeNG's `<p-confirmdialog>` renders an ordinary `<p-dialog>` inside
4630
+ * itself and forwards `styleClass` to its root, so handing it the
4631
+ * `es-dialog` classes makes every rule that dresses `ef-dialog` — the
4632
+ * paper-alt panel, the rule-separated header and footer, the Bricolage
4633
+ * title, the ghost close — apply here too. Only the confirm-specific
4634
+ * internals (the icon tile, the message, the two action buttons) need
4635
+ * their own rules, and those live beside the rest in `_patterns.scss`.
4636
+ *
4637
+ * Drop one instance at the application root; the content is driven by
4638
+ * `ConfirmDialogService.confirm()`, not by inputs.
4639
+ *
4640
+ * ```html
4641
+ * <ef-confirm-dialog />
4642
+ * ```
4643
+ */
4644
+ class EfConfirmDialogComponent {
4645
+ /** Panel width preset, mirroring `ef-dialog`'s `size`. */
4646
+ size = input('sm', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4647
+ /** Extra classes appended to the panel. */
4648
+ styleClass = input('', ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
4649
+ effectiveStyleClass = () => ['es-dialog', `es-dialog--${this.size()}`, 'es-confirm', this.styleClass()]
4650
+ .filter(Boolean)
4651
+ .join(' ');
4652
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfConfirmDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4653
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.11", type: EfConfirmDialogComponent, isStandalone: true, selector: "ef-confirm-dialog", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `<p-confirmdialog [styleClass]="effectiveStyleClass()" />`, isInline: true, dependencies: [{ kind: "ngmodule", type: ConfirmDialogModule }, { kind: "component", type: i1$8.ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4654
+ }
4655
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfConfirmDialogComponent, decorators: [{
4656
+ type: Component,
4657
+ args: [{
4658
+ selector: 'ef-confirm-dialog',
4659
+ standalone: true,
4660
+ imports: [ConfirmDialogModule],
4661
+ template: `<p-confirmdialog [styleClass]="effectiveStyleClass()" />`,
4662
+ changeDetection: ChangeDetectionStrategy.OnPush,
4663
+ }]
4664
+ }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }] } });
4665
+
4666
+ /**
4667
+ * Light / dark switch.
4668
+ *
4669
+ * All of the machinery already exists in `EfThemeConfigService`: it holds
4670
+ * `darkTheme` in the persisted app state, puts `.p-dark` on `<html>`, and
4671
+ * runs the swap through a view transition where the browser supports one.
4672
+ * This is the control that was missing, so the preference had no way to be
4673
+ * expressed.
4674
+ *
4675
+ * The icon shows the theme you would move to, not the one you are in, which
4676
+ * is what makes a single-button toggle readable: a moon means "go dark".
4677
+ *
4678
+ * ```html
4679
+ * <ef-theme-toggle />
4680
+ * ```
4681
+ */
4682
+ class EfThemeToggleComponent {
4683
+ themeConfig = inject(EfThemeConfigService);
4684
+ /** Icon shown while light is active (i.e. "switch to dark"). */
4685
+ darkIcon = input('pi pi-moon', ...(ngDevMode ? [{ debugName: "darkIcon" }] : /* istanbul ignore next */ []));
4686
+ /** Icon shown while dark is active (i.e. "switch to light"). */
4687
+ lightIcon = input('pi pi-sun', ...(ngDevMode ? [{ debugName: "lightIcon" }] : /* istanbul ignore next */ []));
4688
+ /** Translation key for the accessible name. */
4689
+ ariaLabelKey = input('', ...(ngDevMode ? [{ debugName: "ariaLabelKey" }] : /* istanbul ignore next */ []));
4690
+ isDark = computed(() => !!this.themeConfig.appState()?.darkTheme, ...(ngDevMode ? [{ debugName: "isDark" }] : /* istanbul ignore next */ []));
4691
+ labelKey = computed(() => this.ariaLabelKey() ||
4692
+ (this.isDark() ? 'common_theme_switch_light' : 'common_theme_switch_dark'), ...(ngDevMode ? [{ debugName: "labelKey" }] : /* istanbul ignore next */ []));
4693
+ toggle() {
4694
+ this.themeConfig.appState.update(state => ({ ...state, darkTheme: !state.darkTheme }));
4695
+ }
4696
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfThemeToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4697
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.11", type: EfThemeToggleComponent, isStandalone: true, selector: "ef-theme-toggle", inputs: { darkIcon: { classPropertyName: "darkIcon", publicName: "darkIcon", isSignal: true, isRequired: false, transformFunction: null }, lightIcon: { classPropertyName: "lightIcon", publicName: "lightIcon", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelKey: { classPropertyName: "ariaLabelKey", publicName: "ariaLabelKey", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
4698
+ <button
4699
+ type="button"
4700
+ class="ef-theme-toggle"
4701
+ [class.is-dark]="isDark()"
4702
+ [attr.aria-label]="labelKey() | translate"
4703
+ [attr.title]="labelKey() | translate"
4704
+ [attr.aria-pressed]="isDark()"
4705
+ (click)="toggle()"
4706
+ >
4707
+ <i [class]="isDark() ? lightIcon() : darkIcon()" aria-hidden="true"></i>
4708
+ </button>
4709
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4710
+ }
4711
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfThemeToggleComponent, decorators: [{
4712
+ type: Component,
4713
+ args: [{
4714
+ selector: 'ef-theme-toggle',
4715
+ standalone: true,
4716
+ imports: [TranslateModule],
4717
+ template: `
4718
+ <button
4719
+ type="button"
4720
+ class="ef-theme-toggle"
4721
+ [class.is-dark]="isDark()"
4722
+ [attr.aria-label]="labelKey() | translate"
4723
+ [attr.title]="labelKey() | translate"
4724
+ [attr.aria-pressed]="isDark()"
4725
+ (click)="toggle()"
4726
+ >
4727
+ <i [class]="isDark() ? lightIcon() : darkIcon()" aria-hidden="true"></i>
4728
+ </button>
4729
+ `,
4730
+ changeDetection: ChangeDetectionStrategy.OnPush,
4731
+ }]
4732
+ }], propDecorators: { darkIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "darkIcon", required: false }] }], lightIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "lightIcon", required: false }] }], ariaLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelKey", required: false }] }] } });
4733
+
4734
+ /**
4735
+ * Which build is running, for a footer or an about box.
4736
+ *
4737
+ * Reads `EF_BUILD_INFO` optionally and renders nothing when the app has not
4738
+ * provided it, so a consumer that never wired a build stamp shows no empty
4739
+ * line. The commit and branch go in the tooltip rather than the label: the
4740
+ * date is what a person recognises, the hash is what you paste into an issue.
4741
+ *
4742
+ * ```html
4743
+ * <ef-build-stamp owner="Elasticias" />
4744
+ * ```
4745
+ */
4746
+ class EfBuildStampComponent {
4747
+ /** Copyright holder shown before the build. Omit for the build alone. */
4748
+ owner = input('', ...(ngDevMode ? [{ debugName: "owner" }] : /* istanbul ignore next */ []));
4749
+ info = inject(EF_BUILD_INFO, { optional: true });
4750
+ year = new Date().getFullYear();
4751
+ detail = computed(() => this.info ? `${this.info.commit} · ${this.info.branch} · v${this.info.version}` : '', ...(ngDevMode ? [{ debugName: "detail" }] : /* istanbul ignore next */ []));
4752
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfBuildStampComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4753
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfBuildStampComponent, isStandalone: true, selector: "ef-build-stamp", inputs: { owner: { classPropertyName: "owner", publicName: "owner", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
4754
+ @if (info) {
4755
+ <span class="ef-build-stamp" [attr.title]="detail()">
4756
+ @if (owner()) {
4757
+ <span class="ef-build-stamp__owner">© {{ year }} {{ owner() }}</span>
4758
+ <span class="ef-build-stamp__sep" aria-hidden="true">·</span>
4759
+ }
4760
+ <span class="ef-build-stamp__build">build {{ info.date }}</span>
4761
+ </span>
4762
+ }
4763
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
4764
+ }
4765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfBuildStampComponent, decorators: [{
4766
+ type: Component,
4767
+ args: [{
4768
+ selector: 'ef-build-stamp',
4769
+ standalone: true,
4770
+ template: `
4771
+ @if (info) {
4772
+ <span class="ef-build-stamp" [attr.title]="detail()">
4773
+ @if (owner()) {
4774
+ <span class="ef-build-stamp__owner">© {{ year }} {{ owner() }}</span>
4775
+ <span class="ef-build-stamp__sep" aria-hidden="true">·</span>
4776
+ }
4777
+ <span class="ef-build-stamp__build">build {{ info.date }}</span>
4778
+ </span>
4779
+ }
4780
+ `,
4781
+ changeDetection: ChangeDetectionStrategy.OnPush,
4782
+ }]
4783
+ }], propDecorators: { owner: [{ type: i0.Input, args: [{ isSignal: true, alias: "owner", required: false }] }] } });
4784
+
4785
+ /**
4786
+ * Comptoir-skinned tooltip.
4787
+ *
4788
+ * `ef-button` already drives PrimeNG's tooltip through its `tooltipKey`
4789
+ * input, so this composes the same directive rather than introducing a
4790
+ * second tooltip with its own positioning and its own bugs. It contributes
4791
+ * the `ef-*` name the house style asks for and nothing else; the look comes
4792
+ * from the `.p-tooltip` rules in `_patterns.scss`, which means every tooltip
4793
+ * in the app — this one and `ef-button`'s — reads the same.
4794
+ *
4795
+ * Text is a plain input, so translate at the call site:
4796
+ *
4797
+ * ```html
4798
+ * <span [efTooltip]="'module_sales_hint' | translate" efTooltipPosition="top"></span>
4799
+ * ```
4800
+ */
4801
+ class EfTooltipDirective {
4802
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
4803
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.11", type: EfTooltipDirective, isStandalone: true, selector: "[efTooltip]", hostDirectives: [{ directive: i1$5.Tooltip, inputs: ["pTooltip", "efTooltip", "tooltipPosition", "efTooltipPosition", "tooltipDisabled", "efTooltipDisabled", "tooltipStyleClass", "efTooltipStyleClass", "tooltipEvent", "efTooltipEvent", "showDelay", "efTooltipShowDelay", "hideDelay", "efTooltipHideDelay", "appendTo", "efTooltipAppendTo", "autoHide", "efTooltipAutoHide", "escape", "efTooltipEscape", "life", "efTooltipLife"] }], ngImport: i0 });
4804
+ }
4805
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfTooltipDirective, decorators: [{
4806
+ type: Directive,
4807
+ args: [{
4808
+ selector: '[efTooltip]',
4809
+ standalone: true,
4810
+ hostDirectives: [
4811
+ {
4812
+ directive: Tooltip,
4813
+ inputs: [
4814
+ 'pTooltip: efTooltip',
4815
+ 'tooltipPosition: efTooltipPosition',
4816
+ 'tooltipDisabled: efTooltipDisabled',
4817
+ 'tooltipStyleClass: efTooltipStyleClass',
4818
+ 'tooltipEvent: efTooltipEvent',
4819
+ 'showDelay: efTooltipShowDelay',
4820
+ 'hideDelay: efTooltipHideDelay',
4821
+ 'appendTo: efTooltipAppendTo',
4822
+ 'autoHide: efTooltipAutoHide',
4823
+ 'escape: efTooltipEscape',
4824
+ 'life: efTooltipLife',
4825
+ ],
4826
+ },
4827
+ ],
4828
+ }]
4829
+ }] });
4830
+
4618
4831
  class EfFieldsetComponent {
4619
4832
  /** Direct legend text (not translated) */
4620
4833
  legend;
@@ -4624,7 +4837,7 @@ class EfFieldsetComponent {
4624
4837
  collapsed = false;
4625
4838
  styleClass;
4626
4839
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfFieldsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4627
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.11", type: EfFieldsetComponent, isStandalone: true, selector: "ef-fieldset", inputs: { legend: "legend", legendKey: "legendKey", toggleable: ["toggleable", "toggleable", booleanAttribute], collapsed: ["collapsed", "collapsed", booleanAttribute], styleClass: "styleClass" }, ngImport: i0, template: "<p-fieldset\n [legend]=\"legendKey ? (legendKey | translate) : legend\"\n [toggleable]=\"toggleable\"\n [collapsed]=\"collapsed\"\n [styleClass]=\"styleClass\"\n>\n <ng-content />\n</p-fieldset>\n", dependencies: [{ kind: "ngmodule", type: FieldsetModule }, { kind: "component", type: i1$6.Fieldset, selector: "p-fieldset", inputs: ["legend", "toggleable", "style", "styleClass", "transitionOptions", "motionOptions", "collapsed"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
4840
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.11", type: EfFieldsetComponent, isStandalone: true, selector: "ef-fieldset", inputs: { legend: "legend", legendKey: "legendKey", toggleable: ["toggleable", "toggleable", booleanAttribute], collapsed: ["collapsed", "collapsed", booleanAttribute], styleClass: "styleClass" }, ngImport: i0, template: "<p-fieldset\n [legend]=\"legendKey ? (legendKey | translate) : legend\"\n [toggleable]=\"toggleable\"\n [collapsed]=\"collapsed\"\n [styleClass]=\"styleClass\"\n>\n <ng-content />\n</p-fieldset>\n", dependencies: [{ kind: "ngmodule", type: FieldsetModule }, { kind: "component", type: i1$7.Fieldset, selector: "p-fieldset", inputs: ["legend", "toggleable", "style", "styleClass", "transitionOptions", "motionOptions", "collapsed"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
4628
4841
  }
4629
4842
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfFieldsetComponent, decorators: [{
4630
4843
  type: Component,
@@ -4645,7 +4858,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
4645
4858
 
4646
4859
  class EfButtonGroupComponent {
4647
4860
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfButtonGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4648
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: EfButtonGroupComponent, isStandalone: true, selector: "ef-button-group", ngImport: i0, template: `<p-buttonGroup><ng-content /></p-buttonGroup>`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonGroupModule }, { kind: "component", type: i1$7.ButtonGroup, selector: "p-buttonGroup, p-buttongroup, p-button-group" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4861
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.11", type: EfButtonGroupComponent, isStandalone: true, selector: "ef-button-group", ngImport: i0, template: `<p-buttonGroup><ng-content /></p-buttonGroup>`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonGroupModule }, { kind: "component", type: i1$9.ButtonGroup, selector: "p-buttonGroup, p-buttongroup, p-button-group" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4649
4862
  }
4650
4863
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfButtonGroupComponent, decorators: [{
4651
4864
  type: Component,
@@ -5044,7 +5257,7 @@ class EfToolbarComponent {
5044
5257
  this.router.navigate([baseUrl]);
5045
5258
  }
5046
5259
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5047
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfToolbarComponent, isStandalone: true, selector: "ef-toolbar", inputs: { context: "context", state: "state", disabled: "disabled", backButton: "backButton", deleteButton: "deleteButton", duplicateButton: "duplicateButton", saveButton: "saveButton", exportButton: "exportButton", printButton: "printButton", addButton: "addButton", clearButton: "clearButton", searchButton: "searchButton", showFreeSearchInput: "showFreeSearchInput" }, outputs: { back: "back", save: "save", delete: "delete", duplicate: "duplicate", print: "print", triggerCustoAction: "triggerCustoAction", add: "add", search: "search", clear: "clear" }, ngImport: i0, template: "<p-toolbar>\n <ng-template #start>\n <div class=\"flex items-center gap-3\">\n @if (isDetailState || backButton) {\n <ef-button\n icon=\"pi pi-angle-left\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipKey=\"common.back\"\n labelKey=\"common.back\"\n size=\"small\"\n (clickEvent)=\"backAction()\"\n />\n }\n <!-- Custom content slot for start section (e.g., status badge) -->\n <ng-content select=\"[toolbarStart]\" />\n </div>\n </ng-template>\n <ng-template #center>\n @if (showFreeSearchInput) {\n <p-iconfield iconPosition=\"left\">\n <p-inputicon styleClass=\"pi pi-search\" />\n <input\n id=\"freeTextSearch\"\n type=\"text\"\n pInputText\n [placeholder]=\"'common.search' | translate\"\n />\n </p-iconfield>\n }\n </ng-template>\n <ng-template #end>\n <!-- DETAIL state -->\n <!-- Custom content slot for start section (e.g., status badge) -->\n <ng-content select=\"[toolbarEnd]\" />\n @if (isDetailState && isDuplicateMode) {\n <span\n class=\"duplicate-badge flex items-center gap-1 rounded bg-blue-100 px-2 py-1 text-sm text-blue-700\"\n >\n <i class=\"pi pi-copy\"></i> {{ 'common.duplicate' | translate }}\n </span>\n }\n @if (isDetailState && deleteButton && hasDeletePermission) {\n <ef-button\n icon=\"pi pi-trash\"\n severity=\"danger\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.delete\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"deleteAction()\"\n />\n }\n @if (isDetailState && printButton) {\n <ef-button\n icon=\"pi pi-print\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.print\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"printAction()\"\n />\n }\n @if (\n isDetailState &&\n duplicateButton &&\n hasDuplicatePermission &&\n !isDuplicateMode\n ) {\n <ef-button\n icon=\"pi pi-copy\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"left\"\n tooltipKey=\"common.duplicate\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"duplicateAction()\"\n />\n }\n @if (isDetailState && saveButton && (hasCreatePermission || hasEditPermission)) {\n <ef-button\n icon=\"pi pi-save\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.save\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"saveAction()\"\n />\n }\n <!-- SEARCH state -->\n @if (isSearchState && exportButton && hasExportPermission) {\n <ef-button\n icon=\"pi pi-upload\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.export\"\n size=\"small\"\n (clickEvent)=\"exportAction()\"\n />\n }\n @if (isSearchState && addButton && hasCreatePermission) {\n <ef-button\n icon=\"pi pi-plus\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.add\"\n labelKey=\"common.add\"\n size=\"small\"\n (clickEvent)=\"addAction()\"\n />\n }\n @if (isSearchState && clearButton) {\n <ef-button\n icon=\"pi pi-filter-slash\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.clear_search_criteria\"\n labelKey=\"common.clear\"\n size=\"small\"\n (clickEvent)=\"clearAction()\"\n />\n }\n @if (isSearchState && searchButton && hasReadPermission) {\n <ef-button\n icon=\"pi pi-search\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.search\"\n labelKey=\"common.search\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"searchAction()\"\n />\n }\n </ng-template>\n</p-toolbar>\n", styles: [":host ::ng-deep .p-toolbar{padding:4px!important;border-radius:0;border-left:none;border-right:none;overflow:visible}:host ::ng-deep .p-toolbar-end{flex-wrap:wrap;gap:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i1$8.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "component", type: EfButtonComponent, selector: "ef-button", inputs: ["label", "labelKey", "icon", "variant", "severity", "size", "disabled", "rounded", "outlined", "raised", "text", "loading", "styleClass", "type", "badge", "badgeSeverity", "tooltip", "tooltipKey", "tooltipPosition"], outputs: ["clickEvent"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i7.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i8.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i9.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
5260
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfToolbarComponent, isStandalone: true, selector: "ef-toolbar", inputs: { context: "context", state: "state", disabled: "disabled", backButton: "backButton", deleteButton: "deleteButton", duplicateButton: "duplicateButton", saveButton: "saveButton", exportButton: "exportButton", printButton: "printButton", addButton: "addButton", clearButton: "clearButton", searchButton: "searchButton", showFreeSearchInput: "showFreeSearchInput" }, outputs: { back: "back", save: "save", delete: "delete", duplicate: "duplicate", print: "print", triggerCustoAction: "triggerCustoAction", add: "add", search: "search", clear: "clear" }, ngImport: i0, template: "<p-toolbar>\n <ng-template #start>\n <div class=\"flex items-center gap-3\">\n @if (isDetailState || backButton) {\n <ef-button\n icon=\"pi pi-angle-left\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipKey=\"common.back\"\n labelKey=\"common.back\"\n size=\"small\"\n (clickEvent)=\"backAction()\"\n />\n }\n <!-- Custom content slot for start section (e.g., status badge) -->\n <ng-content select=\"[toolbarStart]\" />\n </div>\n </ng-template>\n <ng-template #center>\n @if (showFreeSearchInput) {\n <p-iconfield iconPosition=\"left\">\n <p-inputicon styleClass=\"pi pi-search\" />\n <input\n id=\"freeTextSearch\"\n type=\"text\"\n pInputText\n [placeholder]=\"'common.search' | translate\"\n />\n </p-iconfield>\n }\n </ng-template>\n <ng-template #end>\n <!-- DETAIL state -->\n <!-- Custom content slot for start section (e.g., status badge) -->\n <ng-content select=\"[toolbarEnd]\" />\n @if (isDetailState && isDuplicateMode) {\n <span\n class=\"duplicate-badge flex items-center gap-1 rounded bg-blue-100 px-2 py-1 text-sm text-blue-700\"\n >\n <i class=\"pi pi-copy\"></i> {{ 'common.duplicate' | translate }}\n </span>\n }\n @if (isDetailState && deleteButton && hasDeletePermission) {\n <ef-button\n icon=\"pi pi-trash\"\n severity=\"danger\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.delete\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"deleteAction()\"\n />\n }\n @if (isDetailState && printButton) {\n <ef-button\n icon=\"pi pi-print\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.print\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"printAction()\"\n />\n }\n @if (\n isDetailState &&\n duplicateButton &&\n hasDuplicatePermission &&\n !isDuplicateMode\n ) {\n <ef-button\n icon=\"pi pi-copy\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"left\"\n tooltipKey=\"common.duplicate\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"duplicateAction()\"\n />\n }\n @if (isDetailState && saveButton && (hasCreatePermission || hasEditPermission)) {\n <ef-button\n icon=\"pi pi-save\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.save\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"saveAction()\"\n />\n }\n <!-- SEARCH state -->\n @if (isSearchState && exportButton && hasExportPermission) {\n <ef-button\n icon=\"pi pi-upload\"\n severity=\"primary\"\n styleClass=\"action-btn\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.export\"\n size=\"small\"\n (clickEvent)=\"exportAction()\"\n />\n }\n @if (isSearchState && addButton && hasCreatePermission) {\n <ef-button\n icon=\"pi pi-plus\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.add\"\n labelKey=\"common.add\"\n size=\"small\"\n (clickEvent)=\"addAction()\"\n />\n }\n @if (isSearchState && clearButton) {\n <ef-button\n icon=\"pi pi-filter-slash\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.clear_search_criteria\"\n labelKey=\"common.clear\"\n size=\"small\"\n (clickEvent)=\"clearAction()\"\n />\n }\n @if (isSearchState && searchButton && hasReadPermission) {\n <ef-button\n icon=\"pi pi-search\"\n severity=\"primary\"\n styleClass=\"action-btn-text\"\n tooltipPosition=\"top\"\n tooltipKey=\"common.search\"\n labelKey=\"common.search\"\n size=\"small\"\n [disabled]=\"disabled\"\n (clickEvent)=\"searchAction()\"\n />\n }\n </ng-template>\n</p-toolbar>\n", styles: [":host ::ng-deep .p-toolbar{padding:4px!important;border-radius:0;border-left:none;border-right:none;overflow:visible}:host ::ng-deep .p-toolbar-end{flex-wrap:wrap;gap:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i1$a.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "component", type: EfButtonComponent, selector: "ef-button", inputs: ["label", "labelKey", "icon", "variant", "severity", "size", "disabled", "rounded", "outlined", "raised", "text", "loading", "styleClass", "type", "badge", "badgeSeverity", "tooltip", "tooltipKey", "tooltipPosition"], outputs: ["clickEvent"] }, { kind: "ngmodule", type: IconFieldModule }, { kind: "component", type: i7.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "ngmodule", type: InputIconModule }, { kind: "component", type: i8.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i9.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
5048
5261
  }
5049
5262
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfToolbarComponent, decorators: [{
5050
5263
  type: Component,
@@ -5155,7 +5368,7 @@ class EfModuleRailComponent {
5155
5368
  return row.kind === 'module' ? `m:${row.module.id}` : `d:${index}`;
5156
5369
  }
5157
5370
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfModuleRailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5158
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfModuleRailComponent, isStandalone: true, selector: "ef-module-rail", inputs: { badges: "badges" }, ngImport: i0, template: "<nav class=\"ef-module-rail\" aria-label=\"Modules\">\n <div class=\"ef-module-rail__logo-slot\">\n <ng-content select=\"[logo]\"></ng-content>\n </div>\n\n @for (row of rows(); track trackRow($index, row)) {\n @if (row.kind === 'divider') {\n <span class=\"ef-module-rail__divider\" aria-hidden=\"true\"></span>\n } @else {\n <button\n type=\"button\"\n class=\"ef-module-rail__btn\"\n [class.is-active]=\"activeId() === row.module.id\"\n [attr.data-module]=\"row.module.id\"\n [attr.aria-current]=\"activeId() === row.module.id ? 'page' : null\"\n [style.--m-color]=\"'var(--' + row.module.accent + ')'\"\n [pTooltip]=\"row.module.labelKey | translate\"\n tooltipPosition=\"right\"\n (click)=\"onSelect(row.module)\"\n >\n <i class=\"ef-module-rail__icon\" [class]=\"row.module.icon\" aria-hidden=\"true\"></i>\n\n @if (badgeFor(row.module.id); as badge) {\n <span class=\"ef-module-rail__badge\">{{ badge }}</span>\n }\n\n <span class=\"ef-module-rail__sr\">{{ row.module.labelKey | translate }}</span>\n </button>\n }\n }\n</nav>\n", styles: ["@charset \"UTF-8\";:host{display:block;flex:0 0 64px;width:64px;background:var(--ink-active);color:var(--paper)}.ef-module-rail{display:flex;flex-direction:column;align-items:center;height:100%;padding:12px 0;gap:4px}.ef-module-rail__logo-slot{display:flex;align-items:center;justify-content:center;min-height:40px;width:40px;margin-bottom:4px}.ef-module-rail__logo-slot:empty{display:none}.ef-module-rail__logo-slot:not(:empty)+.ef-module-rail__divider,.ef-module-rail__logo-slot:has(*)+.ef-module-rail__divider{display:block}.ef-module-rail__divider{height:1px;width:32px;background:#ffffff14;margin:4px 0;flex-shrink:0}.ef-module-rail__btn{position:relative;display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;background:transparent;color:#fff9;border-radius:var(--r-md);cursor:pointer;transition:color var(--t-fast) var(--ease-out),background-color var(--t-fast) var(--ease-out)}.ef-module-rail__btn:hover{color:#fff;background:#ffffff14}.ef-module-rail__btn:focus-visible{outline:2px solid color-mix(in srgb,var(--tenant-300, #b87a99) 80%,transparent);outline-offset:2px}.ef-module-rail__btn.is-active{color:#fff;background:#ffffff1f}.ef-module-rail__btn.is-active:before{content:\"\";position:absolute;inset-inline-end:-10px;top:8px;bottom:8px;width:3px;border-radius:var(--r-sm) 0 0 var(--r-sm);background:var(--m-color, var(--tenant-300, #b87a99))}.ef-module-rail__icon{font-size:20px;line-height:1}.ef-module-rail__badge{position:absolute;top:4px;right:4px;min-width:16px;height:16px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;background:var(--tenant-500);color:#fff;border-radius:var(--r-pill);font-family:JetBrains Mono,ui-monospace,monospace;font-size:10px;font-weight:700;line-height:1}:host-context([dir=rtl]) .ef-module-rail__badge{right:auto;left:4px}.ef-module-rail__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i2$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5371
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfModuleRailComponent, isStandalone: true, selector: "ef-module-rail", inputs: { badges: "badges" }, ngImport: i0, template: "<nav class=\"ef-module-rail\" aria-label=\"Modules\">\n <div class=\"ef-module-rail__logo-slot\">\n <ng-content select=\"[logo]\"></ng-content>\n </div>\n\n @for (row of rows(); track trackRow($index, row)) {\n @if (row.kind === 'divider') {\n <span class=\"ef-module-rail__divider\" aria-hidden=\"true\"></span>\n } @else {\n <button\n type=\"button\"\n class=\"ef-module-rail__btn\"\n [class.is-active]=\"activeId() === row.module.id\"\n [attr.data-module]=\"row.module.id\"\n [attr.aria-current]=\"activeId() === row.module.id ? 'page' : null\"\n [style.--m-color]=\"'var(--' + row.module.accent + ')'\"\n [pTooltip]=\"row.module.labelKey | translate\"\n tooltipPosition=\"right\"\n (click)=\"onSelect(row.module)\"\n >\n <i class=\"ef-module-rail__icon\" [class]=\"row.module.icon\" aria-hidden=\"true\"></i>\n\n @if (badgeFor(row.module.id); as badge) {\n <span class=\"ef-module-rail__badge\">{{ badge }}</span>\n }\n\n <span class=\"ef-module-rail__sr\">{{ row.module.labelKey | translate }}</span>\n </button>\n }\n }\n</nav>\n", styles: ["@charset \"UTF-8\";:host{display:block;flex:0 0 64px;width:64px;background:var(--ink-active);color:var(--paper)}.ef-module-rail{display:flex;flex-direction:column;align-items:center;height:100%;padding:12px 0;gap:4px}.ef-module-rail__logo-slot{display:flex;align-items:center;justify-content:center;min-height:40px;width:40px;margin-bottom:4px}.ef-module-rail__logo-slot:empty{display:none}.ef-module-rail__logo-slot:not(:empty)+.ef-module-rail__divider,.ef-module-rail__logo-slot:has(*)+.ef-module-rail__divider{display:block}.ef-module-rail__divider{height:1px;width:32px;background:#ffffff14;margin:4px 0;flex-shrink:0}.ef-module-rail__btn{position:relative;display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;background:transparent;color:#fff9;border-radius:var(--r-md);cursor:pointer;transition:color var(--t-fast) var(--ease-out),background-color var(--t-fast) var(--ease-out)}.ef-module-rail__btn:hover{color:#fff;background:#ffffff14}.ef-module-rail__btn:focus-visible{outline:2px solid color-mix(in srgb,var(--tenant-300, #b87a99) 80%,transparent);outline-offset:2px}.ef-module-rail__btn.is-active{color:#fff;background:#ffffff1f}.ef-module-rail__btn.is-active:before{content:\"\";position:absolute;inset-inline-end:-10px;top:8px;bottom:8px;width:3px;border-radius:var(--r-sm) 0 0 var(--r-sm);background:var(--m-color, var(--tenant-300, #b87a99))}.ef-module-rail__icon{font-size:20px;line-height:1}.ef-module-rail__badge{position:absolute;top:4px;right:4px;min-width:16px;height:16px;padding:0 4px;display:inline-flex;align-items:center;justify-content:center;background:var(--tenant-500);color:#fff;border-radius:var(--r-pill);font-family:JetBrains Mono,ui-monospace,monospace;font-size:10px;font-weight:700;line-height:1}:host-context([dir=rtl]) .ef-module-rail__badge{right:auto;left:4px}.ef-module-rail__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5159
5372
  }
5160
5373
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfModuleRailComponent, decorators: [{
5161
5374
  type: Component,
@@ -5218,17 +5431,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
5218
5431
  * breadcrumb can still project their own content into `[breadcrumb]`.
5219
5432
  */
5220
5433
  class EfAppTopComponent {
5434
+ /**
5435
+ * Show the light/dark switch at the trailing edge of the bar.
5436
+ *
5437
+ * It lives here rather than being projected through `[actions]`
5438
+ * because that slot is declared once per viewport branch in
5439
+ * `ef-app-shell` and only the mobile one receives content — so
5440
+ * anything an app projects there never appears on desktop.
5441
+ */
5442
+ themeToggle = input(true, { ...(ngDevMode ? { debugName: "themeToggle" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5443
+ /**
5444
+ * Show the sign-out button. It only renders when the app has provided
5445
+ * `EF_SESSION`, so this input turns off a control the app opted into
5446
+ * rather than being the thing that enables it.
5447
+ */
5448
+ logout = input(true, { ...(ngDevMode ? { debugName: "logout" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
5449
+ /** Present only when the app provides `EF_SESSION`. */
5450
+ session = inject(EF_SESSION, { optional: true });
5451
+ signOut() {
5452
+ this.session?.logout();
5453
+ }
5221
5454
  active = inject(EfActiveModuleService);
5222
5455
  module = this.active.activeModule;
5223
5456
  navItem = this.active.activeNavItem;
5224
5457
  hasBreadcrumb = computed(() => this.module() != null, ...(ngDevMode ? [{ debugName: "hasBreadcrumb" }] : /* istanbul ignore next */ []));
5225
5458
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppTopComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5226
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppTopComponent, isStandalone: true, selector: "ef-app-top", ngImport: i0, template: "<div class=\"ef-app-top__slot ef-app-top__slot--breadcrumb\">\n <ng-content select=\"[breadcrumb]\"></ng-content>\n @if (hasBreadcrumb()) {\n <nav class=\"ef-app-top__crumb\" aria-label=\"breadcrumb\">\n <span class=\"ef-app-top__crumb-dot\" [attr.data-module]=\"module()!.id\" aria-hidden=\"true\"></span>\n <span class=\"ef-app-top__crumb-root\">{{ module()!.labelKey | translate }}</span>\n @if (navItem(); as item) {\n <span class=\"ef-app-top__crumb-sep\" aria-hidden=\"true\">/</span>\n <span class=\"ef-app-top__crumb-leaf\">{{ item.labelKey | translate }}</span>\n }\n </nav>\n }\n</div>\n\n<div class=\"ef-app-top__slot ef-app-top__slot--actions\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr);align-items:center;gap:16px;flex:0 0 auto;height:48px;padding:0 20px;background:var(--paper-alt);border-bottom:1px solid var(--rule);color:var(--text)}.ef-app-top__slot{display:flex;align-items:center;gap:8px;min-width:0}.ef-app-top__slot--actions{justify-content:flex-end;gap:12px}.ef-app-top__crumb{display:inline-flex;align-items:center;gap:8px;font-family:Manrope,system-ui,sans-serif;font-size:13px;letter-spacing:.01em;line-height:1;color:var(--text-mute)}.ef-app-top__crumb-dot{width:8px;height:8px;border-radius:999px;background:var(--m-admin);flex-shrink:0}.ef-app-top__crumb-dot[data-module=sales]{background:var(--m-sales)}.ef-app-top__crumb-dot[data-module=purchase]{background:var(--m-purchase)}.ef-app-top__crumb-dot[data-module=stock]{background:var(--m-stock)}.ef-app-top__crumb-dot[data-module=pos]{background:var(--m-pos)}.ef-app-top__crumb-dot[data-module=marketing]{background:var(--m-marketing)}.ef-app-top__crumb-dot[data-module=store]{background:var(--m-store)}.ef-app-top__crumb-dot[data-module=finance]{background:var(--m-finance)}.ef-app-top__crumb-dot[data-module=admin]{background:var(--m-admin)}.ef-app-top__crumb-root{font-weight:600;color:var(--text)}.ef-app-top__crumb-sep{color:var(--text-soft)}.ef-app-top__crumb-leaf{color:var(--text-mute)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5459
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppTopComponent, isStandalone: true, selector: "ef-app-top", inputs: { themeToggle: { classPropertyName: "themeToggle", publicName: "themeToggle", isSignal: true, isRequired: false, transformFunction: null }, logout: { classPropertyName: "logout", publicName: "logout", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"ef-app-top__slot ef-app-top__slot--breadcrumb\">\n <ng-content select=\"[breadcrumb]\"></ng-content>\n @if (hasBreadcrumb()) {\n <nav class=\"ef-app-top__crumb\" aria-label=\"breadcrumb\">\n <span class=\"ef-app-top__crumb-dot\" [attr.data-module]=\"module()!.id\" aria-hidden=\"true\"></span>\n <span class=\"ef-app-top__crumb-root\">{{ module()!.labelKey | translate }}</span>\n @if (navItem(); as item) {\n <span class=\"ef-app-top__crumb-sep\" aria-hidden=\"true\">/</span>\n <span class=\"ef-app-top__crumb-leaf\">{{ item.labelKey | translate }}</span>\n }\n </nav>\n }\n</div>\n\n<div class=\"ef-app-top__slot ef-app-top__slot--actions\">\n <ng-content select=\"[actions]\"></ng-content>\n @if (themeToggle()) {\n <ef-theme-toggle />\n }\n @if (logout() && session) {\n <button\n type=\"button\"\n class=\"ef-app-top__logout\"\n [attr.aria-label]=\"'common_logout' | translate\"\n [attr.title]=\"'common_logout' | translate\"\n (click)=\"signOut()\"\n >\n <i class=\"pi pi-sign-out\" aria-hidden=\"true\"></i>\n </button>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr);align-items:center;gap:16px;flex:0 0 auto;height:48px;padding:0 20px;background:var(--paper-alt);border-bottom:1px solid var(--rule);color:var(--text)}.ef-app-top__slot{display:flex;align-items:center;gap:8px;min-width:0}.ef-app-top__slot--actions{justify-content:flex-end;gap:12px}.ef-app-top__crumb{display:inline-flex;align-items:center;gap:8px;font-family:Manrope,system-ui,sans-serif;font-size:13px;letter-spacing:.01em;line-height:1;color:var(--text-mute)}.ef-app-top__crumb-dot{width:8px;height:8px;border-radius:999px;background:var(--m-admin);flex-shrink:0}.ef-app-top__crumb-dot[data-module=sales]{background:var(--m-sales)}.ef-app-top__crumb-dot[data-module=purchase]{background:var(--m-purchase)}.ef-app-top__crumb-dot[data-module=stock]{background:var(--m-stock)}.ef-app-top__crumb-dot[data-module=pos]{background:var(--m-pos)}.ef-app-top__crumb-dot[data-module=marketing]{background:var(--m-marketing)}.ef-app-top__crumb-dot[data-module=store]{background:var(--m-store)}.ef-app-top__crumb-dot[data-module=finance]{background:var(--m-finance)}.ef-app-top__crumb-dot[data-module=admin]{background:var(--m-admin)}.ef-app-top__crumb-root{font-weight:600;color:var(--text)}.ef-app-top__crumb-sep{color:var(--text-soft)}.ef-app-top__crumb-leaf{color:var(--text-mute)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfThemeToggleComponent, selector: "ef-theme-toggle", inputs: ["darkIcon", "lightIcon", "ariaLabelKey"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5227
5460
  }
5228
5461
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppTopComponent, decorators: [{
5229
5462
  type: Component,
5230
- args: [{ selector: 'ef-app-top', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, TranslateModule], template: "<div class=\"ef-app-top__slot ef-app-top__slot--breadcrumb\">\n <ng-content select=\"[breadcrumb]\"></ng-content>\n @if (hasBreadcrumb()) {\n <nav class=\"ef-app-top__crumb\" aria-label=\"breadcrumb\">\n <span class=\"ef-app-top__crumb-dot\" [attr.data-module]=\"module()!.id\" aria-hidden=\"true\"></span>\n <span class=\"ef-app-top__crumb-root\">{{ module()!.labelKey | translate }}</span>\n @if (navItem(); as item) {\n <span class=\"ef-app-top__crumb-sep\" aria-hidden=\"true\">/</span>\n <span class=\"ef-app-top__crumb-leaf\">{{ item.labelKey | translate }}</span>\n }\n </nav>\n }\n</div>\n\n<div class=\"ef-app-top__slot ef-app-top__slot--actions\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr);align-items:center;gap:16px;flex:0 0 auto;height:48px;padding:0 20px;background:var(--paper-alt);border-bottom:1px solid var(--rule);color:var(--text)}.ef-app-top__slot{display:flex;align-items:center;gap:8px;min-width:0}.ef-app-top__slot--actions{justify-content:flex-end;gap:12px}.ef-app-top__crumb{display:inline-flex;align-items:center;gap:8px;font-family:Manrope,system-ui,sans-serif;font-size:13px;letter-spacing:.01em;line-height:1;color:var(--text-mute)}.ef-app-top__crumb-dot{width:8px;height:8px;border-radius:999px;background:var(--m-admin);flex-shrink:0}.ef-app-top__crumb-dot[data-module=sales]{background:var(--m-sales)}.ef-app-top__crumb-dot[data-module=purchase]{background:var(--m-purchase)}.ef-app-top__crumb-dot[data-module=stock]{background:var(--m-stock)}.ef-app-top__crumb-dot[data-module=pos]{background:var(--m-pos)}.ef-app-top__crumb-dot[data-module=marketing]{background:var(--m-marketing)}.ef-app-top__crumb-dot[data-module=store]{background:var(--m-store)}.ef-app-top__crumb-dot[data-module=finance]{background:var(--m-finance)}.ef-app-top__crumb-dot[data-module=admin]{background:var(--m-admin)}.ef-app-top__crumb-root{font-weight:600;color:var(--text)}.ef-app-top__crumb-sep{color:var(--text-soft)}.ef-app-top__crumb-leaf{color:var(--text-mute)}\n"] }]
5231
- }] });
5463
+ args: [{ selector: 'ef-app-top', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, TranslateModule, EfThemeToggleComponent], template: "<div class=\"ef-app-top__slot ef-app-top__slot--breadcrumb\">\n <ng-content select=\"[breadcrumb]\"></ng-content>\n @if (hasBreadcrumb()) {\n <nav class=\"ef-app-top__crumb\" aria-label=\"breadcrumb\">\n <span class=\"ef-app-top__crumb-dot\" [attr.data-module]=\"module()!.id\" aria-hidden=\"true\"></span>\n <span class=\"ef-app-top__crumb-root\">{{ module()!.labelKey | translate }}</span>\n @if (navItem(); as item) {\n <span class=\"ef-app-top__crumb-sep\" aria-hidden=\"true\">/</span>\n <span class=\"ef-app-top__crumb-leaf\">{{ item.labelKey | translate }}</span>\n }\n </nav>\n }\n</div>\n\n<div class=\"ef-app-top__slot ef-app-top__slot--actions\">\n <ng-content select=\"[actions]\"></ng-content>\n @if (themeToggle()) {\n <ef-theme-toggle />\n }\n @if (logout() && session) {\n <button\n type=\"button\"\n class=\"ef-app-top__logout\"\n [attr.aria-label]=\"'common_logout' | translate\"\n [attr.title]=\"'common_logout' | translate\"\n (click)=\"signOut()\"\n >\n <i class=\"pi pi-sign-out\" aria-hidden=\"true\"></i>\n </button>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:grid;grid-template-columns:minmax(0,auto) minmax(0,1fr);align-items:center;gap:16px;flex:0 0 auto;height:48px;padding:0 20px;background:var(--paper-alt);border-bottom:1px solid var(--rule);color:var(--text)}.ef-app-top__slot{display:flex;align-items:center;gap:8px;min-width:0}.ef-app-top__slot--actions{justify-content:flex-end;gap:12px}.ef-app-top__crumb{display:inline-flex;align-items:center;gap:8px;font-family:Manrope,system-ui,sans-serif;font-size:13px;letter-spacing:.01em;line-height:1;color:var(--text-mute)}.ef-app-top__crumb-dot{width:8px;height:8px;border-radius:999px;background:var(--m-admin);flex-shrink:0}.ef-app-top__crumb-dot[data-module=sales]{background:var(--m-sales)}.ef-app-top__crumb-dot[data-module=purchase]{background:var(--m-purchase)}.ef-app-top__crumb-dot[data-module=stock]{background:var(--m-stock)}.ef-app-top__crumb-dot[data-module=pos]{background:var(--m-pos)}.ef-app-top__crumb-dot[data-module=marketing]{background:var(--m-marketing)}.ef-app-top__crumb-dot[data-module=store]{background:var(--m-store)}.ef-app-top__crumb-dot[data-module=finance]{background:var(--m-finance)}.ef-app-top__crumb-dot[data-module=admin]{background:var(--m-admin)}.ef-app-top__crumb-root{font-weight:600;color:var(--text)}.ef-app-top__crumb-sep{color:var(--text-soft)}.ef-app-top__crumb-leaf{color:var(--text-mute)}\n"] }]
5464
+ }], propDecorators: { themeToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "themeToggle", required: false }] }], logout: [{ type: i0.Input, args: [{ isSignal: true, alias: "logout", required: false }] }] } });
5232
5465
 
5233
5466
  /**
5234
5467
  * Content scroll container. Lives at the right of the rail+side
@@ -5347,7 +5580,7 @@ class EfAppShellMobileComponent {
5347
5580
  this.switcherOpen.set(false);
5348
5581
  }
5349
5582
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppShellMobileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5350
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppShellMobileComponent, isStandalone: true, selector: "ef-app-shell-mobile", ngImport: i0, template: "<ef-app-top>\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <button\n actions\n type=\"button\"\n class=\"ef-app-shell-mobile__menu\"\n (click)=\"openSwitcher()\"\n aria-label=\"Modules\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n <ng-content select=\"[actions]\" actions></ng-content>\n</ef-app-top>\n\n<ef-app-main [stripe]=\"true\">\n <ng-content></ng-content>\n</ef-app-main>\n\n<nav class=\"ef-app-shell-mobile__tabs\" aria-label=\"Modules\">\n @for (module of tabs(); track module.id) {\n <button\n type=\"button\"\n class=\"ef-app-shell-mobile__tab\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n [attr.aria-current]=\"activeId() === module.id ? 'page' : null\"\n (click)=\"onSelect(module)\"\n >\n <i class=\"ef-app-shell-mobile__tab-icon\" [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span class=\"ef-app-shell-mobile__tab-label\">{{ module.labelKey | translate }}</span>\n </button>\n }\n</nav>\n\n<ng-content select=\"[fab]\"></ng-content>\n\n<ef-bottom-sheet [open]=\"switcherOpen()\" (openChange)=\"onSwitcherChange($event)\">\n <h2 class=\"ef-app-shell-mobile__sheet-title\">{{ 'modules.all' | translate }}</h2>\n <ul class=\"ef-app-shell-mobile__sheet-list\">\n @for (module of allVisible(); track module.id) {\n <li>\n <button\n type=\"button\"\n class=\"ef-app-shell-mobile__sheet-item\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n (click)=\"onSelect(module)\"\n >\n <i [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span>{{ module.labelKey | translate }}</span>\n </button>\n </li>\n }\n </ul>\n</ef-bottom-sheet>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell-mobile__menu{display:inline-flex;align-items:center;justify-content:center;width:var(--hit-touch);height:var(--hit-touch);background:transparent;border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-size:18px}.ef-app-shell-mobile__menu:hover{background:var(--paper-alt)}.ef-app-shell-mobile__tabs{flex:0 0 auto;display:flex;align-items:stretch;height:64px;padding-bottom:env(safe-area-inset-bottom);background:var(--paper);border-top:1px solid var(--rule)}.ef-app-shell-mobile__tab{position:relative;flex:1 1 0;min-width:0;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;background:transparent;border:0;color:var(--text-mute);cursor:pointer;padding:6px 4px;transition:color var(--t-fast) var(--ease-out)}.ef-app-shell-mobile__tab.is-active{color:var(--text)}.ef-app-shell-mobile__tab.is-active:after{content:\"\";position:absolute;top:0;left:50%;transform:translate(-50%);width:28px;height:3px;background:var(--module);border-radius:0 0 var(--r-sm) var(--r-sm)}.ef-app-shell-mobile__tab-icon{font-size:18px;line-height:1}.ef-app-shell-mobile__tab-label{font-family:Manrope,system-ui,sans-serif;font-size:10.5px;font-weight:600;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.ef-app-shell-mobile__sheet-title{font-family:Bricolage Grotesque,system-ui,sans-serif;font-variation-settings:\"opsz\" 96,\"wght\" 600,\"wdth\" 95;font-size:22px;letter-spacing:-.025em;margin:0 0 12px;color:var(--text)}.ef-app-shell-mobile__sheet-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:8px}.ef-app-shell-mobile__sheet-item{display:flex;align-items:center;gap:12px;width:100%;height:var(--hit-touch);padding:0 16px;background:var(--paper-alt);border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-family:Manrope,system-ui,sans-serif;font-size:14px;font-weight:500;text-align:left;transition:background-color var(--t-fast) var(--ease-out)}.ef-app-shell-mobile__sheet-item:hover{background:var(--rule)}.ef-app-shell-mobile__sheet-item.is-active{border-left:3px solid var(--module);padding-left:13px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "component", type: EfAppTopComponent, selector: "ef-app-top" }, { kind: "component", type: EfAppMainComponent, selector: "ef-app-main", inputs: ["stripe"] }, { kind: "component", type: EfBottomSheetComponent, selector: "ef-bottom-sheet", inputs: ["open", "dismissOnBackdrop"], outputs: ["openChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5583
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppShellMobileComponent, isStandalone: true, selector: "ef-app-shell-mobile", ngImport: i0, template: "<ef-app-top>\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <button\n actions\n type=\"button\"\n class=\"ef-app-shell-mobile__menu\"\n (click)=\"openSwitcher()\"\n aria-label=\"Modules\"\n >\n <i class=\"pi pi-bars\" aria-hidden=\"true\"></i>\n </button>\n <ng-content select=\"[actions]\" actions></ng-content>\n</ef-app-top>\n\n<ef-app-main [stripe]=\"true\">\n <ng-content></ng-content>\n</ef-app-main>\n\n<nav class=\"ef-app-shell-mobile__tabs\" aria-label=\"Modules\">\n @for (module of tabs(); track module.id) {\n <button\n type=\"button\"\n class=\"ef-app-shell-mobile__tab\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n [attr.aria-current]=\"activeId() === module.id ? 'page' : null\"\n (click)=\"onSelect(module)\"\n >\n <i class=\"ef-app-shell-mobile__tab-icon\" [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span class=\"ef-app-shell-mobile__tab-label\">{{ module.labelKey | translate }}</span>\n </button>\n }\n</nav>\n\n<ng-content select=\"[fab]\"></ng-content>\n\n<ef-bottom-sheet [open]=\"switcherOpen()\" (openChange)=\"onSwitcherChange($event)\">\n <h2 class=\"ef-app-shell-mobile__sheet-title\">{{ 'modules.all' | translate }}</h2>\n <ul class=\"ef-app-shell-mobile__sheet-list\">\n @for (module of allVisible(); track module.id) {\n <li>\n <button\n type=\"button\"\n class=\"ef-app-shell-mobile__sheet-item\"\n [class.is-active]=\"activeId() === module.id\"\n [attr.data-module]=\"module.id\"\n (click)=\"onSelect(module)\"\n >\n <i [class]=\"module.icon\" aria-hidden=\"true\"></i>\n <span>{{ module.labelKey | translate }}</span>\n </button>\n </li>\n }\n </ul>\n</ef-bottom-sheet>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell-mobile__menu{display:inline-flex;align-items:center;justify-content:center;width:var(--hit-touch);height:var(--hit-touch);background:transparent;border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-size:18px}.ef-app-shell-mobile__menu:hover{background:var(--paper-alt)}.ef-app-shell-mobile__tabs{flex:0 0 auto;display:flex;align-items:stretch;height:64px;padding-bottom:env(safe-area-inset-bottom);background:var(--paper);border-top:1px solid var(--rule)}.ef-app-shell-mobile__tab{position:relative;flex:1 1 0;min-width:0;display:inline-flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;background:transparent;border:0;color:var(--text-mute);cursor:pointer;padding:6px 4px;transition:color var(--t-fast) var(--ease-out)}.ef-app-shell-mobile__tab.is-active{color:var(--text)}.ef-app-shell-mobile__tab.is-active:after{content:\"\";position:absolute;top:0;left:50%;transform:translate(-50%);width:28px;height:3px;background:var(--module);border-radius:0 0 var(--r-sm) var(--r-sm)}.ef-app-shell-mobile__tab-icon{font-size:18px;line-height:1}.ef-app-shell-mobile__tab-label{font-family:Manrope,system-ui,sans-serif;font-size:10.5px;font-weight:600;letter-spacing:-.005em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.ef-app-shell-mobile__sheet-title{font-family:Bricolage Grotesque,system-ui,sans-serif;font-variation-settings:\"opsz\" 96,\"wght\" 600,\"wdth\" 95;font-size:22px;letter-spacing:-.025em;margin:0 0 12px;color:var(--text)}.ef-app-shell-mobile__sheet-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:8px}.ef-app-shell-mobile__sheet-item{display:flex;align-items:center;gap:12px;width:100%;height:var(--hit-touch);padding:0 16px;background:var(--paper-alt);border:0;border-radius:var(--r-md);color:var(--text);cursor:pointer;font-family:Manrope,system-ui,sans-serif;font-size:14px;font-weight:500;text-align:left;transition:background-color var(--t-fast) var(--ease-out)}.ef-app-shell-mobile__sheet-item:hover{background:var(--rule)}.ef-app-shell-mobile__sheet-item.is-active{border-left:3px solid var(--module);padding-left:13px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "component", type: EfAppTopComponent, selector: "ef-app-top", inputs: ["themeToggle", "logout"] }, { kind: "component", type: EfAppMainComponent, selector: "ef-app-main", inputs: ["stripe"] }, { kind: "component", type: EfBottomSheetComponent, selector: "ef-bottom-sheet", inputs: ["open", "dismissOnBackdrop"], outputs: ["openChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5351
5584
  }
5352
5585
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppShellMobileComponent, decorators: [{
5353
5586
  type: Component,
@@ -5397,7 +5630,7 @@ class EfAppShellComponent {
5397
5630
  isMobile = this.vp.isMobile;
5398
5631
  showSide = computed(() => !this.vp.isMobile(), ...(ngDevMode ? [{ debugName: "showSide" }] : /* istanbul ignore next */ []));
5399
5632
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5400
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppShellComponent, isStandalone: true, selector: "ef-app-shell", inputs: { stripe: "stripe" }, host: { properties: { "attr.data-viewport": "viewport()" } }, ngImport: i0, template: "@if (isMobile()) {\n <ef-app-shell-mobile>\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n <ng-content select=\"[fab]\" fab></ng-content>\n <ng-content></ng-content>\n </ef-app-shell-mobile>\n} @else {\n <ef-module-rail>\n <ng-content select=\"[logo]\" logo></ng-content>\n </ef-module-rail>\n @if (showSide()) {\n <ef-module-side>\n <ng-content select=\"[side-header-meta]\" side-header-meta></ng-content>\n <ng-content select=\"[side-footer]\" side-footer></ng-content>\n </ef-module-side>\n }\n <div class=\"ef-app-shell__column\">\n <ef-app-top>\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n </ef-app-top>\n <ef-app-main [stripe]=\"stripe\">\n <ng-content></ng-content>\n </ef-app-main>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:row;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell__column{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EfModuleRailComponent, selector: "ef-module-rail", inputs: ["badges"] }, { kind: "component", type: EfModuleSideComponent, selector: "ef-module-side" }, { kind: "component", type: EfAppTopComponent, selector: "ef-app-top" }, { kind: "component", type: EfAppMainComponent, selector: "ef-app-main", inputs: ["stripe"] }, { kind: "component", type: EfAppShellMobileComponent, selector: "ef-app-shell-mobile" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5633
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfAppShellComponent, isStandalone: true, selector: "ef-app-shell", inputs: { stripe: "stripe" }, host: { properties: { "attr.data-viewport": "viewport()" } }, ngImport: i0, template: "@if (isMobile()) {\n <ef-app-shell-mobile>\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[search]\" search></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n <ng-content select=\"[fab]\" fab></ng-content>\n <ng-content></ng-content>\n </ef-app-shell-mobile>\n} @else {\n <ef-module-rail>\n <ng-content select=\"[logo]\" logo></ng-content>\n </ef-module-rail>\n @if (showSide()) {\n <ef-module-side>\n <ng-content select=\"[side-header-meta]\" side-header-meta></ng-content>\n <ng-content select=\"[side-footer]\" side-footer></ng-content>\n </ef-module-side>\n }\n <div class=\"ef-app-shell__column\">\n <ef-app-top>\n <ng-content select=\"[breadcrumb]\" breadcrumb></ng-content>\n <ng-content select=\"[actions]\" actions></ng-content>\n </ef-app-top>\n <ef-app-main [stripe]=\"stripe\">\n <ng-content></ng-content>\n </ef-app-main>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:row;width:100%;height:100vh;background:var(--paper);color:var(--text);overflow:hidden}.ef-app-shell__column{display:flex;flex-direction:column;flex:1 1 auto;min-width:0;min-height:0;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EfModuleRailComponent, selector: "ef-module-rail", inputs: ["badges"] }, { kind: "component", type: EfModuleSideComponent, selector: "ef-module-side" }, { kind: "component", type: EfAppTopComponent, selector: "ef-app-top", inputs: ["themeToggle", "logout"] }, { kind: "component", type: EfAppMainComponent, selector: "ef-app-main", inputs: ["stripe"] }, { kind: "component", type: EfAppShellMobileComponent, selector: "ef-app-shell-mobile" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5401
5634
  }
5402
5635
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfAppShellComponent, decorators: [{
5403
5636
  type: Component,
@@ -5807,7 +6040,7 @@ class EfBlockUiComponent {
5807
6040
  isLoading = false;
5808
6041
  contentPanel;
5809
6042
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfBlockUiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5810
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfBlockUiComponent, isStandalone: true, selector: "ef-block-ui", inputs: { isLoading: "isLoading", contentPanel: "contentPanel" }, ngImport: i0, template: "@if (isLoading) {\n <p-blockUI\n [target]=\"contentPanel\"\n [blocked]=\"isLoading\"\n styleClass=\"appBlockUI w-full h-full fixed top-0 left-0 right-0 flex items-start justify-center bg-black/30 z-20\">\n\n <ng-template pTemplate=\"loader\">\n <!-- Loader Container -->\n <div class=\"mt-2 flex flex-row items-center space-x-4 rounded-lg bg-white px-4 py-2 shadow\">\n <!-- Spinning Loader -->\n <div class=\"h-6 w-6 animate-spin rounded-full border-2 border-primary border-t-transparent dark:border-primary-contrast dark:border-t-transparent\"></div>\n\n <!-- Loading Text -->\n <div id=\"loading-text\" class=\"font-normal text-primary dark:text-primary-contrast\">\n Chargement en cours... !\n </div>\n </div>\n </ng-template>\n </p-blockUI>\n}\n", styles: [":host ::ng-deep .p-overlay-mask{background:#13111126!important}:host ::ng-deep .p-blockui-mask{border-radius:none!important}\n"], dependencies: [{ kind: "ngmodule", type: BlockUIModule }, { kind: "component", type: i1$9.BlockUI, selector: "p-blockUI, p-blockui, p-block-ui", inputs: ["target", "autoZIndex", "baseZIndex", "styleClass", "blocked"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }] });
6043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfBlockUiComponent, isStandalone: true, selector: "ef-block-ui", inputs: { isLoading: "isLoading", contentPanel: "contentPanel" }, ngImport: i0, template: "@if (isLoading) {\n <p-blockUI\n [target]=\"contentPanel\"\n [blocked]=\"isLoading\"\n styleClass=\"appBlockUI w-full h-full fixed top-0 left-0 right-0 flex items-start justify-center bg-black/30 z-20\">\n\n <ng-template pTemplate=\"loader\">\n <!-- Loader Container -->\n <div class=\"mt-2 flex flex-row items-center space-x-4 rounded-lg bg-white px-4 py-2 shadow\">\n <!-- Spinning Loader -->\n <div class=\"h-6 w-6 animate-spin rounded-full border-2 border-primary border-t-transparent dark:border-primary-contrast dark:border-t-transparent\"></div>\n\n <!-- Loading Text -->\n <div id=\"loading-text\" class=\"font-normal text-primary dark:text-primary-contrast\">\n Chargement en cours... !\n </div>\n </div>\n </ng-template>\n </p-blockUI>\n}\n", styles: [":host ::ng-deep .p-overlay-mask{background:#13111126!important}:host ::ng-deep .p-blockui-mask{border-radius:none!important}\n"], dependencies: [{ kind: "ngmodule", type: BlockUIModule }, { kind: "component", type: i1$b.BlockUI, selector: "p-blockUI, p-blockui, p-block-ui", inputs: ["target", "autoZIndex", "baseZIndex", "styleClass", "blocked"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }] });
5811
6044
  }
5812
6045
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfBlockUiComponent, decorators: [{
5813
6046
  type: Component,
@@ -7019,7 +7252,7 @@ moduleColor) {
7019
7252
  };
7020
7253
  }
7021
7254
 
7022
- Chart.register(ArcElement, BarController, BarElement, CategoryScale, DoughnutController, Filler, Legend, LineController, LineElement, LinearScale, PointElement, Tooltip);
7255
+ Chart.register(ArcElement, BarController, BarElement, CategoryScale, DoughnutController, Filler, Legend, LineController, LineElement, LinearScale, PointElement, Tooltip$1);
7023
7256
  /**
7024
7257
  * Thin chart.js wrapper for report/dashboard visuals (line, bar, donut).
7025
7258
  * Labels/series are data — i18n happens in the parent. Zoneless-safe: the
@@ -7403,7 +7636,7 @@ class EfToggleSwitchComponent extends AbstractEfFormControl {
7403
7636
  styleClass="form-label-left cursor-pointer"
7404
7637
  />
7405
7638
  }
7406
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i1$a.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }] });
7639
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i1$c.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }] });
7407
7640
  }
7408
7641
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfToggleSwitchComponent, decorators: [{
7409
7642
  type: Component,
@@ -7517,7 +7750,7 @@ class EfDatepickerComponent {
7517
7750
  this.onTouched();
7518
7751
  }
7519
7752
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7520
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDatepickerComponent, isStandalone: true, selector: "ef-datepicker", inputs: { label: "label", labelKey: "labelKey", inputId: "inputId", name: "name", placeholder: "placeholder", placeholderKey: "placeholderKey", size: "size", required: ["required", "required", booleanAttribute], fluid: ["fluid", "fluid", booleanAttribute], inline: ["inline", "inline", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], showIcon: ["showIcon", "showIcon", booleanAttribute], iconDisplay: "iconDisplay", selectionMode: "selectionMode", dateFormat: "dateFormat", appendTo: "appendTo", showTime: ["showTime", "showTime", booleanAttribute], showButtonBar: ["showButtonBar", "showButtonBar", booleanAttribute], minDate: "minDate", maxDate: "maxDate" }, outputs: { dateSelectEvent: "dateSelectEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, ngImport: i0, template: "@if (labelKey || label) {\n <ef-label [labelKey]=\"labelKey\" [label]=\"label\" [for]=\"effectiveId\" [required]=\"required\" />\n}\n<div class=\"ef-field-control\">\n <p-datepicker\n [inputId]=\"effectiveId\"\n [name]=\"name\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"disabled\"\n [showIcon]=\"showIcon\"\n [iconDisplay]=\"iconDisplay\"\n [selectionMode]=\"selectionMode\"\n [dateFormat]=\"dateFormat\"\n [appendTo]=\"appendTo\"\n [showTime]=\"showTime\"\n [showButtonBar]=\"showButtonBar\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [fluid]=\"fluid\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n />\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i1$b.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
7753
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDatepickerComponent, isStandalone: true, selector: "ef-datepicker", inputs: { label: "label", labelKey: "labelKey", inputId: "inputId", name: "name", placeholder: "placeholder", placeholderKey: "placeholderKey", size: "size", required: ["required", "required", booleanAttribute], fluid: ["fluid", "fluid", booleanAttribute], inline: ["inline", "inline", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], showIcon: ["showIcon", "showIcon", booleanAttribute], iconDisplay: "iconDisplay", selectionMode: "selectionMode", dateFormat: "dateFormat", appendTo: "appendTo", showTime: ["showTime", "showTime", booleanAttribute], showButtonBar: ["showButtonBar", "showButtonBar", booleanAttribute], minDate: "minDate", maxDate: "maxDate" }, outputs: { dateSelectEvent: "dateSelectEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, ngImport: i0, template: "@if (labelKey || label) {\n <ef-label [labelKey]=\"labelKey\" [label]=\"label\" [for]=\"effectiveId\" [required]=\"required\" />\n}\n<div class=\"ef-field-control\">\n <p-datepicker\n [inputId]=\"effectiveId\"\n [name]=\"name\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"disabled\"\n [showIcon]=\"showIcon\"\n [iconDisplay]=\"iconDisplay\"\n [selectionMode]=\"selectionMode\"\n [dateFormat]=\"dateFormat\"\n [appendTo]=\"appendTo\"\n [showTime]=\"showTime\"\n [showButtonBar]=\"showButtonBar\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [fluid]=\"fluid\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n />\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i1$d.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
7521
7754
  }
7522
7755
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDatepickerComponent, decorators: [{
7523
7756
  type: Component,
@@ -7639,7 +7872,7 @@ class EfPasswordComponent extends AbstractEfFormControl {
7639
7872
  this.onTouched();
7640
7873
  }
7641
7874
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7642
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfPasswordComponent, isStandalone: true, selector: "ef-password", inputs: { size: "size", fluid: ["fluid", "fluid", booleanAttribute], inline: ["inline", "inline", booleanAttribute], toggleMask: ["toggleMask", "toggleMask", booleanAttribute], feedback: ["feedback", "feedback", booleanAttribute], autocomplete: "autocomplete" }, outputs: { valueChangeEvent: "valueChangeEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, usesInheritance: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n <p-password\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [toggleMask]=\"toggleMask\"\n [feedback]=\"feedback\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n [showClear]=\"canClear\"\n (onClear)=\"clearValue()\"\n styleClass=\"ef-password-field\"\n fluid\n >\n <ng-template #clearicon>\n <span class=\"ef-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n </p-password>\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: PasswordModule }, { kind: "component", type: i1$c.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
7875
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfPasswordComponent, isStandalone: true, selector: "ef-password", inputs: { size: "size", fluid: ["fluid", "fluid", booleanAttribute], inline: ["inline", "inline", booleanAttribute], toggleMask: ["toggleMask", "toggleMask", booleanAttribute], feedback: ["feedback", "feedback", booleanAttribute], autocomplete: "autocomplete" }, outputs: { valueChangeEvent: "valueChangeEvent" }, host: { properties: { "class.ef-inline": "this.isInline" } }, usesInheritance: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" [for]=\"effectiveId\" [required]=\"required()\" />\n}\n<div class=\"ef-field-control\">\n <p-password\n [inputId]=\"effectiveId\"\n [name]=\"name()\"\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (ngModelChange)=\"handleChange($event)\"\n (onBlur)=\"handleBlur()\"\n [toggleMask]=\"toggleMask\"\n [feedback]=\"feedback\"\n [placeholder]=\"effectivePlaceholder\"\n [size]=\"size\"\n [disabled]=\"isDisabled()\"\n [attr.autocomplete]=\"autocomplete\"\n [class.ng-invalid]=\"isInvalid\"\n [class.ng-touched]=\"ngControl?.touched\"\n [showClear]=\"canClear\"\n (onClear)=\"clearValue()\"\n styleClass=\"ef-password-field\"\n fluid\n >\n <ng-template #clearicon>\n <span class=\"ef-clear\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\">\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n </span>\n </ng-template>\n </p-password>\n @if (showRequired) {\n <small class=\"text-danger\">{{ 'validation.required' | translate }}</small>\n }\n @if (serverErrors; as errors) {\n @for (error of errors; track error) {\n <small class=\"text-danger block\">{{ error }}</small>\n }\n }\n</div>\n", styles: [":host{display:block}:host(.ef-inline){display:flex;align-items:baseline;gap:.5rem}:host(.ef-inline)>label{white-space:nowrap;flex-shrink:0}:host(.ef-inline)>.ef-field-control{flex:1;min-width:0}\n"], dependencies: [{ kind: "ngmodule", type: PasswordModule }, { kind: "component", type: i1$e.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
7643
7876
  }
7644
7877
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfPasswordComponent, decorators: [{
7645
7878
  type: Component,
@@ -7825,7 +8058,7 @@ class EfSelectButtonComponent extends AbstractEfFormControl {
7825
8058
  this.onTouched();
7826
8059
  }
7827
8060
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfSelectButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7828
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfSelectButtonComponent, isStandalone: true, selector: "ef-selectbutton", inputs: { options: "options", optionLabel: "optionLabel", optionValue: "optionValue", multiple: ["multiple", "multiple", booleanAttribute], allowEmpty: ["allowEmpty", "allowEmpty", booleanAttribute], size: "size", styleClass: "styleClass" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" />\n}\n<p-selectbutton\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleChange($event)\"\n [options]=\"options\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [multiple]=\"multiple\"\n [allowEmpty]=\"allowEmpty\"\n [disabled]=\"isDisabled()\"\n [size]=\"size\"\n [styleClass]=\"styleClass\"\n>\n @if (itemTemplate) {\n <ng-template let-item pTemplate=\"item\">\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n</p-selectbutton>\n", dependencies: [{ kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i1$d.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }] });
8061
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfSelectButtonComponent, isStandalone: true, selector: "ef-selectbutton", inputs: { options: "options", optionLabel: "optionLabel", optionValue: "optionValue", multiple: ["multiple", "multiple", booleanAttribute], allowEmpty: ["allowEmpty", "allowEmpty", booleanAttribute], size: "size", styleClass: "styleClass" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: ["item"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (labelKey() || label()) {\n <ef-label [labelKey]=\"labelKey()\" [label]=\"label()\" />\n}\n<p-selectbutton\n [ngModel]=\"value\"\n [ngModelOptions]=\"{standalone: true}\"\n (onChange)=\"handleChange($event)\"\n [options]=\"options\"\n [optionLabel]=\"optionLabel\"\n [optionValue]=\"optionValue\"\n [multiple]=\"multiple\"\n [allowEmpty]=\"allowEmpty\"\n [disabled]=\"isDisabled()\"\n [size]=\"size\"\n [styleClass]=\"styleClass\"\n>\n @if (itemTemplate) {\n <ng-template let-item pTemplate=\"item\">\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\" />\n </ng-template>\n }\n</p-selectbutton>\n", dependencies: [{ kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i1$f.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EfLabelComponent, selector: "ef-label", inputs: ["label", "labelKey", "for", "styleClass", "required"] }] });
7829
8062
  }
7830
8063
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfSelectButtonComponent, decorators: [{
7831
8064
  type: Component,
@@ -8282,7 +8515,7 @@ class EfDatatableComponent {
8282
8515
  return this.pTable?.filters;
8283
8516
  }
8284
8517
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDatatableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8285
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDatatableComponent, isStandalone: true, selector: "ef-datatable", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, searchEntity: { classPropertyName: "searchEntity", publicName: "searchEntity", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, pt: { classPropertyName: "pt", publicName: "pt", isSignal: true, isRequired: false, transformFunction: null }, screenStateKey: { classPropertyName: "screenStateKey", publicName: "screenStateKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editRow: "editRow", deleteRow: "deleteRow", duplicateRow: "duplicateRow", lazyLoad: "lazyLoad", rowSelect: "rowSelect" }, viewQueries: [{ propertyName: "pTable", first: true, predicate: ["pTable"], descendants: true }], ngImport: i0, template: "<p-table #pTable\n [value]=\"searchEntity()?.items || []\"\n [columns]=\"processedColumns()\"\n [dataKey]=\"mergedConfig.dataKey\"\n\n [lazy]=\"mergedConfig.lazy\"\n (onLazyLoad)=\"handleLazyLoad($event)\"\n\n [paginator]=\"mergedConfig.paginator\"\n [rows]=\"searchEntity()?.pagination?.pageSize || mergedConfig.rows\"\n [rowsPerPageOptions]=\"mergedConfig.rowsPerPageOptions\"\n [totalRecords]=\"searchEntity()?.totalCount || 0\"\n [first]=\"searchEntity()?.pagination ? (searchEntity()!.pagination!.pageNumber - 1) * searchEntity()!.pagination!.pageSize : 0\"\n\n [scrollable]=\"mergedConfig.scrollable\"\n [scrollHeight]=\"mergedConfig.scrollHeight\"\n\n [resizableColumns]=\"mergedConfig.resizableColumns\"\n [columnResizeMode]=\"mergedConfig.columnResizeMode\"\n\n [stateStorage]=\"mergedConfig.stateStorage\"\n [stateKey]=\"mergedConfig.stateKey\"\n\n [size]=\"mergedConfig.size\"\n [class]=\"mergedConfig.styleClass\"\n [tableStyle]=\"mergedConfig.tableStyle\"\n\n [currentPageReportTemplate]=\"searchEntity()?.totalCount ? 'Affichage de {first} a {last} sur {totalRecords} entrees' : mergedConfig.emptyMessage\"\n [showCurrentPageReport]=\"true\"\n [sortField]=\"sortField()\"\n [sortOrder]=\"sortOrder()\"\n [loading]=\"loading()\"\n\n [pt]=\"pt()\"\n\n selectionMode=\"single\" [(selection)]=\"selectedItem\">\n\n <!-- Header Template -->\n <ng-template #header>\n <tr>\n <!-- Action column at start if configured -->\n @if (mergedActions.show && mergedActions.position === 'start') {\n <th [class]=\"mergedActions.width\"></th>\n }\n\n <!-- Data columns -->\n @for (column of processedColumns(); track column.field) {\n @if (column.sortable && column.resizable) {\n <th\n [pSortableColumn]=\"column.field\"\n pResizableColumn\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n <p-sortIcon [field]=\"column.field\" />\n }\n </th>\n } @else if (column.sortable) {\n <th\n [pSortableColumn]=\"column.field\"\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n <p-sortIcon [field]=\"column.field\" />\n }\n </th>\n } @else if (column.resizable) {\n <th\n pResizableColumn\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n }\n </th>\n } @else {\n <th\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n }\n </th>\n }\n }\n\n <!-- Action column at end if configured -->\n @if (mergedActions.show && mergedActions.position === 'end') {\n <th [class]=\"mergedActions.width\"></th>\n }\n </tr>\n </ng-template>\n\n <!-- Body Template -->\n <ng-template #body let-rowData let-rowIndex=\"rowIndex\">\n <tr (dblclick)=\"handleEdit(rowData)\" style=\"cursor: pointer\"\n [pSelectableRow]=\"rowData\" [pSelectableRowIndex]=\"rowIndex\">\n <!-- Action column at start if configured -->\n @if (mergedActions.show && mergedActions.position === 'start') {\n <td>\n <ef-datatable-actionbar\n [context]=\"context()\"\n (edit)=\"handleEdit(rowData)\"\n (delete)=\"handleDelete(rowData)\"\n (duplicate)=\"handleDuplicate(rowData)\">\n </ef-datatable-actionbar>\n </td>\n }\n\n <!-- Data columns -->\n @for (column of processedColumns(); track column.field) {\n <td [ngClass]=\"getAlignmentClass(column.align)\">\n @if (column.template) {\n <ng-container *ngTemplateOutlet=\"column.template; context: { $implicit: rowData, column: column }\"></ng-container>\n } @else {\n {{ formatCellValue(rowData, column) }}\n }\n </td>\n }\n\n <!-- Action column at end if configured -->\n @if (mergedActions.show && mergedActions.position === 'end') {\n <td>\n <ef-datatable-actionbar\n [context]=\"context()\"\n (edit)=\"handleEdit(rowData)\"\n (delete)=\"handleDelete(rowData)\"\n (duplicate)=\"handleDuplicate(rowData)\">\n </ef-datatable-actionbar>\n </td>\n }\n </tr>\n </ng-template>\n</p-table>\n", styles: [":host{display:block}:host ::ng-deep .text-end{text-align:right!important}:host ::ng-deep .text-center{text-align:center!important}:host ::ng-deep .text-start{text-align:left!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$5.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$5.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i2$5.SelectableRow, selector: "[pSelectableRow]", inputs: ["pSelectableRow", "pSelectableRowIndex", "pSelectableRowDisabled"] }, { kind: "directive", type: i2$5.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "component", type: i2$5.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfDatatableActionBarComponent, selector: "ef-datatable-actionbar", inputs: ["context", "state", "duplicateButton", "editButton", "deleteButton"], outputs: ["duplicate", "edit", "delete"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8518
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfDatatableComponent, isStandalone: true, selector: "ef-datatable", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, searchEntity: { classPropertyName: "searchEntity", publicName: "searchEntity", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, pt: { classPropertyName: "pt", publicName: "pt", isSignal: true, isRequired: false, transformFunction: null }, screenStateKey: { classPropertyName: "screenStateKey", publicName: "screenStateKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { editRow: "editRow", deleteRow: "deleteRow", duplicateRow: "duplicateRow", lazyLoad: "lazyLoad", rowSelect: "rowSelect" }, viewQueries: [{ propertyName: "pTable", first: true, predicate: ["pTable"], descendants: true }], ngImport: i0, template: "<p-table #pTable\n [value]=\"searchEntity()?.items || []\"\n [columns]=\"processedColumns()\"\n [dataKey]=\"mergedConfig.dataKey\"\n\n [lazy]=\"mergedConfig.lazy\"\n (onLazyLoad)=\"handleLazyLoad($event)\"\n\n [paginator]=\"mergedConfig.paginator\"\n [rows]=\"searchEntity()?.pagination?.pageSize || mergedConfig.rows\"\n [rowsPerPageOptions]=\"mergedConfig.rowsPerPageOptions\"\n [totalRecords]=\"searchEntity()?.totalCount || 0\"\n [first]=\"searchEntity()?.pagination ? (searchEntity()!.pagination!.pageNumber - 1) * searchEntity()!.pagination!.pageSize : 0\"\n\n [scrollable]=\"mergedConfig.scrollable\"\n [scrollHeight]=\"mergedConfig.scrollHeight\"\n\n [resizableColumns]=\"mergedConfig.resizableColumns\"\n [columnResizeMode]=\"mergedConfig.columnResizeMode\"\n\n [stateStorage]=\"mergedConfig.stateStorage\"\n [stateKey]=\"mergedConfig.stateKey\"\n\n [size]=\"mergedConfig.size\"\n [class]=\"mergedConfig.styleClass\"\n [tableStyle]=\"mergedConfig.tableStyle\"\n\n [currentPageReportTemplate]=\"searchEntity()?.totalCount ? 'Affichage de {first} a {last} sur {totalRecords} entrees' : mergedConfig.emptyMessage\"\n [showCurrentPageReport]=\"true\"\n [sortField]=\"sortField()\"\n [sortOrder]=\"sortOrder()\"\n [loading]=\"loading()\"\n\n [pt]=\"pt()\"\n\n selectionMode=\"single\" [(selection)]=\"selectedItem\">\n\n <!-- Header Template -->\n <ng-template #header>\n <tr>\n <!-- Action column at start if configured -->\n @if (mergedActions.show && mergedActions.position === 'start') {\n <th [class]=\"mergedActions.width\"></th>\n }\n\n <!-- Data columns -->\n @for (column of processedColumns(); track column.field) {\n @if (column.sortable && column.resizable) {\n <th\n [pSortableColumn]=\"column.field\"\n pResizableColumn\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n <p-sortIcon [field]=\"column.field\" />\n }\n </th>\n } @else if (column.sortable) {\n <th\n [pSortableColumn]=\"column.field\"\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n <p-sortIcon [field]=\"column.field\" />\n }\n </th>\n } @else if (column.resizable) {\n <th\n pResizableColumn\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n }\n </th>\n } @else {\n <th\n [class]=\"column.width || ''\"\n [ngClass]=\"column.styleClass\">\n\n @if (column.headerTemplate) {\n <ng-container *ngTemplateOutlet=\"column.headerTemplate; context: { $implicit: column }\"></ng-container>\n } @else {\n {{ column.header | translate }}\n }\n </th>\n }\n }\n\n <!-- Action column at end if configured -->\n @if (mergedActions.show && mergedActions.position === 'end') {\n <th [class]=\"mergedActions.width\"></th>\n }\n </tr>\n </ng-template>\n\n <!-- Body Template -->\n <ng-template #body let-rowData let-rowIndex=\"rowIndex\">\n <tr (dblclick)=\"handleEdit(rowData)\" style=\"cursor: pointer\"\n [pSelectableRow]=\"rowData\" [pSelectableRowIndex]=\"rowIndex\">\n <!-- Action column at start if configured -->\n @if (mergedActions.show && mergedActions.position === 'start') {\n <td>\n <ef-datatable-actionbar\n [context]=\"context()\"\n (edit)=\"handleEdit(rowData)\"\n (delete)=\"handleDelete(rowData)\"\n (duplicate)=\"handleDuplicate(rowData)\">\n </ef-datatable-actionbar>\n </td>\n }\n\n <!-- Data columns -->\n @for (column of processedColumns(); track column.field) {\n <td [ngClass]=\"getAlignmentClass(column.align)\">\n @if (column.template) {\n <ng-container *ngTemplateOutlet=\"column.template; context: { $implicit: rowData, column: column }\"></ng-container>\n } @else {\n {{ formatCellValue(rowData, column) }}\n }\n </td>\n }\n\n <!-- Action column at end if configured -->\n @if (mergedActions.show && mergedActions.position === 'end') {\n <td>\n <ef-datatable-actionbar\n [context]=\"context()\"\n (edit)=\"handleEdit(rowData)\"\n (delete)=\"handleDelete(rowData)\"\n (duplicate)=\"handleDuplicate(rowData)\">\n </ef-datatable-actionbar>\n </td>\n }\n </tr>\n </ng-template>\n</p-table>\n", styles: [":host{display:block}:host ::ng-deep .text-end{text-align:right!important}:host ::ng-deep .text-center{text-align:center!important}:host ::ng-deep .text-start{text-align:left!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$4.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i2$4.SelectableRow, selector: "[pSelectableRow]", inputs: ["pSelectableRow", "pSelectableRowIndex", "pSelectableRowDisabled"] }, { kind: "directive", type: i2$4.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "component", type: i2$4.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfDatatableActionBarComponent, selector: "ef-datatable-actionbar", inputs: ["context", "state", "duplicateButton", "editButton", "deleteButton"], outputs: ["duplicate", "edit", "delete"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8286
8519
  }
8287
8520
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfDatatableComponent, decorators: [{
8288
8521
  type: Component,
@@ -8328,6 +8561,13 @@ class EfPagerComponent {
8328
8561
  hideSize = input(false, ...(ngDevMode ? [{ debugName: "hideSize" }] : /* istanbul ignore next */ []));
8329
8562
  pageChange = output();
8330
8563
  pageSizeChange = output();
8564
+ /** Falls back to the first configured option if the value ever goes empty. */
8565
+ get defaultSize() {
8566
+ return this.pageSizeOptions()[0] ?? this.pageSize();
8567
+ }
8568
+ /** `pageSizeOptions` shaped for `ef-select`, which reads a label and a
8569
+ * value off each option rather than taking bare primitives. */
8570
+ sizeOptions = computed(() => this.pageSizeOptions().map(n => ({ label: String(n), value: n })), ...(ngDevMode ? [{ debugName: "sizeOptions" }] : /* istanbul ignore next */ []));
8331
8571
  totalPages = computed(() => {
8332
8572
  const size = this.pageSize();
8333
8573
  return size > 0 ? Math.max(1, Math.ceil(this.totalCount() / size)) : 1;
@@ -8369,20 +8609,28 @@ class EfPagerComponent {
8369
8609
  this.pageChange.emit(page);
8370
8610
  }
8371
8611
  onSizeChange(value) {
8372
- const size = parseInt(value, 10);
8373
- if (!Number.isNaN(size) && size > 0 && size !== this.pageSize()) {
8374
- this.pageSizeChange.emit(size);
8612
+ const size = typeof value === 'number' ? value : parseInt(value ?? '', 10);
8613
+ if (Number.isNaN(size) || size <= 0) {
8614
+ // "No page size" has no meaning. The control is not clearable
8615
+ // (see the template), so this only guards a value arriving empty
8616
+ // from somewhere else: fall back to the first configured option.
8617
+ const fallback = this.defaultSize;
8618
+ if (fallback !== this.pageSize())
8619
+ this.pageSizeChange.emit(fallback);
8620
+ return;
8375
8621
  }
8622
+ if (size !== this.pageSize())
8623
+ this.pageSizeChange.emit(size);
8376
8624
  }
8377
8625
  trackBtn(index, btn) {
8378
8626
  return btn.kind === 'page' ? `p${btn.value}` : `e${index}`;
8379
8627
  }
8380
8628
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfPagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8381
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfPagerComponent, isStandalone: true, selector: "ef-pager", inputs: { pageNumber: { classPropertyName: "pageNumber", publicName: "pageNumber", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, totalCount: { classPropertyName: "totalCount", publicName: "totalCount", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, linesPerPageLabelKey: { classPropertyName: "linesPerPageLabelKey", publicName: "linesPerPageLabelKey", isSignal: true, isRequired: false, transformFunction: null }, ofLabelKey: { classPropertyName: "ofLabelKey", publicName: "ofLabelKey", isSignal: true, isRequired: false, transformFunction: null }, prevLabelKey: { classPropertyName: "prevLabelKey", publicName: "prevLabelKey", isSignal: true, isRequired: false, transformFunction: null }, nextLabelKey: { classPropertyName: "nextLabelKey", publicName: "nextLabelKey", isSignal: true, isRequired: false, transformFunction: null }, hideSize: { classPropertyName: "hideSize", publicName: "hideSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange" }, ngImport: i0, template: "<div class=\"pager\">\n @if (!hideSize()) {\n <div class=\"size\">\n <span>{{ linesPerPageLabelKey() | translate }}</span>\n <select\n [value]=\"pageSize()\"\n [attr.aria-label]=\"linesPerPageLabelKey() | translate\"\n (change)=\"onSizeChange($any($event.target).value)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <option [value]=\"option\" [selected]=\"option === pageSize()\">{{ option }}</option>\n }\n </select>\n @if (totalCount() > 0) {\n <span>\u00B7 {{ range().start }}\u2013{{ range().end }} {{ ofLabelKey() | translate }} {{ totalCount() }}</span>\n }\n </div>\n } @else {\n <span></span>\n }\n\n <div class=\"pages\">\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() <= 1\"\n [attr.aria-label]=\"prevLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() - 1)\"\n >\u2039</button>\n\n @for (btn of pageButtons(); track trackBtn($index, btn)) {\n @if (btn.kind === 'page') {\n <button\n class=\"pg\"\n type=\"button\"\n [class.active]=\"btn.value === pageNumber()\"\n (click)=\"goToPage(btn.value)\"\n >{{ btn.value }}</button>\n } @else {\n <span class=\"pg\" aria-hidden=\"true\" style=\"cursor: default;\">\u2026</span>\n }\n }\n\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() >= totalPages()\"\n [attr.aria-label]=\"nextLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() + 1)\"\n >\u203A</button>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8629
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfPagerComponent, isStandalone: true, selector: "ef-pager", inputs: { pageNumber: { classPropertyName: "pageNumber", publicName: "pageNumber", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, totalCount: { classPropertyName: "totalCount", publicName: "totalCount", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, linesPerPageLabelKey: { classPropertyName: "linesPerPageLabelKey", publicName: "linesPerPageLabelKey", isSignal: true, isRequired: false, transformFunction: null }, ofLabelKey: { classPropertyName: "ofLabelKey", publicName: "ofLabelKey", isSignal: true, isRequired: false, transformFunction: null }, prevLabelKey: { classPropertyName: "prevLabelKey", publicName: "prevLabelKey", isSignal: true, isRequired: false, transformFunction: null }, nextLabelKey: { classPropertyName: "nextLabelKey", publicName: "nextLabelKey", isSignal: true, isRequired: false, transformFunction: null }, hideSize: { classPropertyName: "hideSize", publicName: "hideSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pageChange: "pageChange", pageSizeChange: "pageSizeChange" }, ngImport: i0, template: "<div class=\"pager\">\n @if (!hideSize()) {\n <div class=\"size\">\n <span>{{ linesPerPageLabelKey() | translate }}</span>\n <ef-select\n size=\"small\"\n appendTo=\"body\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [options]=\"sizeOptions()\"\n [value]=\"pageSize()\"\n [ariaLabelKey]=\"linesPerPageLabelKey()\"\n [showClear]=\"false\"\n (selectionChangeEvent)=\"onSizeChange($event)\"\n />\n @if (totalCount() > 0) {\n <span>\u00B7 {{ range().start }}\u2013{{ range().end }} {{ ofLabelKey() | translate }} {{ totalCount() }}</span>\n }\n </div>\n } @else {\n <span></span>\n }\n\n <div class=\"pages\">\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() <= 1\"\n [attr.aria-label]=\"prevLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() - 1)\"\n >\u2039</button>\n\n @for (btn of pageButtons(); track trackBtn($index, btn)) {\n @if (btn.kind === 'page') {\n <button\n class=\"pg\"\n type=\"button\"\n [class.active]=\"btn.value === pageNumber()\"\n (click)=\"goToPage(btn.value)\"\n >{{ btn.value }}</button>\n } @else {\n <span class=\"pg\" aria-hidden=\"true\" style=\"cursor: default;\">\u2026</span>\n }\n }\n\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() >= totalPages()\"\n [attr.aria-label]=\"nextLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() + 1)\"\n >\u203A</button>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: EfSelectComponent, selector: "ef-select", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "dataKey", "group", "optionGroupLabel", "optionGroupChildren", "size", "fluid", "inline", "appendTo", "multiple", "filter", "filterBy", "filterPlaceholder", "filterPlaceholderKey", "autofocusFilter", "editable", "loading", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "multiDisplay", "showToggleAll", "emptyMessage", "emptyMessageKey", "emptyFilterMessage", "emptyFilterMessageKey", "styleClass", "panelStyleClass", "filterByKeys", "variant", "value"], outputs: ["selectionChangeEvent", "filterChangeEvent", "panelShowEvent", "panelHideEvent"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8382
8630
  }
8383
8631
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfPagerComponent, decorators: [{
8384
8632
  type: Component,
8385
- args: [{ selector: 'ef-pager', standalone: true, imports: [CommonModule, TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"pager\">\n @if (!hideSize()) {\n <div class=\"size\">\n <span>{{ linesPerPageLabelKey() | translate }}</span>\n <select\n [value]=\"pageSize()\"\n [attr.aria-label]=\"linesPerPageLabelKey() | translate\"\n (change)=\"onSizeChange($any($event.target).value)\"\n >\n @for (option of pageSizeOptions(); track option) {\n <option [value]=\"option\" [selected]=\"option === pageSize()\">{{ option }}</option>\n }\n </select>\n @if (totalCount() > 0) {\n <span>\u00B7 {{ range().start }}\u2013{{ range().end }} {{ ofLabelKey() | translate }} {{ totalCount() }}</span>\n }\n </div>\n } @else {\n <span></span>\n }\n\n <div class=\"pages\">\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() <= 1\"\n [attr.aria-label]=\"prevLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() - 1)\"\n >\u2039</button>\n\n @for (btn of pageButtons(); track trackBtn($index, btn)) {\n @if (btn.kind === 'page') {\n <button\n class=\"pg\"\n type=\"button\"\n [class.active]=\"btn.value === pageNumber()\"\n (click)=\"goToPage(btn.value)\"\n >{{ btn.value }}</button>\n } @else {\n <span class=\"pg\" aria-hidden=\"true\" style=\"cursor: default;\">\u2026</span>\n }\n }\n\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() >= totalPages()\"\n [attr.aria-label]=\"nextLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() + 1)\"\n >\u203A</button>\n </div>\n</div>\n" }]
8633
+ args: [{ selector: 'ef-pager', standalone: true, imports: [CommonModule, TranslateModule, EfSelectComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"pager\">\n @if (!hideSize()) {\n <div class=\"size\">\n <span>{{ linesPerPageLabelKey() | translate }}</span>\n <ef-select\n size=\"small\"\n appendTo=\"body\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [options]=\"sizeOptions()\"\n [value]=\"pageSize()\"\n [ariaLabelKey]=\"linesPerPageLabelKey()\"\n [showClear]=\"false\"\n (selectionChangeEvent)=\"onSizeChange($event)\"\n />\n @if (totalCount() > 0) {\n <span>\u00B7 {{ range().start }}\u2013{{ range().end }} {{ ofLabelKey() | translate }} {{ totalCount() }}</span>\n }\n </div>\n } @else {\n <span></span>\n }\n\n <div class=\"pages\">\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() <= 1\"\n [attr.aria-label]=\"prevLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() - 1)\"\n >\u2039</button>\n\n @for (btn of pageButtons(); track trackBtn($index, btn)) {\n @if (btn.kind === 'page') {\n <button\n class=\"pg\"\n type=\"button\"\n [class.active]=\"btn.value === pageNumber()\"\n (click)=\"goToPage(btn.value)\"\n >{{ btn.value }}</button>\n } @else {\n <span class=\"pg\" aria-hidden=\"true\" style=\"cursor: default;\">\u2026</span>\n }\n }\n\n <button\n class=\"pg\"\n type=\"button\"\n [disabled]=\"pageNumber() >= totalPages()\"\n [attr.aria-label]=\"nextLabelKey() | translate\"\n (click)=\"goToPage(pageNumber() + 1)\"\n >\u203A</button>\n </div>\n</div>\n" }]
8386
8634
  }], propDecorators: { pageNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageNumber", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], totalCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalCount", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], linesPerPageLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "linesPerPageLabelKey", required: false }] }], ofLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "ofLabelKey", required: false }] }], prevLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabelKey", required: false }] }], nextLabelKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabelKey", required: false }] }], hideSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideSize", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }] } });
8387
8635
 
8388
8636
  /**
@@ -8413,6 +8661,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
8413
8661
  *
8414
8662
  * Behaviour:
8415
8663
  * - Click the trigger to toggle. Trigger gets `.open` (ink-active) while the menu is open.
8664
+ * - Only one row menu is open at a time — opening one closes the last.
8665
+ * - The menu flips above the trigger when there isn't room below it.
8416
8666
  * - Click outside or press `Escape` to close.
8417
8667
  * - Clicking an item runs its `command` then closes the menu.
8418
8668
  * - dblclick on the trigger or menu does NOT propagate, so the data-card's
@@ -8451,12 +8701,32 @@ class EfRowActionsComponent {
8451
8701
  }, ...(ngDevMode ? [{ debugName: "visibleItems" }] : /* istanbul ignore next */ []));
8452
8702
  /** Open state. */
8453
8703
  open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
8704
+ /** Menu renders above the trigger instead of below it. */
8705
+ dropUp = signal(false, ...(ngDevMode ? [{ debugName: "dropUp" }] : /* istanbul ignore next */ []));
8706
+ /**
8707
+ * The one menu currently open, app-wide.
8708
+ *
8709
+ * The trigger click is stopped from reaching `document` so it can't
8710
+ * select or open the row, which also means no other instance's
8711
+ * outside-click listener ever sees it. Without an explicit hand-off
8712
+ * every menu clicked stays open and they stack up on screen.
8713
+ */
8714
+ static openInstance = null;
8454
8715
  toggle(event) {
8455
8716
  event.stopPropagation();
8456
8717
  if (this.disabled() || this.visibleItems().length === 0)
8457
8718
  return;
8458
8719
  this.open.update(v => !v);
8459
8720
  const isOpen = this.open();
8721
+ if (isOpen) {
8722
+ EfRowActionsComponent.openInstance?.close();
8723
+ EfRowActionsComponent.openInstance = this;
8724
+ // Place it from an estimate first so it never renders in the
8725
+ // wrong direction, then correct against the real height once
8726
+ // the menu is in the DOM.
8727
+ this.dropUp.set(this.shouldDropUp(this.estimateMenuHeight()));
8728
+ this.correctPlacementAfterRender();
8729
+ }
8460
8730
  this.dispatchToggle(isOpen);
8461
8731
  if (isOpen)
8462
8732
  this.opened.emit();
@@ -8474,9 +8744,46 @@ class EfRowActionsComponent {
8474
8744
  if (!this.open())
8475
8745
  return;
8476
8746
  this.open.set(false);
8747
+ if (EfRowActionsComponent.openInstance === this) {
8748
+ EfRowActionsComponent.openInstance = null;
8749
+ }
8477
8750
  this.dispatchToggle(false);
8478
8751
  this.closed.emit();
8479
8752
  }
8753
+ /* ── Placement ──────────────────────────────────────────────── */
8754
+ /** Gap between the trigger and the menu, plus a little breathing room
8755
+ * against the viewport edge. Matches `top: calc(100% + 8px)`. */
8756
+ static EDGE_GAP = 16;
8757
+ /**
8758
+ * Drop upward when the menu would not fit below the trigger and there
8759
+ * is more room above. On a short viewport where it fits neither way,
8760
+ * below wins, which is where it has always been.
8761
+ */
8762
+ shouldDropUp(menuHeight) {
8763
+ const rect = this.host.nativeElement.getBoundingClientRect();
8764
+ const below = window.innerHeight - rect.bottom;
8765
+ const above = rect.top;
8766
+ return below < menuHeight + EfRowActionsComponent.EDGE_GAP && above > below;
8767
+ }
8768
+ /** Rough height before the menu exists: item padding + line box, with
8769
+ * dividers and the menu's own padding and border. */
8770
+ estimateMenuHeight() {
8771
+ const items = this.visibleItems();
8772
+ const separators = items.filter(a => a.separator).length;
8773
+ return 14 + (items.length - separators) * 39 + separators * 10;
8774
+ }
8775
+ /** Re-decide against the rendered height — item labels wrap, and the
8776
+ * estimate can't know that. */
8777
+ correctPlacementAfterRender() {
8778
+ requestAnimationFrame(() => {
8779
+ if (!this.open())
8780
+ return;
8781
+ const menu = this.host.nativeElement.querySelector('.row-actions__menu');
8782
+ if (!menu)
8783
+ return;
8784
+ this.dropUp.set(this.shouldDropUp(menu.offsetHeight));
8785
+ });
8786
+ }
8480
8787
  /** Bubbling DOM event so ancestors (e.g. ef-data-card) can react —
8481
8788
  * see `.tbl-wrap.has-open-menu { overflow: visible }`. */
8482
8789
  dispatchToggle(open) {
@@ -8515,11 +8822,11 @@ class EfRowActionsComponent {
8515
8822
  /** Stable trackBy across renders. */
8516
8823
  trackByItem = (i, action) => action.id ?? (action.separator ? `__sep_${i}` : action.label ?? action.labelKey ?? i);
8517
8824
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfRowActionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8518
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfRowActionsComponent, isStandalone: true, selector: "ef-row-actions", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, triggerIcon: { classPropertyName: "triggerIcon", publicName: "triggerIcon", isSignal: true, isRequired: false, transformFunction: null }, triggerAriaKey: { classPropertyName: "triggerAriaKey", publicName: "triggerAriaKey", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, menuLeft: { classPropertyName: "menuLeft", publicName: "menuLeft", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "<div class=\"row-actions\">\n <button\n type=\"button\"\n class=\"row-actions__trigger\"\n [class.open]=\"open()\"\n [disabled]=\"disabled() || visibleItems().length === 0\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (click)=\"toggle($event)\"\n (dblclick)=\"onDblClick($event)\"\n >\n <i [class]=\"triggerIcon()\" aria-hidden=\"true\"></i>\n </button>\n\n @if (open()) {\n <div\n class=\"row-actions__menu open\"\n [class.left]=\"menuLeft()\"\n role=\"menu\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (dblclick)=\"onDblClick($event)\"\n >\n @for (action of visibleItems(); track trackByItem($index, action)) {\n @if (action.separator) {\n <div class=\"row-actions__divider\" role=\"separator\"></div>\n } @else {\n <button\n type=\"button\"\n class=\"row-actions__item\"\n [class.danger]=\"action.severity === 'danger'\"\n [disabled]=\"action.disabled\"\n role=\"menuitem\"\n (click)=\"runCommand(action, $event)\"\n >\n @if (action.icon) {\n <i class=\"ico\" [class]=\"'ico ' + action.icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"lbl\">\n {{ action.labelKey ? (action.labelKey | translate) : action.label }}\n </span>\n @if (action.kbd) {\n <span class=\"kbd\" aria-hidden=\"true\">{{ action.kbd }}</span>\n }\n </button>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:inline-flex;align-items:center;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8825
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfRowActionsComponent, isStandalone: true, selector: "ef-row-actions", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, triggerIcon: { classPropertyName: "triggerIcon", publicName: "triggerIcon", isSignal: true, isRequired: false, transformFunction: null }, triggerAriaKey: { classPropertyName: "triggerAriaKey", publicName: "triggerAriaKey", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, menuLeft: { classPropertyName: "menuLeft", publicName: "menuLeft", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "<div class=\"row-actions\">\n <button\n type=\"button\"\n class=\"row-actions__trigger\"\n [class.open]=\"open()\"\n [disabled]=\"disabled() || visibleItems().length === 0\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (click)=\"toggle($event)\"\n (dblclick)=\"onDblClick($event)\"\n >\n <i [class]=\"triggerIcon()\" aria-hidden=\"true\"></i>\n </button>\n\n @if (open()) {\n <div\n class=\"row-actions__menu open\"\n [class.left]=\"menuLeft()\"\n [class.up]=\"dropUp()\"\n role=\"menu\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (dblclick)=\"onDblClick($event)\"\n >\n @for (action of visibleItems(); track trackByItem($index, action)) {\n @if (action.separator) {\n <div class=\"row-actions__divider\" role=\"separator\"></div>\n } @else {\n <button\n type=\"button\"\n class=\"row-actions__item\"\n [class.danger]=\"action.severity === 'danger'\"\n [disabled]=\"action.disabled\"\n role=\"menuitem\"\n (click)=\"runCommand(action, $event)\"\n >\n @if (action.icon) {\n <i class=\"ico\" [class]=\"'ico ' + action.icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"lbl\">\n {{ action.labelKey ? (action.labelKey | translate) : action.label }}\n </span>\n @if (action.kbd) {\n <span class=\"kbd\" aria-hidden=\"true\">{{ action.kbd }}</span>\n }\n </button>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:inline-flex;align-items:center;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8519
8826
  }
8520
8827
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfRowActionsComponent, decorators: [{
8521
8828
  type: Component,
8522
- args: [{ selector: 'ef-row-actions', standalone: true, imports: [CommonModule, TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"row-actions\">\n <button\n type=\"button\"\n class=\"row-actions__trigger\"\n [class.open]=\"open()\"\n [disabled]=\"disabled() || visibleItems().length === 0\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (click)=\"toggle($event)\"\n (dblclick)=\"onDblClick($event)\"\n >\n <i [class]=\"triggerIcon()\" aria-hidden=\"true\"></i>\n </button>\n\n @if (open()) {\n <div\n class=\"row-actions__menu open\"\n [class.left]=\"menuLeft()\"\n role=\"menu\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (dblclick)=\"onDblClick($event)\"\n >\n @for (action of visibleItems(); track trackByItem($index, action)) {\n @if (action.separator) {\n <div class=\"row-actions__divider\" role=\"separator\"></div>\n } @else {\n <button\n type=\"button\"\n class=\"row-actions__item\"\n [class.danger]=\"action.severity === 'danger'\"\n [disabled]=\"action.disabled\"\n role=\"menuitem\"\n (click)=\"runCommand(action, $event)\"\n >\n @if (action.icon) {\n <i class=\"ico\" [class]=\"'ico ' + action.icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"lbl\">\n {{ action.labelKey ? (action.labelKey | translate) : action.label }}\n </span>\n @if (action.kbd) {\n <span class=\"kbd\" aria-hidden=\"true\">{{ action.kbd }}</span>\n }\n </button>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:inline-flex;align-items:center;justify-content:flex-end}\n"] }]
8829
+ args: [{ selector: 'ef-row-actions', standalone: true, imports: [CommonModule, TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"row-actions\">\n <button\n type=\"button\"\n class=\"row-actions__trigger\"\n [class.open]=\"open()\"\n [disabled]=\"disabled() || visibleItems().length === 0\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (click)=\"toggle($event)\"\n (dblclick)=\"onDblClick($event)\"\n >\n <i [class]=\"triggerIcon()\" aria-hidden=\"true\"></i>\n </button>\n\n @if (open()) {\n <div\n class=\"row-actions__menu open\"\n [class.left]=\"menuLeft()\"\n [class.up]=\"dropUp()\"\n role=\"menu\"\n [attr.aria-label]=\"triggerAriaKey() | translate\"\n (dblclick)=\"onDblClick($event)\"\n >\n @for (action of visibleItems(); track trackByItem($index, action)) {\n @if (action.separator) {\n <div class=\"row-actions__divider\" role=\"separator\"></div>\n } @else {\n <button\n type=\"button\"\n class=\"row-actions__item\"\n [class.danger]=\"action.severity === 'danger'\"\n [disabled]=\"action.disabled\"\n role=\"menuitem\"\n (click)=\"runCommand(action, $event)\"\n >\n @if (action.icon) {\n <i class=\"ico\" [class]=\"'ico ' + action.icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"lbl\">\n {{ action.labelKey ? (action.labelKey | translate) : action.label }}\n </span>\n @if (action.kbd) {\n <span class=\"kbd\" aria-hidden=\"true\">{{ action.kbd }}</span>\n }\n </button>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:inline-flex;align-items:center;justify-content:flex-end}\n"] }]
8523
8830
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], triggerIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerIcon", required: false }] }], triggerAriaKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerAriaKey", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], menuLeft: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuLeft", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], onDocumentClick: [{
8524
8831
  type: HostListener,
8525
8832
  args: ['document:click', ['$event']]
@@ -10033,7 +10340,7 @@ class EfThemeConfiguratorComponent {
10033
10340
  </div>
10034
10341
  </div>
10035
10342
  </div>
10036
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i1$a.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
10343
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i1$c.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }] });
10037
10344
  }
10038
10345
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfThemeConfiguratorComponent, decorators: [{
10039
10346
  type: Component,
@@ -10195,7 +10502,7 @@ class EfEmailMetricsCardComponent {
10195
10502
  return 'warn';
10196
10503
  }
10197
10504
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfEmailMetricsCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10198
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfEmailMetricsCardComponent, isStandalone: true, selector: "ef-email-metrics-card", inputs: { metrics: { classPropertyName: "metrics", publicName: "metrics", isSignal: true, isRequired: false, transformFunction: null }, recentEvents: { classPropertyName: "recentEvents", publicName: "recentEvents", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rangeChange: "rangeChange" }, ngImport: i0, template: "<p-card styleClass=\"ef-email-metrics-card\">\n <ng-template pTemplate=\"header\">\n <div class=\"ef-email-metrics-card__header\">\n <div>\n <h3 class=\"ef-email-metrics-card__title\">{{ title() }}</h3>\n @if (metrics(); as m) {\n <p class=\"ef-email-metrics-card__subtitle\">\n {{ m.from | date: 'dd MMM' }} \u2013 {{ m.to | date: 'dd MMM yyyy' }}\n </p>\n }\n </div>\n <p-selectButton\n [options]=\"rangeOptions\"\n [(ngModel)]=\"selectedRange\"\n optionLabel=\"label\"\n optionValue=\"value\"\n styleClass=\"ef-email-metrics-card__range\"\n (onChange)=\"onRangeChange($event.value)\"\n />\n </div>\n </ng-template>\n\n @if (metrics(); as m) {\n <div class=\"ef-email-metrics-card__kpis\">\n @for (kpi of kpis(); track kpi.label) {\n <div class=\"ef-email-metrics-card__kpi\" [attr.data-tone]=\"kpi.tone\">\n <span class=\"ef-email-metrics-card__kpi-label\">{{ kpi.label }}</span>\n <span class=\"ef-email-metrics-card__kpi-value\">\n @if (kpi.rate) {\n {{ kpi.value | number: '1.1-1' : 'fr' }}\n <span class=\"ef-email-metrics-card__kpi-unit\">%</span>\n } @else {\n {{ kpi.value | number: '1.0-0' : 'fr' }}\n }\n </span>\n </div>\n }\n </div>\n\n @if (m.categories.length > 0) {\n <div class=\"ef-email-metrics-card__section\">\n <h4 class=\"ef-email-metrics-card__section-title\">Par cat\u00E9gorie</h4>\n <p-table [value]=\"m.categories\" styleClass=\"ef-email-metrics-card__table\" [scrollable]=\"true\" scrollHeight=\"180px\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Cat\u00E9gorie</th>\n <th class=\"ef-email-metrics-card__num\">Envoy\u00E9s</th>\n <th class=\"ef-email-metrics-card__num\">Ouverts</th>\n <th class=\"ef-email-metrics-card__num\">Cliqu\u00E9s</th>\n <th class=\"ef-email-metrics-card__num\">Rebonds</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-row>\n <tr>\n <td class=\"ef-email-metrics-card__category\">{{ row.category }}</td>\n <td class=\"ef-email-metrics-card__num\">{{ row.sent }}</td>\n <td class=\"ef-email-metrics-card__num\">{{ row.opened }}</td>\n <td class=\"ef-email-metrics-card__num\">{{ row.clicked }}</td>\n <td class=\"ef-email-metrics-card__num\" [class.ef-email-metrics-card__num--danger]=\"row.bounced > 0\">{{ row.bounced }}</td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n }\n\n @if (recentEvents().length > 0) {\n <div class=\"ef-email-metrics-card__section\">\n <h4 class=\"ef-email-metrics-card__section-title\">\u00C9v\u00E9nements r\u00E9cents</h4>\n <p-table [value]=\"recentEvents()\" styleClass=\"ef-email-metrics-card__table\" [scrollable]=\"true\" scrollHeight=\"240px\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Quand</th>\n <th>Destinataire</th>\n <th>Cat\u00E9gorie</th>\n <th>Type</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-row>\n <tr>\n <td class=\"ef-email-metrics-card__when\">{{ row.occurredAt | date: 'dd/MM HH:mm' }}</td>\n <td class=\"ef-email-metrics-card__recipient\">{{ row.recipient }}</td>\n <td>{{ row.category || '\u2014' }}</td>\n <td>\n <p-tag [severity]=\"kindSeverity(row.kind)\" [value]=\"row.kind\" styleClass=\"ef-email-metrics-card__kind\" />\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n }\n } @else {\n <div class=\"ef-email-metrics-card__empty\">\n <p-button label=\"Aucune donn\u00E9e encore\" [text]=\"true\" icon=\"pi pi-envelope\" [disabled]=\"true\" />\n </div>\n }\n</p-card>\n", styles: [":host{display:block}.ef-email-metrics-card__header{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:1rem 1.25rem 0;flex-wrap:wrap}.ef-email-metrics-card__title{margin:0;font-size:1rem;font-weight:600;letter-spacing:-.01em;color:var(--p-text-color)}.ef-email-metrics-card__subtitle{margin:.15rem 0 0;font-size:.8125rem;color:var(--p-text-muted-color)}.ef-email-metrics-card__range :global(.p-selectbutton){border-radius:999px}.ef-email-metrics-card__range :global(.p-selectbutton .p-button){border-radius:999px;padding:.25rem .75rem;font-size:.75rem}.ef-email-metrics-card__kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:.75rem;padding:1rem 0}.ef-email-metrics-card__kpi{display:flex;flex-direction:column;gap:.25rem;padding:.85rem 1rem;border-radius:12px;background:var(--p-surface-50, #f8fafc);border:1px solid var(--p-surface-200, #e2e8f0)}.ef-email-metrics-card__kpi[data-tone=good]{background:color-mix(in srgb,var(--p-green-500, #10b981) 8%,transparent);border-color:color-mix(in srgb,var(--p-green-500, #10b981) 25%,transparent)}.ef-email-metrics-card__kpi[data-tone=warn]{background:color-mix(in srgb,var(--p-orange-500, #f97316) 8%,transparent);border-color:color-mix(in srgb,var(--p-orange-500, #f97316) 25%,transparent)}.ef-email-metrics-card__kpi-label{font-size:.75rem;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:var(--p-text-muted-color)}.ef-email-metrics-card__kpi-value{font-size:1.5rem;font-weight:700;letter-spacing:-.02em;color:var(--p-text-color)}.ef-email-metrics-card__kpi-unit{font-size:.875rem;font-weight:500;margin-left:.125rem;color:var(--p-text-muted-color)}.ef-email-metrics-card__section{margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--p-surface-200, #e2e8f0)}.ef-email-metrics-card__section-title{margin:0 0 .5rem;font-size:.8125rem;font-weight:600;color:var(--p-text-color)}.ef-email-metrics-card__table{font-size:.8125rem}.ef-email-metrics-card__num{text-align:right;font-variant-numeric:tabular-nums}.ef-email-metrics-card__num--danger{color:var(--p-red-600, #dc2626);font-weight:600}.ef-email-metrics-card__category{text-transform:capitalize;font-weight:500}.ef-email-metrics-card__recipient{font-family:JetBrains Mono,ui-monospace,monospace;font-size:.75rem;color:var(--p-text-muted-color)}.ef-email-metrics-card__when{font-variant-numeric:tabular-nums;white-space:nowrap;font-size:.75rem}.ef-email-metrics-card__kind{border-radius:999px;padding:.1rem .6rem;font-size:.7rem;letter-spacing:.02em}.ef-email-metrics-card__empty{padding:2rem 1.25rem;text-align:center;color:var(--p-text-muted-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i5$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i2$4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$5.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$2.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i1$d.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "pipe", type: i1$3.DecimalPipe, name: "number" }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }] });
10505
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.11", type: EfEmailMetricsCardComponent, isStandalone: true, selector: "ef-email-metrics-card", inputs: { metrics: { classPropertyName: "metrics", publicName: "metrics", isSignal: true, isRequired: false, transformFunction: null }, recentEvents: { classPropertyName: "recentEvents", publicName: "recentEvents", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rangeChange: "rangeChange" }, ngImport: i0, template: "<p-card styleClass=\"ef-email-metrics-card\">\n <ng-template pTemplate=\"header\">\n <div class=\"ef-email-metrics-card__header\">\n <div>\n <h3 class=\"ef-email-metrics-card__title\">{{ title() }}</h3>\n @if (metrics(); as m) {\n <p class=\"ef-email-metrics-card__subtitle\">\n {{ m.from | date: 'dd MMM' }} \u2013 {{ m.to | date: 'dd MMM yyyy' }}\n </p>\n }\n </div>\n <p-selectButton\n [options]=\"rangeOptions\"\n [(ngModel)]=\"selectedRange\"\n optionLabel=\"label\"\n optionValue=\"value\"\n styleClass=\"ef-email-metrics-card__range\"\n (onChange)=\"onRangeChange($event.value)\"\n />\n </div>\n </ng-template>\n\n @if (metrics(); as m) {\n <div class=\"ef-email-metrics-card__kpis\">\n @for (kpi of kpis(); track kpi.label) {\n <div class=\"ef-email-metrics-card__kpi\" [attr.data-tone]=\"kpi.tone\">\n <span class=\"ef-email-metrics-card__kpi-label\">{{ kpi.label }}</span>\n <span class=\"ef-email-metrics-card__kpi-value\">\n @if (kpi.rate) {\n {{ kpi.value | number: '1.1-1' : 'fr' }}\n <span class=\"ef-email-metrics-card__kpi-unit\">%</span>\n } @else {\n {{ kpi.value | number: '1.0-0' : 'fr' }}\n }\n </span>\n </div>\n }\n </div>\n\n @if (m.categories.length > 0) {\n <div class=\"ef-email-metrics-card__section\">\n <h4 class=\"ef-email-metrics-card__section-title\">Par cat\u00E9gorie</h4>\n <p-table [value]=\"m.categories\" styleClass=\"ef-email-metrics-card__table\" [scrollable]=\"true\" scrollHeight=\"180px\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Cat\u00E9gorie</th>\n <th class=\"ef-email-metrics-card__num\">Envoy\u00E9s</th>\n <th class=\"ef-email-metrics-card__num\">Ouverts</th>\n <th class=\"ef-email-metrics-card__num\">Cliqu\u00E9s</th>\n <th class=\"ef-email-metrics-card__num\">Rebonds</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-row>\n <tr>\n <td class=\"ef-email-metrics-card__category\">{{ row.category }}</td>\n <td class=\"ef-email-metrics-card__num\">{{ row.sent }}</td>\n <td class=\"ef-email-metrics-card__num\">{{ row.opened }}</td>\n <td class=\"ef-email-metrics-card__num\">{{ row.clicked }}</td>\n <td class=\"ef-email-metrics-card__num\" [class.ef-email-metrics-card__num--danger]=\"row.bounced > 0\">{{ row.bounced }}</td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n }\n\n @if (recentEvents().length > 0) {\n <div class=\"ef-email-metrics-card__section\">\n <h4 class=\"ef-email-metrics-card__section-title\">\u00C9v\u00E9nements r\u00E9cents</h4>\n <p-table [value]=\"recentEvents()\" styleClass=\"ef-email-metrics-card__table\" [scrollable]=\"true\" scrollHeight=\"240px\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Quand</th>\n <th>Destinataire</th>\n <th>Cat\u00E9gorie</th>\n <th>Type</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-row>\n <tr>\n <td class=\"ef-email-metrics-card__when\">{{ row.occurredAt | date: 'dd/MM HH:mm' }}</td>\n <td class=\"ef-email-metrics-card__recipient\">{{ row.recipient }}</td>\n <td>{{ row.category || '\u2014' }}</td>\n <td>\n <p-tag [severity]=\"kindSeverity(row.kind)\" [value]=\"row.kind\" styleClass=\"ef-email-metrics-card__kind\" />\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n }\n } @else {\n <div class=\"ef-email-metrics-card__empty\">\n <p-button label=\"Aucune donn\u00E9e encore\" [text]=\"true\" icon=\"pi pi-envelope\" [disabled]=\"true\" />\n </div>\n }\n</p-card>\n", styles: [":host{display:block}.ef-email-metrics-card__header{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;padding:1rem 1.25rem 0;flex-wrap:wrap}.ef-email-metrics-card__title{margin:0;font-size:1rem;font-weight:600;letter-spacing:-.01em;color:var(--p-text-color)}.ef-email-metrics-card__subtitle{margin:.15rem 0 0;font-size:.8125rem;color:var(--p-text-muted-color)}.ef-email-metrics-card__range :global(.p-selectbutton){border-radius:999px}.ef-email-metrics-card__range :global(.p-selectbutton .p-button){border-radius:999px;padding:.25rem .75rem;font-size:.75rem}.ef-email-metrics-card__kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:.75rem;padding:1rem 0}.ef-email-metrics-card__kpi{display:flex;flex-direction:column;gap:.25rem;padding:.85rem 1rem;border-radius:12px;background:var(--p-surface-50, #f8fafc);border:1px solid var(--p-surface-200, #e2e8f0)}.ef-email-metrics-card__kpi[data-tone=good]{background:color-mix(in srgb,var(--p-green-500, #10b981) 8%,transparent);border-color:color-mix(in srgb,var(--p-green-500, #10b981) 25%,transparent)}.ef-email-metrics-card__kpi[data-tone=warn]{background:color-mix(in srgb,var(--p-orange-500, #f97316) 8%,transparent);border-color:color-mix(in srgb,var(--p-orange-500, #f97316) 25%,transparent)}.ef-email-metrics-card__kpi-label{font-size:.75rem;font-weight:500;text-transform:uppercase;letter-spacing:.06em;color:var(--p-text-muted-color)}.ef-email-metrics-card__kpi-value{font-size:1.5rem;font-weight:700;letter-spacing:-.02em;color:var(--p-text-color)}.ef-email-metrics-card__kpi-unit{font-size:.875rem;font-weight:500;margin-left:.125rem;color:var(--p-text-muted-color)}.ef-email-metrics-card__section{margin-top:.75rem;padding-top:.75rem;border-top:1px solid var(--p-surface-200, #e2e8f0)}.ef-email-metrics-card__section-title{margin:0 0 .5rem;font-size:.8125rem;font-weight:600;color:var(--p-text-color)}.ef-email-metrics-card__table{font-size:.8125rem}.ef-email-metrics-card__num{text-align:right;font-variant-numeric:tabular-nums}.ef-email-metrics-card__num--danger{color:var(--p-red-600, #dc2626);font-weight:600}.ef-email-metrics-card__category{text-transform:capitalize;font-weight:500}.ef-email-metrics-card__recipient{font-family:JetBrains Mono,ui-monospace,monospace;font-size:.75rem;color:var(--p-text-muted-color)}.ef-email-metrics-card__when{font-variant-numeric:tabular-nums;white-space:nowrap;font-size:.75rem}.ef-email-metrics-card__kind{border-radius:999px;padding:.1rem .6rem;font-size:.7rem;letter-spacing:.02em}.ef-email-metrics-card__empty{padding:2rem 1.25rem;text-align:center;color:var(--p-text-muted-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i5$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i2$4.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i5$2.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i1$f.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "pipe", type: i1$3.DecimalPipe, name: "number" }, { kind: "pipe", type: i1$3.DatePipe, name: "date" }] });
10199
10506
  }
10200
10507
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: EfEmailMetricsCardComponent, decorators: [{
10201
10508
  type: Component,
@@ -10218,5 +10525,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
10218
10525
  * Generated bundle index. Do not edit.
10219
10526
  */
10220
10527
 
10221
- export { EF_BADGE_BG_COLORS, EF_BADGE_BG_LIGHT_COLORS, EF_BADGE_BORDER_COLORS, EF_BADGE_DEFAULTS, EF_BADGE_TEXT_COLORS, EF_CHART_PALETTE, EF_DATATABLE_ACTIONS_DEFAULTS, EF_DATATABLE_COLUMN_DEFAULTS, EF_DATATABLE_DEFAULTS, EF_STATUS_COLORS, EF_STATUS_COLOR_ALIASES, EfActivationFilterComponent, EfAppMainComponent, EfAppShellComponent, EfAppShellMobileComponent, EfAppTopComponent, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfBottomSheetComponent, EfBulkBarComponent, EfButtonComponent, EfButtonGroupComponent, EfCardComponent, EfChangeHistoryComponent, EfChartComponent, EfCheckboxComponent, EfClearButtonComponent, EfColumnHeaderTemplateDirective, EfColumnTemplateDirective, EfCompactPipe, EfCurrencyPipe, EfDataCardComponent, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerAdvancedComponent, EfDatepickerComponent, EfDetailToolbarComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfEmptyStateComponent, EfFabComponent, EfFieldsetComponent, EfFilterDrawerComponent, EfFilterPillComponent, EfFormGridComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfModuleRailComponent, EfModuleSideComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfPagerComponent, EfPasswordComponent, EfPdfPreviewComponent, EfPillGroupComponent, EfPresetPillComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfProductTypeaheadComponent, EfProfileChipComponent, EfPulseComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfRankListComponent, EfRowActionsComponent, EfSearchToolbarComponent, EfSelectButtonComponent, EfSelectComponent, EfServerErrorsDirective, EfSkeletonComponent, EfSmartBarComponent, EfStatsComponent, EfStatusChipComponent, EfTabPanelDirective, EfTabsComponent, EfTextareaComponent, EfThemeConfiguratorComponent, EfTimelineComponent, EfToastRegionComponent, EfToggleSwitchComponent, EfToolbarComponent, EfTotalsComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, buildChartConfig, getColumnAlignment, mergeColumnDefaults, resolveEfStatusColor };
10528
+ export { EF_BADGE_BG_COLORS, EF_BADGE_BG_LIGHT_COLORS, EF_BADGE_BORDER_COLORS, EF_BADGE_DEFAULTS, EF_BADGE_TEXT_COLORS, EF_CHART_PALETTE, EF_DATATABLE_ACTIONS_DEFAULTS, EF_DATATABLE_COLUMN_DEFAULTS, EF_DATATABLE_DEFAULTS, EF_STATUS_COLORS, EF_STATUS_COLOR_ALIASES, EfActivationFilterComponent, EfAppMainComponent, EfAppShellComponent, EfAppShellMobileComponent, EfAppTopComponent, EfBadgeComponent, EfBlockUiComponent, EfBlockableDivComponent, EfBottomSheetComponent, EfBuildStampComponent, EfBulkBarComponent, EfButtonComponent, EfButtonGroupComponent, EfCardComponent, EfChangeHistoryComponent, EfChartComponent, EfCheckboxComponent, EfClearButtonComponent, EfColumnHeaderTemplateDirective, EfColumnTemplateDirective, EfCompactPipe, EfConfirmDialogComponent, EfCurrencyPipe, EfDataCardComponent, EfDatatableActionBarComponent, EfDatatableComponent, EfDatepickerAdvancedComponent, EfDatepickerComponent, EfDetailToolbarComponent, EfDialogComponent, EfEmailMetricsCardComponent, EfEmptyStateComponent, EfFabComponent, EfFieldsetComponent, EfFilterDrawerComponent, EfFilterPillComponent, EfFormGridComponent, EfInputNumberComponent, EfInputTextComponent, EfKpiCardComponent, EfLabelComponent, EfModuleRailComponent, EfModuleSideComponent, EfMultiSelectComponent, EfOrderBuilderComponent, EfOrderSummaryComponent, EfPagerComponent, EfPasswordComponent, EfPdfPreviewComponent, EfPillGroupComponent, EfPresetPillComponent, EfPriceDisplayComponent, EfProductCatalogueComponent, EfProductCatalogueFilterComponent, EfProductTypeaheadComponent, EfProfileChipComponent, EfPulseComponent, EfQuantitySelectorComponent, EfQuantityStepperComponent, EfRankListComponent, EfRowActionsComponent, EfSearchToolbarComponent, EfSelectButtonComponent, EfSelectComponent, EfServerErrorsDirective, EfSkeletonComponent, EfSmartBarComponent, EfStatsComponent, EfStatusChipComponent, EfTabPanelDirective, EfTabsComponent, EfTextareaComponent, EfThemeConfiguratorComponent, EfThemeToggleComponent, EfTimelineComponent, EfToastRegionComponent, EfToggleSwitchComponent, EfToolbarComponent, EfTooltipDirective, EfTotalsComponent, OrderEntityHelper, OrderLineItemHelper, TruncatePipe, buildChartConfig, getColumnAlignment, mergeColumnDefaults, resolveEfStatusColor };
10222
10529
  //# sourceMappingURL=elasticias-ui.mjs.map