@eagami/ui 0.11.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,11 @@ import { input, signal, ChangeDetectionStrategy, Component, inject, computed, mo
3
3
  import { NgClass, NgTemplateOutlet } from '@angular/common';
4
4
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
5
5
 
6
+ /**
7
+ * Container for expandable content sections. By default only one item can be
8
+ * open at a time; set `multi` to allow several to stay expanded together.
9
+ * Provides a built-in chevron animation and supports per-item disabling.
10
+ */
6
11
  class AccordionComponent {
7
12
  multi = input(false, ...(ngDevMode ? [{ debugName: "multi" }] : /* istanbul ignore next */ []));
8
13
  expandedItems = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedItems" }] : /* istanbul ignore next */ []));
@@ -71,11 +76,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
71
76
  }]
72
77
  }] });
73
78
 
79
+ /**
80
+ * Single expandable section within an `ea-accordion`. Each item exposes a
81
+ * header button with the supplied `label` and reveals its projected content
82
+ * when expanded. Must be rendered inside an `ea-accordion`.
83
+ */
74
84
  class AccordionItemComponent {
75
85
  accordion = inject(AccordionComponent);
76
86
  value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
77
87
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
78
88
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
89
+ id = input(`ea-accordion-item-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
79
90
  isExpanded = computed(() => this.accordion.isExpanded(this.value()), ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
80
91
  toggle() {
81
92
  if (this.disabled())
@@ -83,12 +94,12 @@ class AccordionItemComponent {
83
94
  this.accordion.toggle(this.value());
84
95
  }
85
96
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AccordionItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
86
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AccordionItemComponent, isStandalone: true, selector: "ea-accordion-item", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-accordion-item\"\n [class.ea-accordion-item--expanded]=\"isExpanded()\"\n [class.ea-accordion-item--disabled]=\"disabled()\">\n <button\n class=\"ea-accordion-item__trigger\"\n type=\"button\"\n [attr.aria-expanded]=\"isExpanded()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\">\n <span class=\"ea-accordion-item__label\">{{ label() }}</span>\n <ea-icon-chevron-down class=\"ea-accordion-item__chevron\" />\n </button>\n @if (isExpanded()) {\n <div\n class=\"ea-accordion-item__content\"\n role=\"region\">\n <ng-content />\n </div>\n }\n</div>\n", styles: [".ea-accordion-item{border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-accordion-item:last-child{border-bottom:none}.ea-accordion-item__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);text-align:left;background:none;border:none;color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-accordion-item__trigger:hover:not(:disabled){background-color:var(--color-bg-subtle)}.ea-accordion-item__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-accordion-item__trigger:disabled{opacity:.5;cursor:not-allowed}.ea-accordion-item__chevron{flex-shrink:0;width:16px;height:16px;color:var(--color-text-secondary);transition:transform var(--duration-normal) var(--ease-out)}.ea-accordion-item--expanded .ea-accordion-item__chevron{transform:rotate(180deg)}.ea-accordion-item__content{padding:0 var(--space-4) var(--space-4);font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-accordion-item--disabled{opacity:.5}\n"], dependencies: [{ kind: "component", type: ChevronDownIconComponent, selector: "ea-icon-chevron-down" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
97
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AccordionItemComponent, isStandalone: true, selector: "ea-accordion-item", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-accordion-item\"\n [class.ea-accordion-item--expanded]=\"isExpanded()\"\n [class.ea-accordion-item--disabled]=\"disabled()\">\n <button\n class=\"ea-accordion-item__trigger\"\n type=\"button\"\n [id]=\"id() + '-trigger'\"\n [attr.aria-expanded]=\"isExpanded()\"\n [attr.aria-controls]=\"id() + '-content'\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\">\n <span class=\"ea-accordion-item__label\">{{ label() }}</span>\n <ea-icon-chevron-down\n class=\"ea-accordion-item__chevron\"\n aria-hidden=\"true\" />\n </button>\n @if (isExpanded()) {\n <div\n class=\"ea-accordion-item__content\"\n role=\"region\"\n [id]=\"id() + '-content'\"\n [attr.aria-labelledby]=\"id() + '-trigger'\">\n <ng-content />\n </div>\n }\n</div>\n", styles: [".ea-accordion-item{border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-accordion-item:last-child{border-bottom:none}.ea-accordion-item__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);text-align:left;background:none;border:none;color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-accordion-item__trigger:hover:not(:disabled){background-color:var(--color-bg-subtle)}.ea-accordion-item__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-accordion-item__trigger:disabled{opacity:.5;cursor:not-allowed}.ea-accordion-item__chevron{flex-shrink:0;width:16px;height:16px;color:var(--color-text-secondary);transition:transform var(--duration-normal) var(--ease-out)}.ea-accordion-item--expanded .ea-accordion-item__chevron{transform:rotate(180deg)}.ea-accordion-item__content{padding:0 var(--space-4) var(--space-4);font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-accordion-item--disabled{opacity:.5}\n"], dependencies: [{ kind: "component", type: ChevronDownIconComponent, selector: "ea-icon-chevron-down" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
87
98
  }
88
99
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AccordionItemComponent, decorators: [{
89
100
  type: Component,
90
- args: [{ selector: 'ea-accordion-item', imports: [ChevronDownIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ea-accordion-item\"\n [class.ea-accordion-item--expanded]=\"isExpanded()\"\n [class.ea-accordion-item--disabled]=\"disabled()\">\n <button\n class=\"ea-accordion-item__trigger\"\n type=\"button\"\n [attr.aria-expanded]=\"isExpanded()\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\">\n <span class=\"ea-accordion-item__label\">{{ label() }}</span>\n <ea-icon-chevron-down class=\"ea-accordion-item__chevron\" />\n </button>\n @if (isExpanded()) {\n <div\n class=\"ea-accordion-item__content\"\n role=\"region\">\n <ng-content />\n </div>\n }\n</div>\n", styles: [".ea-accordion-item{border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-accordion-item:last-child{border-bottom:none}.ea-accordion-item__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);text-align:left;background:none;border:none;color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-accordion-item__trigger:hover:not(:disabled){background-color:var(--color-bg-subtle)}.ea-accordion-item__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-accordion-item__trigger:disabled{opacity:.5;cursor:not-allowed}.ea-accordion-item__chevron{flex-shrink:0;width:16px;height:16px;color:var(--color-text-secondary);transition:transform var(--duration-normal) var(--ease-out)}.ea-accordion-item--expanded .ea-accordion-item__chevron{transform:rotate(180deg)}.ea-accordion-item__content{padding:0 var(--space-4) var(--space-4);font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-accordion-item--disabled{opacity:.5}\n"] }]
91
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
101
+ args: [{ selector: 'ea-accordion-item', imports: [ChevronDownIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ea-accordion-item\"\n [class.ea-accordion-item--expanded]=\"isExpanded()\"\n [class.ea-accordion-item--disabled]=\"disabled()\">\n <button\n class=\"ea-accordion-item__trigger\"\n type=\"button\"\n [id]=\"id() + '-trigger'\"\n [attr.aria-expanded]=\"isExpanded()\"\n [attr.aria-controls]=\"id() + '-content'\"\n [disabled]=\"disabled()\"\n (click)=\"toggle()\">\n <span class=\"ea-accordion-item__label\">{{ label() }}</span>\n <ea-icon-chevron-down\n class=\"ea-accordion-item__chevron\"\n aria-hidden=\"true\" />\n </button>\n @if (isExpanded()) {\n <div\n class=\"ea-accordion-item__content\"\n role=\"region\"\n [id]=\"id() + '-content'\"\n [attr.aria-labelledby]=\"id() + '-trigger'\">\n <ng-content />\n </div>\n }\n</div>\n", styles: [".ea-accordion-item{border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-accordion-item:last-child{border-bottom:none}.ea-accordion-item__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);text-align:left;background:none;border:none;color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-accordion-item__trigger:hover:not(:disabled){background-color:var(--color-bg-subtle)}.ea-accordion-item__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-accordion-item__trigger:disabled{opacity:.5;cursor:not-allowed}.ea-accordion-item__chevron{flex-shrink:0;width:16px;height:16px;color:var(--color-text-secondary);transition:transform var(--duration-normal) var(--ease-out)}.ea-accordion-item--expanded .ea-accordion-item__chevron{transform:rotate(180deg)}.ea-accordion-item__content{padding:0 var(--space-4) var(--space-4);font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-accordion-item--disabled{opacity:.5}\n"] }]
102
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
92
103
 
93
104
  class AlertCircleIconComponent {
94
105
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AlertCircleIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -288,20 +299,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
288
299
  }]
289
300
  }] });
290
301
 
302
+ /**
303
+ * Inline banner for surfacing semantic messages such as success confirmations,
304
+ * warnings, or errors. Optionally dismissible, with a two-way `visible`
305
+ * binding and an automatically chosen ARIA role based on severity.
306
+ */
291
307
  class AlertComponent {
292
308
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
293
309
  dismissible = input(false, ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
294
310
  visible = model(true, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
311
+ /** Fires when the user dismisses the alert via its close button. */
295
312
  dismissed = output();
296
313
  alertClasses = computed(() => ({
297
314
  [`ea-alert--${this.variant()}`]: true,
298
315
  }), ...(ngDevMode ? [{ debugName: "alertClasses" }] : /* istanbul ignore next */ []));
316
+ role = computed(() => {
317
+ const v = this.variant();
318
+ return v === 'error' || v === 'warning' ? 'alert' : 'status';
319
+ }, ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
320
+ /** Hides the alert and emits `dismissed`. */
299
321
  dismiss() {
300
322
  this.visible.set(false);
301
323
  this.dismissed.emit();
302
324
  }
303
325
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
304
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AlertComponent, isStandalone: true, selector: "ea-alert", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", dismissed: "dismissed" }, ngImport: i0, template: "@if (visible()) {\n <div\n class=\"ea-alert\"\n [class.ea-alert--default]=\"variant() === 'default'\"\n [class.ea-alert--success]=\"variant() === 'success'\"\n [class.ea-alert--warning]=\"variant() === 'warning'\"\n [class.ea-alert--error]=\"variant() === 'error'\"\n [class.ea-alert--info]=\"variant() === 'info'\"\n role=\"alert\">\n <span class=\"ea-alert__icon\">\n @switch (variant()) {\n @case ('success') {\n <ea-icon-check />\n }\n @case ('warning') {\n <ea-icon-alert-circle />\n }\n @case ('error') {\n <ea-icon-alert-circle />\n }\n @case ('info') {\n <ea-icon-info />\n }\n @default {\n <ea-icon-info />\n }\n }\n </span>\n <div class=\"ea-alert__content\">\n <ng-content />\n </div>\n @if (dismissible()) {\n <button\n class=\"ea-alert__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"dismiss()\">\n <ea-icon-x />\n </button>\n }\n </div>\n}\n", styles: [".ea-alert{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);border:var(--border-width-thin) solid;border-radius:var(--radius-lg)}.ea-alert--default{background-color:var(--color-bg-subtle);border-color:var(--color-border-default);color:var(--color-text-primary)}.ea-alert--default .ea-alert__icon{color:var(--color-text-secondary)}.ea-alert--success{background-color:var(--color-success-subtle);border-color:var(--color-success-default);color:var(--color-text-primary)}.ea-alert--success .ea-alert__icon{color:var(--color-success-default)}.ea-alert--warning{background-color:var(--color-warning-subtle);border-color:var(--color-warning-default);color:var(--color-text-primary)}.ea-alert--warning .ea-alert__icon{color:var(--color-warning-default)}.ea-alert--error{background-color:var(--color-error-subtle);border-color:var(--color-error-default);color:var(--color-text-primary)}.ea-alert--error .ea-alert__icon{color:var(--color-error-default)}.ea-alert--info{background-color:var(--color-info-subtle);border-color:var(--color-info-default);color:var(--color-text-primary)}.ea-alert--info .ea-alert__icon{color:var(--color-info-default)}.ea-alert__icon{display:flex;flex-shrink:0;width:1.25rem;height:1.25rem;padding-top:1px}.ea-alert__content{flex:1;min-width:0}.ea-alert__close{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;border-radius:var(--radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-alert__close:hover{color:var(--color-text-primary)}.ea-alert__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"], dependencies: [{ kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }, { kind: "component", type: CheckIconComponent, selector: "ea-icon-check" }, { kind: "component", type: InfoIconComponent, selector: "ea-icon-info" }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
326
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AlertComponent, isStandalone: true, selector: "ea-alert", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", dismissed: "dismissed" }, ngImport: i0, template: "@if (visible()) {\n <div\n class=\"ea-alert\"\n [class.ea-alert--default]=\"variant() === 'default'\"\n [class.ea-alert--success]=\"variant() === 'success'\"\n [class.ea-alert--warning]=\"variant() === 'warning'\"\n [class.ea-alert--error]=\"variant() === 'error'\"\n [class.ea-alert--info]=\"variant() === 'info'\"\n [attr.role]=\"role()\">\n <span class=\"ea-alert__icon\">\n @switch (variant()) {\n @case ('success') {\n <ea-icon-check />\n }\n @case ('warning') {\n <ea-icon-alert-circle />\n }\n @case ('error') {\n <ea-icon-alert-circle />\n }\n @case ('info') {\n <ea-icon-info />\n }\n @default {\n <ea-icon-info />\n }\n }\n </span>\n <div class=\"ea-alert__content\">\n <ng-content />\n </div>\n @if (dismissible()) {\n <button\n class=\"ea-alert__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"dismiss()\">\n <ea-icon-x />\n </button>\n }\n </div>\n}\n", styles: [".ea-alert{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);border:var(--border-width-thin) solid;border-radius:var(--radius-lg)}.ea-alert--default{background-color:var(--color-bg-subtle);border-color:var(--color-border-default);color:var(--color-text-primary)}.ea-alert--default .ea-alert__icon{color:var(--color-text-secondary)}.ea-alert--success{background-color:var(--color-success-subtle);border-color:var(--color-success-default);color:var(--color-text-primary)}.ea-alert--success .ea-alert__icon{color:var(--color-success-default)}.ea-alert--warning{background-color:var(--color-warning-subtle);border-color:var(--color-warning-default);color:var(--color-text-primary)}.ea-alert--warning .ea-alert__icon{color:var(--color-warning-default)}.ea-alert--error{background-color:var(--color-error-subtle);border-color:var(--color-error-default);color:var(--color-text-primary)}.ea-alert--error .ea-alert__icon{color:var(--color-error-default)}.ea-alert--info{background-color:var(--color-info-subtle);border-color:var(--color-info-default);color:var(--color-text-primary)}.ea-alert--info .ea-alert__icon{color:var(--color-info-default)}.ea-alert__icon{display:flex;flex-shrink:0;width:1.25rem;height:1.25rem;padding-top:1px}.ea-alert__content{flex:1;min-width:0}.ea-alert__close{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;border-radius:var(--radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-alert__close:hover{color:var(--color-text-primary)}.ea-alert__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"], dependencies: [{ kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }, { kind: "component", type: CheckIconComponent, selector: "ea-icon-check" }, { kind: "component", type: InfoIconComponent, selector: "ea-icon-info" }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
305
327
  }
306
328
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AlertComponent, decorators: [{
307
329
  type: Component,
@@ -310,9 +332,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
310
332
  CheckIconComponent,
311
333
  InfoIconComponent,
312
334
  XIconComponent,
313
- ], template: "@if (visible()) {\n <div\n class=\"ea-alert\"\n [class.ea-alert--default]=\"variant() === 'default'\"\n [class.ea-alert--success]=\"variant() === 'success'\"\n [class.ea-alert--warning]=\"variant() === 'warning'\"\n [class.ea-alert--error]=\"variant() === 'error'\"\n [class.ea-alert--info]=\"variant() === 'info'\"\n role=\"alert\">\n <span class=\"ea-alert__icon\">\n @switch (variant()) {\n @case ('success') {\n <ea-icon-check />\n }\n @case ('warning') {\n <ea-icon-alert-circle />\n }\n @case ('error') {\n <ea-icon-alert-circle />\n }\n @case ('info') {\n <ea-icon-info />\n }\n @default {\n <ea-icon-info />\n }\n }\n </span>\n <div class=\"ea-alert__content\">\n <ng-content />\n </div>\n @if (dismissible()) {\n <button\n class=\"ea-alert__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"dismiss()\">\n <ea-icon-x />\n </button>\n }\n </div>\n}\n", styles: [".ea-alert{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);border:var(--border-width-thin) solid;border-radius:var(--radius-lg)}.ea-alert--default{background-color:var(--color-bg-subtle);border-color:var(--color-border-default);color:var(--color-text-primary)}.ea-alert--default .ea-alert__icon{color:var(--color-text-secondary)}.ea-alert--success{background-color:var(--color-success-subtle);border-color:var(--color-success-default);color:var(--color-text-primary)}.ea-alert--success .ea-alert__icon{color:var(--color-success-default)}.ea-alert--warning{background-color:var(--color-warning-subtle);border-color:var(--color-warning-default);color:var(--color-text-primary)}.ea-alert--warning .ea-alert__icon{color:var(--color-warning-default)}.ea-alert--error{background-color:var(--color-error-subtle);border-color:var(--color-error-default);color:var(--color-text-primary)}.ea-alert--error .ea-alert__icon{color:var(--color-error-default)}.ea-alert--info{background-color:var(--color-info-subtle);border-color:var(--color-info-default);color:var(--color-text-primary)}.ea-alert--info .ea-alert__icon{color:var(--color-info-default)}.ea-alert__icon{display:flex;flex-shrink:0;width:1.25rem;height:1.25rem;padding-top:1px}.ea-alert__content{flex:1;min-width:0}.ea-alert__close{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;border-radius:var(--radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-alert__close:hover{color:var(--color-text-primary)}.ea-alert__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"] }]
335
+ ], template: "@if (visible()) {\n <div\n class=\"ea-alert\"\n [class.ea-alert--default]=\"variant() === 'default'\"\n [class.ea-alert--success]=\"variant() === 'success'\"\n [class.ea-alert--warning]=\"variant() === 'warning'\"\n [class.ea-alert--error]=\"variant() === 'error'\"\n [class.ea-alert--info]=\"variant() === 'info'\"\n [attr.role]=\"role()\">\n <span class=\"ea-alert__icon\">\n @switch (variant()) {\n @case ('success') {\n <ea-icon-check />\n }\n @case ('warning') {\n <ea-icon-alert-circle />\n }\n @case ('error') {\n <ea-icon-alert-circle />\n }\n @case ('info') {\n <ea-icon-info />\n }\n @default {\n <ea-icon-info />\n }\n }\n </span>\n <div class=\"ea-alert__content\">\n <ng-content />\n </div>\n @if (dismissible()) {\n <button\n class=\"ea-alert__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"dismiss()\">\n <ea-icon-x />\n </button>\n }\n </div>\n}\n", styles: [".ea-alert{display:flex;align-items:flex-start;gap:var(--space-3);padding:var(--space-3) var(--space-4);font-size:var(--font-size-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);border:var(--border-width-thin) solid;border-radius:var(--radius-lg)}.ea-alert--default{background-color:var(--color-bg-subtle);border-color:var(--color-border-default);color:var(--color-text-primary)}.ea-alert--default .ea-alert__icon{color:var(--color-text-secondary)}.ea-alert--success{background-color:var(--color-success-subtle);border-color:var(--color-success-default);color:var(--color-text-primary)}.ea-alert--success .ea-alert__icon{color:var(--color-success-default)}.ea-alert--warning{background-color:var(--color-warning-subtle);border-color:var(--color-warning-default);color:var(--color-text-primary)}.ea-alert--warning .ea-alert__icon{color:var(--color-warning-default)}.ea-alert--error{background-color:var(--color-error-subtle);border-color:var(--color-error-default);color:var(--color-text-primary)}.ea-alert--error .ea-alert__icon{color:var(--color-error-default)}.ea-alert--info{background-color:var(--color-info-subtle);border-color:var(--color-info-default);color:var(--color-text-primary)}.ea-alert--info .ea-alert__icon{color:var(--color-info-default)}.ea-alert__icon{display:flex;flex-shrink:0;width:1.25rem;height:1.25rem;padding-top:1px}.ea-alert__content{flex:1;min-width:0}.ea-alert__close{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;border-radius:var(--radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-alert__close:hover{color:var(--color-text-primary)}.ea-alert__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"] }]
314
336
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }, { type: i0.Output, args: ["visibleChange"] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
315
337
 
338
+ /**
339
+ * Text input paired with a filtered suggestion list. Filters options by
340
+ * case-insensitive substring match, supports arrow-key navigation, and
341
+ * implements `ControlValueAccessor` for use with reactive and template-driven
342
+ * forms.
343
+ */
316
344
  class AutocompleteComponent {
317
345
  inputEl = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputEl" }] : /* istanbul ignore next */ []));
318
346
  hostEl = viewChild('hostEl', ...(ngDevMode ? [{ debugName: "hostEl" }] : /* istanbul ignore next */ []));
@@ -325,7 +353,7 @@ class AutocompleteComponent {
325
353
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
326
354
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
327
355
  hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
328
- errorMsg = input(undefined, { ...(ngDevMode ? { debugName: "errorMsg" } : /* istanbul ignore next */ {}), alias: 'error' });
356
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
329
357
  minLength = input(0, ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
330
358
  maxResults = input(10, ...(ngDevMode ? [{ debugName: "maxResults" }] : /* istanbul ignore next */ []));
331
359
  emptyMessage = input('No results', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
@@ -333,11 +361,17 @@ class AutocompleteComponent {
333
361
  // Two-way value binding (current text value in the input)
334
362
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
335
363
  // Outputs
336
- optionSelected = output();
337
- valueChanged = output();
364
+ /** Fires when the user picks an option from the suggestion list. */
365
+ selected = output();
366
+ /** Fires whenever the input text changes, including on free-text edits. */
367
+ changed = output();
368
+ /** Fires when the input receives focus. */
369
+ focused = output();
370
+ /** Fires when the input loses focus. */
371
+ blurred = output();
338
372
  // Internal state
339
373
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
340
- focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
374
+ isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
341
375
  focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
342
376
  _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
343
377
  justSelected = false;
@@ -346,9 +380,9 @@ class AutocompleteComponent {
346
380
  onTouched = () => { };
347
381
  // Computed
348
382
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
349
- resolvedStatus = computed(() => (this.errorMsg() ? 'error' : 'default'), ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
350
- showError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
351
- showHint = computed(() => !!this.hint() && !this.showError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
383
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
384
+ showError = this.hasError;
385
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
352
386
  filteredOptions = computed(() => {
353
387
  const query = this.value().trim().toLowerCase();
354
388
  const allOptions = this.options();
@@ -364,8 +398,8 @@ class AutocompleteComponent {
364
398
  showEmpty = computed(() => this.showList() && this.filteredOptions().length === 0, ...(ngDevMode ? [{ debugName: "showEmpty" }] : /* istanbul ignore next */ []));
365
399
  wrapperClasses = computed(() => ({
366
400
  [`ea-autocomplete__wrapper--${this.size()}`]: true,
367
- [`ea-autocomplete__wrapper--${this.resolvedStatus()}`]: true,
368
- 'ea-autocomplete__wrapper--focused': this.focused(),
401
+ 'ea-autocomplete__wrapper--error': this.hasError(),
402
+ 'ea-autocomplete__wrapper--focused': this.isFocused(),
369
403
  'ea-autocomplete__wrapper--disabled': this.isDisabled(),
370
404
  }), ...(ngDevMode ? [{ debugName: "wrapperClasses" }] : /* istanbul ignore next */ []));
371
405
  // ControlValueAccessor
@@ -386,12 +420,13 @@ class AutocompleteComponent {
386
420
  const next = event.target.value;
387
421
  this.value.set(next);
388
422
  this.onChange(next);
389
- this.valueChanged.emit(next);
423
+ this.changed.emit(next);
390
424
  this.isOpen.set(true);
391
425
  this.focusedIndex.set(-1);
392
426
  }
393
- handleFocus() {
394
- this.focused.set(true);
427
+ handleFocus(event) {
428
+ this.isFocused.set(true);
429
+ this.focused.emit(event);
395
430
  if (this.justSelected) {
396
431
  this.justSelected = false;
397
432
  return;
@@ -400,9 +435,10 @@ class AutocompleteComponent {
400
435
  this.isOpen.set(true);
401
436
  }
402
437
  }
403
- handleBlur() {
404
- this.focused.set(false);
438
+ handleBlur(event) {
439
+ this.isFocused.set(false);
405
440
  this.onTouched();
441
+ this.blurred.emit(event);
406
442
  }
407
443
  handleKeydown(event) {
408
444
  if (this.isDisabled() || this.readonly())
@@ -439,21 +475,27 @@ class AutocompleteComponent {
439
475
  break;
440
476
  }
441
477
  }
478
+ /** Programmatically selects the given option, updating the value and closing the list. */
442
479
  selectOption(option) {
443
480
  if (option.disabled || this.isDisabled())
444
481
  return;
445
482
  this.value.set(option.label);
446
483
  this.onChange(option.label);
447
- this.valueChanged.emit(option.label);
448
- this.optionSelected.emit(option);
484
+ this.changed.emit(option.label);
485
+ this.selected.emit(option);
449
486
  this.justSelected = true;
450
487
  this.close();
451
488
  this.inputEl()?.nativeElement.focus();
452
489
  }
490
+ /** Closes the suggestion list without changing the current value. */
453
491
  close() {
454
492
  this.isOpen.set(false);
455
493
  this.focusedIndex.set(-1);
456
494
  }
495
+ /** Moves keyboard focus to the underlying text input. */
496
+ focus() {
497
+ this.inputEl()?.nativeElement.focus();
498
+ }
457
499
  moveFocus(delta) {
458
500
  const opts = this.filteredOptions();
459
501
  if (opts.length === 0)
@@ -475,13 +517,13 @@ class AutocompleteComponent {
475
517
  }
476
518
  }
477
519
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
478
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AutocompleteComponent, isStandalone: true, selector: "ea-autocomplete", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxResults: { classPropertyName: "maxResults", publicName: "maxResults", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", optionSelected: "optionSelected", valueChanged: "valueChanged" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
520
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AutocompleteComponent, isStandalone: true, selector: "ea-autocomplete", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxResults: { classPropertyName: "maxResults", publicName: "maxResults", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", selected: "selected", changed: "changed", focused: "focused", blurred: "blurred" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
479
521
  {
480
522
  provide: NG_VALUE_ACCESSOR,
481
523
  useExisting: forwardRef(() => AutocompleteComponent),
482
524
  multi: true,
483
525
  },
484
- ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }, { propertyName: "hostEl", first: true, predicate: ["hostEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #hostEl\n class=\"ea-autocomplete\">\n @if (label()) {\n <label\n class=\"ea-autocomplete__label\"\n [for]=\"id()\"\n [class.ea-autocomplete__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-autocomplete__wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <span class=\"ea-autocomplete__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-autocomplete__input\"\n type=\"text\"\n autocomplete=\"off\"\n role=\"combobox\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"id() + '-listbox'\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n (keydown)=\"handleKeydown($event)\" />\n\n <span class=\"ea-autocomplete__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n </div>\n\n @if (showList()) {\n <ul\n class=\"ea-autocomplete__listbox\"\n role=\"listbox\"\n [id]=\"id() + '-listbox'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"ea-autocomplete__option\"\n role=\"option\"\n [id]=\"id() + '-option-' + i\"\n [class.ea-autocomplete__option--focused]=\"i === focusedIndex()\"\n [class.ea-autocomplete__option--disabled]=\"option.disabled\"\n [attr.aria-selected]=\"i === focusedIndex()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (mousedown)=\"selectOption(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n @if (showEmpty()) {\n <li\n class=\"ea-autocomplete__empty\"\n role=\"presentation\">\n {{ emptyMessage() }}\n </li>\n }\n </ul>\n }\n\n @if (showError()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-autocomplete{position:relative;display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-autocomplete__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-autocomplete__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-autocomplete__wrapper{display:flex;align-items:center;gap:var(--space-2);width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);transition:var(--transition-colors),var(--transition-shadow)}.ea-autocomplete__wrapper--sm{padding:var(--space-1-5) var(--space-2);min-height:2rem}.ea-autocomplete__wrapper--sm .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--md{padding:var(--space-2) var(--space-3);min-height:2.5rem}.ea-autocomplete__wrapper--md .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--lg{padding:var(--space-2-5) var(--space-4);min-height:3rem}.ea-autocomplete__wrapper--lg .ea-autocomplete__input{font-size:var(--font-size-md)}.ea-autocomplete__wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-autocomplete__wrapper--error{border-color:var(--color-error-default)}.ea-autocomplete__wrapper--error.ea-autocomplete__wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-autocomplete__wrapper--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-autocomplete__input{flex:1;min-width:0;padding:0;border:none;background:transparent;font-family:var(--font-family-sans);color:var(--color-text-primary);outline:none}.ea-autocomplete__input::placeholder{color:var(--color-text-tertiary)}.ea-autocomplete__input:disabled{cursor:not-allowed}.ea-autocomplete__prefix,.ea-autocomplete__suffix{display:flex;flex-shrink:0;align-items:center;color:var(--color-text-secondary)}.ea-autocomplete__prefix:empty,.ea-autocomplete__suffix:empty{display:none}.ea-autocomplete__listbox{position:absolute;z-index:var(--z-index-dropdown);top:100%;left:0;right:0;max-height:15rem;padding:var(--space-1) 0;margin:var(--space-1) 0 0;overflow-y:auto;list-style:none;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}.ea-autocomplete__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-autocomplete__option--focused{background-color:var(--color-bg-muted)}.ea-autocomplete__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-autocomplete__empty{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-style:italic;color:var(--color-text-tertiary)}.ea-autocomplete__message{display:flex;align-items:center;gap:var(--space-1);margin:0;font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-autocomplete__message--hint{color:var(--color-text-secondary)}.ea-autocomplete__message--error{color:var(--color-error-default)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
526
+ ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }, { propertyName: "hostEl", first: true, predicate: ["hostEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #hostEl\n class=\"ea-autocomplete\">\n @if (label()) {\n <label\n class=\"ea-autocomplete__label\"\n [for]=\"id()\"\n [class.ea-autocomplete__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-autocomplete__wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <span class=\"ea-autocomplete__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-autocomplete__input\"\n type=\"text\"\n autocomplete=\"off\"\n role=\"combobox\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"id() + '-listbox'\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeydown($event)\" />\n\n <span class=\"ea-autocomplete__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n </div>\n\n @if (showList()) {\n <ul\n class=\"ea-autocomplete__listbox\"\n role=\"listbox\"\n [id]=\"id() + '-listbox'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"ea-autocomplete__option\"\n role=\"option\"\n [id]=\"id() + '-option-' + i\"\n [class.ea-autocomplete__option--focused]=\"i === focusedIndex()\"\n [class.ea-autocomplete__option--disabled]=\"option.disabled\"\n [attr.aria-selected]=\"i === focusedIndex()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (mousedown)=\"selectOption(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n @if (showEmpty()) {\n <li\n class=\"ea-autocomplete__empty\"\n role=\"presentation\">\n {{ emptyMessage() }}\n </li>\n }\n </ul>\n }\n\n @if (showError()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-autocomplete{position:relative;display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-autocomplete__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-autocomplete__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-autocomplete__wrapper{display:flex;align-items:center;gap:var(--space-2);width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);transition:var(--transition-colors),var(--transition-shadow)}.ea-autocomplete__wrapper--sm{padding:var(--space-1-5) var(--space-2);min-height:2rem}.ea-autocomplete__wrapper--sm .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--md{padding:var(--space-2) var(--space-3);min-height:2.5rem}.ea-autocomplete__wrapper--md .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--lg{padding:var(--space-2-5) var(--space-4);min-height:3rem}.ea-autocomplete__wrapper--lg .ea-autocomplete__input{font-size:var(--font-size-md)}.ea-autocomplete__wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-autocomplete__wrapper--error{border-color:var(--color-error-default)}.ea-autocomplete__wrapper--error.ea-autocomplete__wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-autocomplete__wrapper--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-autocomplete__input{flex:1;min-width:0;padding:0;border:none;background:transparent;font-family:var(--font-family-sans);color:var(--color-text-primary);outline:none}.ea-autocomplete__input::placeholder{color:var(--color-text-tertiary)}.ea-autocomplete__input:disabled{cursor:not-allowed}.ea-autocomplete__prefix,.ea-autocomplete__suffix{display:flex;flex-shrink:0;align-items:center;color:var(--color-text-secondary)}.ea-autocomplete__prefix:empty,.ea-autocomplete__suffix:empty{display:none}.ea-autocomplete__listbox{position:absolute;z-index:var(--z-index-dropdown);top:100%;left:0;right:0;max-height:15rem;padding:var(--space-1) 0;margin:var(--space-1) 0 0;overflow-y:auto;list-style:none;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}.ea-autocomplete__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-autocomplete__option--focused{background-color:var(--color-bg-muted)}.ea-autocomplete__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-autocomplete__empty{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-style:italic;color:var(--color-text-tertiary)}.ea-autocomplete__message{display:flex;align-items:center;gap:var(--space-1);margin:0;font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-autocomplete__message--hint{color:var(--color-text-secondary)}.ea-autocomplete__message--error{color:var(--color-error-default)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
485
527
  }
486
528
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AutocompleteComponent, decorators: [{
487
529
  type: Component,
@@ -491,8 +533,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
491
533
  useExisting: forwardRef(() => AutocompleteComponent),
492
534
  multi: true,
493
535
  },
494
- ], template: "<div\n #hostEl\n class=\"ea-autocomplete\">\n @if (label()) {\n <label\n class=\"ea-autocomplete__label\"\n [for]=\"id()\"\n [class.ea-autocomplete__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-autocomplete__wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <span class=\"ea-autocomplete__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-autocomplete__input\"\n type=\"text\"\n autocomplete=\"off\"\n role=\"combobox\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"id() + '-listbox'\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n (keydown)=\"handleKeydown($event)\" />\n\n <span class=\"ea-autocomplete__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n </div>\n\n @if (showList()) {\n <ul\n class=\"ea-autocomplete__listbox\"\n role=\"listbox\"\n [id]=\"id() + '-listbox'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"ea-autocomplete__option\"\n role=\"option\"\n [id]=\"id() + '-option-' + i\"\n [class.ea-autocomplete__option--focused]=\"i === focusedIndex()\"\n [class.ea-autocomplete__option--disabled]=\"option.disabled\"\n [attr.aria-selected]=\"i === focusedIndex()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (mousedown)=\"selectOption(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n @if (showEmpty()) {\n <li\n class=\"ea-autocomplete__empty\"\n role=\"presentation\">\n {{ emptyMessage() }}\n </li>\n }\n </ul>\n }\n\n @if (showError()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-autocomplete{position:relative;display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-autocomplete__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-autocomplete__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-autocomplete__wrapper{display:flex;align-items:center;gap:var(--space-2);width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);transition:var(--transition-colors),var(--transition-shadow)}.ea-autocomplete__wrapper--sm{padding:var(--space-1-5) var(--space-2);min-height:2rem}.ea-autocomplete__wrapper--sm .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--md{padding:var(--space-2) var(--space-3);min-height:2.5rem}.ea-autocomplete__wrapper--md .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--lg{padding:var(--space-2-5) var(--space-4);min-height:3rem}.ea-autocomplete__wrapper--lg .ea-autocomplete__input{font-size:var(--font-size-md)}.ea-autocomplete__wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-autocomplete__wrapper--error{border-color:var(--color-error-default)}.ea-autocomplete__wrapper--error.ea-autocomplete__wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-autocomplete__wrapper--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-autocomplete__input{flex:1;min-width:0;padding:0;border:none;background:transparent;font-family:var(--font-family-sans);color:var(--color-text-primary);outline:none}.ea-autocomplete__input::placeholder{color:var(--color-text-tertiary)}.ea-autocomplete__input:disabled{cursor:not-allowed}.ea-autocomplete__prefix,.ea-autocomplete__suffix{display:flex;flex-shrink:0;align-items:center;color:var(--color-text-secondary)}.ea-autocomplete__prefix:empty,.ea-autocomplete__suffix:empty{display:none}.ea-autocomplete__listbox{position:absolute;z-index:var(--z-index-dropdown);top:100%;left:0;right:0;max-height:15rem;padding:var(--space-1) 0;margin:var(--space-1) 0 0;overflow-y:auto;list-style:none;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}.ea-autocomplete__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-autocomplete__option--focused{background-color:var(--color-bg-muted)}.ea-autocomplete__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-autocomplete__empty{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-style:italic;color:var(--color-text-tertiary)}.ea-autocomplete__message{display:flex;align-items:center;gap:var(--space-1);margin:0;font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-autocomplete__message--hint{color:var(--color-text-secondary)}.ea-autocomplete__message--error{color:var(--color-error-default)}\n"] }]
495
- }], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], hostEl: [{ type: i0.ViewChild, args: ['hostEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxResults: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxResults", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }], onDocumentClick: [{
536
+ ], template: "<div\n #hostEl\n class=\"ea-autocomplete\">\n @if (label()) {\n <label\n class=\"ea-autocomplete__label\"\n [for]=\"id()\"\n [class.ea-autocomplete__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-autocomplete__wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <span class=\"ea-autocomplete__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-autocomplete__input\"\n type=\"text\"\n autocomplete=\"off\"\n role=\"combobox\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-controls]=\"id() + '-listbox'\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"\n (keydown)=\"handleKeydown($event)\" />\n\n <span class=\"ea-autocomplete__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n </div>\n\n @if (showList()) {\n <ul\n class=\"ea-autocomplete__listbox\"\n role=\"listbox\"\n [id]=\"id() + '-listbox'\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <li\n class=\"ea-autocomplete__option\"\n role=\"option\"\n [id]=\"id() + '-option-' + i\"\n [class.ea-autocomplete__option--focused]=\"i === focusedIndex()\"\n [class.ea-autocomplete__option--disabled]=\"option.disabled\"\n [attr.aria-selected]=\"i === focusedIndex()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (mousedown)=\"selectOption(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n @if (showEmpty()) {\n <li\n class=\"ea-autocomplete__empty\"\n role=\"presentation\">\n {{ emptyMessage() }}\n </li>\n }\n </ul>\n }\n\n @if (showError()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-autocomplete__message ea-autocomplete__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-autocomplete{position:relative;display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-autocomplete__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-autocomplete__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-autocomplete__wrapper{display:flex;align-items:center;gap:var(--space-2);width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);transition:var(--transition-colors),var(--transition-shadow)}.ea-autocomplete__wrapper--sm{padding:var(--space-1-5) var(--space-2);min-height:2rem}.ea-autocomplete__wrapper--sm .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--md{padding:var(--space-2) var(--space-3);min-height:2.5rem}.ea-autocomplete__wrapper--md .ea-autocomplete__input{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--lg{padding:var(--space-2-5) var(--space-4);min-height:3rem}.ea-autocomplete__wrapper--lg .ea-autocomplete__input{font-size:var(--font-size-md)}.ea-autocomplete__wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-autocomplete__wrapper--error{border-color:var(--color-error-default)}.ea-autocomplete__wrapper--error.ea-autocomplete__wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-autocomplete__wrapper--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-autocomplete__input{flex:1;min-width:0;padding:0;border:none;background:transparent;font-family:var(--font-family-sans);color:var(--color-text-primary);outline:none}.ea-autocomplete__input::placeholder{color:var(--color-text-tertiary)}.ea-autocomplete__input:disabled{cursor:not-allowed}.ea-autocomplete__prefix,.ea-autocomplete__suffix{display:flex;flex-shrink:0;align-items:center;color:var(--color-text-secondary)}.ea-autocomplete__prefix:empty,.ea-autocomplete__suffix:empty{display:none}.ea-autocomplete__listbox{position:absolute;z-index:var(--z-index-dropdown);top:100%;left:0;right:0;max-height:15rem;padding:var(--space-1) 0;margin:var(--space-1) 0 0;overflow-y:auto;list-style:none;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}.ea-autocomplete__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-autocomplete__option--focused{background-color:var(--color-bg-muted)}.ea-autocomplete__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-autocomplete__empty{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-style:italic;color:var(--color-text-tertiary)}.ea-autocomplete__message{display:flex;align-items:center;gap:var(--space-1);margin:0;font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-autocomplete__message--hint{color:var(--color-text-secondary)}.ea-autocomplete__message--error{color:var(--color-error-default)}\n"] }]
537
+ }], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], hostEl: [{ type: i0.ViewChild, args: ['hostEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxResults: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxResults", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], selected: [{ type: i0.Output, args: ["selected"] }], changed: [{ type: i0.Output, args: ["changed"] }], focused: [{ type: i0.Output, args: ["focused"] }], blurred: [{ type: i0.Output, args: ["blurred"] }], onDocumentClick: [{
496
538
  type: HostListener,
497
539
  args: ['document:click', ['$event']]
498
540
  }] } });
@@ -791,6 +833,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
791
833
  }]
792
834
  }] });
793
835
 
836
+ /**
837
+ * Loading placeholder rendered as a pulsing block in one of three shapes.
838
+ * Honours `prefers-reduced-motion` by suppressing the pulse animation when
839
+ * the user has expressed that preference.
840
+ */
794
841
  class SkeletonComponent {
795
842
  variant = input('text', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
796
843
  width = input(undefined, ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
@@ -816,20 +863,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
816
863
  args: [{ selector: 'ea-skeleton', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ea-skeleton\"\n [class.ea-skeleton--text]=\"variant() === 'text'\"\n [class.ea-skeleton--circle]=\"variant() === 'circle'\"\n [class.ea-skeleton--rect]=\"variant() === 'rect'\"\n [class.ea-skeleton--animated]=\"animated()\"\n [style]=\"hostStyles()\"\n aria-hidden=\"true\">\n</div>\n", styles: [".ea-skeleton{display:block;background-color:var(--color-bg-muted);border-radius:var(--radius-md)}.ea-skeleton--text{width:100%;height:1rem;border-radius:var(--radius-sm)}.ea-skeleton--circle{width:2.5rem;height:2.5rem;border-radius:var(--radius-full)}.ea-skeleton--rect{width:100%;height:6rem}.ea-skeleton--animated{animation:ea-skeleton-pulse 1.5s ease-in-out infinite}@keyframes ea-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}@media(prefers-reduced-motion:reduce){.ea-skeleton--animated{animation:none}}\n"] }]
817
864
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], animated: [{ type: i0.Input, args: [{ isSignal: true, alias: "animated", required: false }] }] } });
818
865
 
866
+ /**
867
+ * Attaches a positioned tooltip to its host element. Shows on hover and
868
+ * focus, hides on leave/blur or Escape, and wires up `aria-describedby` so
869
+ * the tooltip text is announced to assistive technology.
870
+ */
819
871
  class TooltipDirective {
820
872
  el = inject(ElementRef);
821
873
  renderer = inject(Renderer2);
822
874
  eaTooltip = input.required(...(ngDevMode ? [{ debugName: "eaTooltip" }] : /* istanbul ignore next */ []));
823
875
  tooltipPosition = input('top', ...(ngDevMode ? [{ debugName: "tooltipPosition" }] : /* istanbul ignore next */ []));
824
876
  tooltipEl = null;
877
+ tooltipId = `ea-tooltip-${Math.random().toString(36).slice(2, 9)}`;
825
878
  showHandler = () => this.show();
826
879
  hideHandler = () => this.hide();
880
+ keydownHandler = (event) => {
881
+ if (event.key === 'Escape' && this.tooltipEl) {
882
+ this.hide();
883
+ }
884
+ };
827
885
  constructor() {
828
886
  const native = this.el.nativeElement;
829
887
  native.addEventListener('mouseenter', this.showHandler);
830
888
  native.addEventListener('mouseleave', this.hideHandler);
831
889
  native.addEventListener('focus', this.showHandler);
832
890
  native.addEventListener('blur', this.hideHandler);
891
+ native.addEventListener('keydown', this.keydownHandler);
833
892
  }
834
893
  ngOnDestroy() {
835
894
  const native = this.el.nativeElement;
@@ -837,6 +896,7 @@ class TooltipDirective {
837
896
  native.removeEventListener('mouseleave', this.hideHandler);
838
897
  native.removeEventListener('focus', this.showHandler);
839
898
  native.removeEventListener('blur', this.hideHandler);
899
+ native.removeEventListener('keydown', this.keydownHandler);
840
900
  this.hide();
841
901
  }
842
902
  show() {
@@ -845,14 +905,37 @@ class TooltipDirective {
845
905
  this.tooltipEl = this.renderer.createElement('div');
846
906
  this.renderer.addClass(this.tooltipEl, 'ea-tooltip');
847
907
  this.renderer.addClass(this.tooltipEl, `ea-tooltip--${this.tooltipPosition()}`);
908
+ this.renderer.setAttribute(this.tooltipEl, 'role', 'tooltip');
909
+ this.renderer.setAttribute(this.tooltipEl, 'id', this.tooltipId);
848
910
  this.tooltipEl.textContent = this.eaTooltip();
849
911
  this.renderer.appendChild(document.body, this.tooltipEl);
912
+ this.appendDescribedBy();
850
913
  this.positionTooltip();
851
914
  }
852
915
  hide() {
853
916
  if (this.tooltipEl) {
854
917
  this.tooltipEl.remove();
855
918
  this.tooltipEl = null;
919
+ this.removeDescribedBy();
920
+ }
921
+ }
922
+ appendDescribedBy() {
923
+ const native = this.el.nativeElement;
924
+ const existing = (native.getAttribute('aria-describedby') ?? '').trim();
925
+ const tokens = existing ? existing.split(/\s+/) : [];
926
+ if (!tokens.includes(this.tooltipId))
927
+ tokens.push(this.tooltipId);
928
+ this.renderer.setAttribute(native, 'aria-describedby', tokens.join(' '));
929
+ }
930
+ removeDescribedBy() {
931
+ const native = this.el.nativeElement;
932
+ const existing = (native.getAttribute('aria-describedby') ?? '').trim();
933
+ const tokens = existing.split(/\s+/).filter((t) => t && t !== this.tooltipId);
934
+ if (tokens.length) {
935
+ this.renderer.setAttribute(native, 'aria-describedby', tokens.join(' '));
936
+ }
937
+ else {
938
+ this.renderer.removeAttribute(native, 'aria-describedby');
856
939
  }
857
940
  }
858
941
  positionTooltip() {
@@ -894,6 +977,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
894
977
  }]
895
978
  }], ctorParameters: () => [], propDecorators: { eaTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "eaTooltip", required: true }] }], tooltipPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltipPosition", required: false }] }] } });
896
979
 
980
+ /**
981
+ * Canvas-based image editor for cropping avatars. Supports drag-and-drop
982
+ * upload, mouse/touch panning, zoom via slider or scroll wheel, and exports
983
+ * the cropped image as either a `Blob` or a data URL.
984
+ */
897
985
  class AvatarEditorComponent {
898
986
  canvasEl = viewChild('canvasEl', ...(ngDevMode ? [{ debugName: "canvasEl" }] : /* istanbul ignore next */ []));
899
987
  fileInputEl = viewChild('fileInputEl', ...(ngDevMode ? [{ debugName: "fileInputEl" }] : /* istanbul ignore next */ []));
@@ -908,11 +996,16 @@ class AvatarEditorComponent {
908
996
  exportQuality = input(0.92, ...(ngDevMode ? [{ debugName: "exportQuality" }] : /* istanbul ignore next */ []));
909
997
  exportType = input('image/png', ...(ngDevMode ? [{ debugName: "exportType" }] : /* istanbul ignore next */ []));
910
998
  cropState = input(...(ngDevMode ? [undefined, { debugName: "cropState" }] : /* istanbul ignore next */ []));
999
+ /** Fires when the user finalises a crop via {@link exportCrop}; payload contains both `Blob` and data URL. */
911
1000
  cropped = output();
1001
+ /** Fires when a file is chosen from disk or dropped onto the editor. */
912
1002
  fileSelected = output();
1003
+ /** Fires when the current image is cleared via the remove control. */
913
1004
  removed = output();
914
- fileError = output();
915
- cropStateChange = output();
1005
+ /** Fires with a human-readable message when validation fails (wrong type, oversized file, etc.). */
1006
+ errored = output();
1007
+ /** Fires whenever the user pans or zooms the image; useful for persisting in-progress crops. */
1008
+ cropStateChanged = output();
916
1009
  hasImage = signal(false, ...(ngDevMode ? [{ debugName: "hasImage" }] : /* istanbul ignore next */ []));
917
1010
  isDragOver = signal(false, ...(ngDevMode ? [{ debugName: "isDragOver" }] : /* istanbul ignore next */ []));
918
1011
  isAtOriginal = signal(false, ...(ngDevMode ? [{ debugName: "isAtOriginal" }] : /* istanbul ignore next */ []));
@@ -988,6 +1081,7 @@ class AvatarEditorComponent {
988
1081
  this.loadFile(file);
989
1082
  input.value = '';
990
1083
  }
1084
+ /** Opens the native file picker dialog. */
991
1085
  openFilePicker() {
992
1086
  this.fileInputEl()?.nativeElement.click();
993
1087
  }
@@ -1074,6 +1168,48 @@ class AvatarEditorComponent {
1074
1168
  const delta = event.deltaY > 0 ? -0.1 : 0.1;
1075
1169
  this.setZoom(this.zoom() + delta);
1076
1170
  }
1171
+ onCanvasKeydown(event) {
1172
+ if (!this.hasImage() || this.isLoading())
1173
+ return;
1174
+ const step = event.shiftKey ? 20 : 5;
1175
+ let handled = false;
1176
+ switch (event.key) {
1177
+ case 'ArrowLeft':
1178
+ this.offsetX += step;
1179
+ handled = true;
1180
+ break;
1181
+ case 'ArrowRight':
1182
+ this.offsetX -= step;
1183
+ handled = true;
1184
+ break;
1185
+ case 'ArrowUp':
1186
+ this.offsetY += step;
1187
+ handled = true;
1188
+ break;
1189
+ case 'ArrowDown':
1190
+ this.offsetY -= step;
1191
+ handled = true;
1192
+ break;
1193
+ case '+':
1194
+ case '=':
1195
+ this.setZoom(this.zoom() + 0.1);
1196
+ event.preventDefault();
1197
+ return;
1198
+ case '-':
1199
+ case '_':
1200
+ this.setZoom(this.zoom() - 0.1);
1201
+ event.preventDefault();
1202
+ return;
1203
+ }
1204
+ if (handled) {
1205
+ event.preventDefault();
1206
+ this.isAtOriginal.set(false);
1207
+ this.clampOffset();
1208
+ this.draw();
1209
+ this.emitCropStateChange();
1210
+ }
1211
+ }
1212
+ /** Sets the zoom level, clamped to the configured `minZoom`/`maxZoom` range. */
1077
1213
  setZoom(value) {
1078
1214
  this.isAtOriginal.set(false);
1079
1215
  const clamped = Math.min(this.maxZoom(), Math.max(this.minZoom(), value));
@@ -1086,6 +1222,7 @@ class AvatarEditorComponent {
1086
1222
  const value = parseFloat(event.target.value);
1087
1223
  this.setZoom(value);
1088
1224
  }
1225
+ /** Clears the loaded image and resets pan/zoom to defaults. */
1089
1226
  removeImage() {
1090
1227
  this.image = null;
1091
1228
  this.hasImage.set(false);
@@ -1097,6 +1234,7 @@ class AvatarEditorComponent {
1097
1234
  this.isAtOriginal.set(this.originalCaptured && !this.originalImage);
1098
1235
  this.removed.emit();
1099
1236
  }
1237
+ /** Marks the current image and crop state as the baseline for {@link revertImage}. */
1100
1238
  captureOriginal() {
1101
1239
  this.originalCaptured = true;
1102
1240
  this.originalImage = this.image;
@@ -1105,6 +1243,7 @@ class AvatarEditorComponent {
1105
1243
  : null;
1106
1244
  this.isAtOriginal.set(true);
1107
1245
  }
1246
+ /** Restores the image and crop state captured by the most recent {@link captureOriginal}. */
1108
1247
  revertImage() {
1109
1248
  if (!this.originalCaptured)
1110
1249
  return;
@@ -1135,6 +1274,7 @@ class AvatarEditorComponent {
1135
1274
  this.isAtOriginal.set(true);
1136
1275
  }
1137
1276
  }
1277
+ /** Renders the current crop to an offscreen canvas, emits `cropped`, and resolves with the resulting `Blob`. */
1138
1278
  exportCrop() {
1139
1279
  return new Promise((resolve, reject) => {
1140
1280
  if (!this.image) {
@@ -1205,12 +1345,12 @@ class AvatarEditorComponent {
1205
1345
  }
1206
1346
  loadFile(file) {
1207
1347
  if (!file.type.startsWith('image/')) {
1208
- this.fileError.emit('File must be an image');
1348
+ this.errored.emit('File must be an image');
1209
1349
  return;
1210
1350
  }
1211
1351
  if (file.size > this.maxFileSize()) {
1212
1352
  const maxMb = Math.round(this.maxFileSize() / (1024 * 1024));
1213
- this.fileError.emit(`File exceeds ${maxMb} MB limit`);
1353
+ this.errored.emit(`File exceeds ${maxMb} MB limit`);
1214
1354
  return;
1215
1355
  }
1216
1356
  this.isAtOriginal.set(false);
@@ -1305,7 +1445,7 @@ class AvatarEditorComponent {
1305
1445
  emitCropStateChange() {
1306
1446
  if (this._suppressCropStateEmit)
1307
1447
  return;
1308
- this.cropStateChange.emit({
1448
+ this.cropStateChanged.emit({
1309
1449
  zoom: this.zoom(),
1310
1450
  offsetX: this.offsetX,
1311
1451
  offsetY: this.offsetY,
@@ -1319,7 +1459,7 @@ class AvatarEditorComponent {
1319
1459
  ctx.clearRect(0, 0, canvas.width, canvas.height);
1320
1460
  }
1321
1461
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AvatarEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1322
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AvatarEditorComponent, isStandalone: true, selector: "ea-avatar-editor", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: false, transformFunction: null }, currentSrc: { classPropertyName: "currentSrc", publicName: "currentSrc", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, minZoom: { classPropertyName: "minZoom", publicName: "minZoom", isSignal: true, isRequired: false, transformFunction: null }, maxZoom: { classPropertyName: "maxZoom", publicName: "maxZoom", isSignal: true, isRequired: false, transformFunction: null }, exportQuality: { classPropertyName: "exportQuality", publicName: "exportQuality", isSignal: true, isRequired: false, transformFunction: null }, exportType: { classPropertyName: "exportType", publicName: "exportType", isSignal: true, isRequired: false, transformFunction: null }, cropState: { classPropertyName: "cropState", publicName: "cropState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cropped: "cropped", fileSelected: "fileSelected", removed: "removed", fileError: "fileError", cropStateChange: "cropStateChange" }, viewQueries: [{ propertyName: "canvasEl", first: true, predicate: ["canvasEl"], descendants: true, isSignal: true }, { propertyName: "fileInputEl", first: true, predicate: ["fileInputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ea-avatar-editor\"\n [ngClass]=\"hostClasses()\">\n <input\n #fileInputEl\n type=\"file\"\n class=\"ea-avatar-editor__file-input\"\n [accept]=\"accept()\"\n (change)=\"onFileSelected($event)\" />\n\n @if (!hasImage() && !isLoading()) {\n <button\n type=\"button\"\n class=\"ea-avatar-editor__dropzone\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (click)=\"openFilePicker()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <ea-icon-upload class=\"ea-avatar-editor__upload-icon\" />\n <span class=\"ea-avatar-editor__dropzone-text\">Drop image or click to upload</span>\n </button>\n }\n\n @if (hasImage() || isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-wrapper\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (isLoading()) {\n <ea-skeleton\n [variant]=\"shape() === 'circle' ? 'circle' : 'rect'\"\n [width]=\"canvasSize() + 'px'\"\n [height]=\"canvasSize() + 'px'\" />\n }\n\n @if (hasImage()) {\n <canvas\n #canvasEl\n class=\"ea-avatar-editor__canvas\"\n [style.display]=\"isLoading() ? 'none' : 'block'\"\n [width]=\"canvasSize()\"\n [height]=\"canvasSize()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"></canvas>\n\n @if (!isLoading()) {\n <div class=\"ea-avatar-editor__canvas-overlay\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>Change photo</span>\n </div>\n }\n }\n </div>\n }\n\n <div class=\"ea-avatar-editor__controls\">\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Revert to original'\"\n aria-label=\"Revert to original\"\n [disabled]=\"!canRevert() || isLoading()\"\n (click)=\"revertImage()\">\n <ea-icon-rotate-ccw />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom out'\"\n aria-label=\"Zoom out\"\n [disabled]=\"!hasImage() || isLoading() || zoom() <= minZoom()\"\n (click)=\"setZoom(zoom() - 0.1)\">\n <ea-icon-minus />\n </button>\n\n <input\n type=\"range\"\n class=\"ea-avatar-editor__zoom-slider\"\n [min]=\"minZoom()\"\n [max]=\"maxZoom()\"\n step=\"0.01\"\n [value]=\"zoom()\"\n [disabled]=\"!hasImage() || isLoading()\"\n aria-label=\"Zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom in'\"\n aria-label=\"Zoom in\"\n [disabled]=\"!hasImage() || isLoading() || zoom() >= maxZoom()\"\n (click)=\"setZoom(zoom() + 0.1)\">\n <ea-icon-plus />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn ea-avatar-editor__icon-btn--danger\"\n [eaTooltip]=\"'Remove image'\"\n aria-label=\"Remove image\"\n [disabled]=\"!hasImage() || isLoading()\"\n (click)=\"removeImage()\">\n <ea-icon-trash />\n </button>\n </div>\n</div>\n", styles: [".ea-avatar-editor{display:inline-flex;flex-direction:column;align-items:center;gap:var(--space-3);font-family:var(--font-family-sans)}.ea-avatar-editor__file-input{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;margin:-1px;border:0;white-space:nowrap;clip:rect(0,0,0,0);clip-path:inset(50%)}.ea-avatar-editor__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);font-family:inherit;font-size:var(--font-size-sm);line-height:var(--line-height-normal);border:2px dashed var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-tertiary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__dropzone:hover{border-color:var(--color-border-focus);background-color:var(--color-bg-muted);color:var(--color-text-secondary)}.ea-avatar-editor__dropzone:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor--drag-over .ea-avatar-editor__dropzone{border-color:var(--color-primary-500);background-color:var(--color-primary-50);color:var(--color-primary-600)}.ea-avatar-editor--circle .ea-avatar-editor__dropzone{border-radius:var(--radius-full)}.ea-avatar-editor__upload-icon{width:32px;height:32px;opacity:.6}.ea-avatar-editor__dropzone-text{text-align:center}.ea-avatar-editor__canvas-wrapper{position:relative;overflow:hidden;border-radius:var(--radius-lg)}.ea-avatar-editor--circle .ea-avatar-editor__canvas-wrapper{border-radius:var(--radius-full)}.ea-avatar-editor__canvas{display:block;cursor:grab}.ea-avatar-editor__canvas:active{cursor:grabbing}.ea-avatar-editor__canvas-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);background-color:var(--color-bg-overlay);color:var(--color-text-inverse);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default)}.ea-avatar-editor__overlay-icon{width:24px;height:24px}.ea-avatar-editor__canvas-wrapper:hover .ea-avatar-editor__canvas-overlay{opacity:1}.ea-avatar-editor__controls{display:flex;align-items:center;gap:var(--space-2)}.ea-avatar-editor__icon-btn{display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0}.ea-avatar-editor__icon-btn ea-icon-rotate-ccw,.ea-avatar-editor__icon-btn ea-icon-minus,.ea-avatar-editor__icon-btn ea-icon-plus,.ea-avatar-editor__icon-btn ea-icon-trash{width:1rem;height:1rem}.ea-avatar-editor__icon-btn{border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__icon-btn:hover:not(:disabled){border-color:var(--color-border-focus)}.ea-avatar-editor__icon-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__icon-btn:disabled{opacity:.4;cursor:not-allowed}.ea-avatar-editor__icon-btn--danger{color:var(--color-error-default)}.ea-avatar-editor__icon-btn--danger:hover:not(:disabled){border-color:var(--color-error-default)}.ea-avatar-editor__zoom-slider{width:7rem;height:4px;border-radius:var(--radius-full);background:var(--color-neutral-200);appearance:none;cursor:pointer}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);appearance:none;cursor:grab}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider::-moz-range-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);cursor:grab}.ea-avatar-editor__zoom-slider::-moz-range-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider:focus-visible{outline:none}.ea-avatar-editor__zoom-slider:focus-visible::-webkit-slider-thumb{box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__zoom-slider:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CameraIconComponent, selector: "ea-icon-camera" }, { kind: "component", type: MinusIconComponent, selector: "ea-icon-minus" }, { kind: "component", type: PlusIconComponent, selector: "ea-icon-plus" }, { kind: "component", type: RotateCcwIconComponent, selector: "ea-icon-rotate-ccw" }, { kind: "component", type: SkeletonComponent, selector: "ea-skeleton", inputs: ["variant", "width", "height", "animated"] }, { kind: "component", type: TrashIconComponent, selector: "ea-icon-trash" }, { kind: "component", type: UploadIconComponent, selector: "ea-icon-upload" }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1462
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AvatarEditorComponent, isStandalone: true, selector: "ea-avatar-editor", inputs: { shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: false, transformFunction: null }, currentSrc: { classPropertyName: "currentSrc", publicName: "currentSrc", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, minZoom: { classPropertyName: "minZoom", publicName: "minZoom", isSignal: true, isRequired: false, transformFunction: null }, maxZoom: { classPropertyName: "maxZoom", publicName: "maxZoom", isSignal: true, isRequired: false, transformFunction: null }, exportQuality: { classPropertyName: "exportQuality", publicName: "exportQuality", isSignal: true, isRequired: false, transformFunction: null }, exportType: { classPropertyName: "exportType", publicName: "exportType", isSignal: true, isRequired: false, transformFunction: null }, cropState: { classPropertyName: "cropState", publicName: "cropState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cropped: "cropped", fileSelected: "fileSelected", removed: "removed", errored: "errored", cropStateChanged: "cropStateChanged" }, viewQueries: [{ propertyName: "canvasEl", first: true, predicate: ["canvasEl"], descendants: true, isSignal: true }, { propertyName: "fileInputEl", first: true, predicate: ["fileInputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ea-avatar-editor\"\n [ngClass]=\"hostClasses()\">\n <input\n #fileInputEl\n type=\"file\"\n class=\"ea-avatar-editor__file-input\"\n aria-label=\"Upload image\"\n [accept]=\"accept()\"\n (change)=\"onFileSelected($event)\" />\n\n @if (!hasImage() && !isLoading()) {\n <button\n type=\"button\"\n class=\"ea-avatar-editor__dropzone\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (click)=\"openFilePicker()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <ea-icon-upload class=\"ea-avatar-editor__upload-icon\" />\n <span class=\"ea-avatar-editor__dropzone-text\">Drop image or click to upload</span>\n </button>\n }\n\n @if (hasImage() || isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-wrapper\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (isLoading()) {\n <ea-skeleton\n [variant]=\"shape() === 'circle' ? 'circle' : 'rect'\"\n [width]=\"canvasSize() + 'px'\"\n [height]=\"canvasSize() + 'px'\" />\n }\n\n @if (hasImage()) {\n <canvas\n #canvasEl\n class=\"ea-avatar-editor__canvas\"\n role=\"img\"\n tabindex=\"0\"\n aria-label=\"Image preview, drag or use arrow keys to pan, slider to zoom\"\n [style.display]=\"isLoading() ? 'none' : 'block'\"\n [width]=\"canvasSize()\"\n [height]=\"canvasSize()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (keydown)=\"onCanvasKeydown($event)\"></canvas>\n\n @if (!isLoading()) {\n <div class=\"ea-avatar-editor__canvas-overlay\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>Change photo</span>\n </div>\n }\n }\n </div>\n }\n\n <div class=\"ea-avatar-editor__controls\">\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Revert to original'\"\n aria-label=\"Revert to original\"\n [disabled]=\"!canRevert() || isLoading()\"\n (click)=\"revertImage()\">\n <ea-icon-rotate-ccw />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom out'\"\n aria-label=\"Zoom out\"\n [disabled]=\"!hasImage() || isLoading() || zoom() <= minZoom()\"\n (click)=\"setZoom(zoom() - 0.1)\">\n <ea-icon-minus />\n </button>\n\n <input\n type=\"range\"\n class=\"ea-avatar-editor__zoom-slider\"\n [min]=\"minZoom()\"\n [max]=\"maxZoom()\"\n step=\"0.01\"\n [value]=\"zoom()\"\n [disabled]=\"!hasImage() || isLoading()\"\n aria-label=\"Zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom in'\"\n aria-label=\"Zoom in\"\n [disabled]=\"!hasImage() || isLoading() || zoom() >= maxZoom()\"\n (click)=\"setZoom(zoom() + 0.1)\">\n <ea-icon-plus />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn ea-avatar-editor__icon-btn--danger\"\n [eaTooltip]=\"'Remove image'\"\n aria-label=\"Remove image\"\n [disabled]=\"!hasImage() || isLoading()\"\n (click)=\"removeImage()\">\n <ea-icon-trash />\n </button>\n </div>\n</div>\n", styles: [".ea-avatar-editor{display:inline-flex;flex-direction:column;align-items:center;gap:var(--space-3);font-family:var(--font-family-sans)}.ea-avatar-editor__file-input{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;margin:-1px;border:0;white-space:nowrap;clip:rect(0,0,0,0);clip-path:inset(50%)}.ea-avatar-editor__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);font-family:inherit;font-size:var(--font-size-sm);line-height:var(--line-height-normal);border:2px dashed var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-tertiary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__dropzone:hover{border-color:var(--color-border-focus);background-color:var(--color-bg-muted);color:var(--color-text-secondary)}.ea-avatar-editor__dropzone:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor--drag-over .ea-avatar-editor__dropzone{border-color:var(--color-primary-500);background-color:var(--color-primary-50);color:var(--color-primary-600)}.ea-avatar-editor--circle .ea-avatar-editor__dropzone{border-radius:var(--radius-full)}.ea-avatar-editor__upload-icon{width:32px;height:32px;opacity:.6}.ea-avatar-editor__dropzone-text{text-align:center}.ea-avatar-editor__canvas-wrapper{position:relative;overflow:hidden;border-radius:var(--radius-lg)}.ea-avatar-editor--circle .ea-avatar-editor__canvas-wrapper{border-radius:var(--radius-full)}.ea-avatar-editor__canvas{display:block;cursor:grab}.ea-avatar-editor__canvas:active{cursor:grabbing}.ea-avatar-editor__canvas-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);background-color:var(--color-bg-overlay);color:var(--color-text-inverse);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default)}.ea-avatar-editor__overlay-icon{width:24px;height:24px}.ea-avatar-editor__canvas-wrapper:hover .ea-avatar-editor__canvas-overlay{opacity:1}.ea-avatar-editor__controls{display:flex;align-items:center;gap:var(--space-2)}.ea-avatar-editor__icon-btn{display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0}.ea-avatar-editor__icon-btn ea-icon-rotate-ccw,.ea-avatar-editor__icon-btn ea-icon-minus,.ea-avatar-editor__icon-btn ea-icon-plus,.ea-avatar-editor__icon-btn ea-icon-trash{width:1rem;height:1rem}.ea-avatar-editor__icon-btn{border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__icon-btn:hover:not(:disabled){border-color:var(--color-border-focus)}.ea-avatar-editor__icon-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__icon-btn:disabled{opacity:.4;cursor:not-allowed}.ea-avatar-editor__icon-btn--danger{color:var(--color-error-default)}.ea-avatar-editor__icon-btn--danger:hover:not(:disabled){border-color:var(--color-error-default)}.ea-avatar-editor__zoom-slider{width:7rem;height:4px;border-radius:var(--radius-full);background:var(--color-neutral-200);appearance:none;cursor:pointer}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);appearance:none;cursor:grab}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider::-moz-range-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);cursor:grab}.ea-avatar-editor__zoom-slider::-moz-range-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider:focus-visible{outline:none}.ea-avatar-editor__zoom-slider:focus-visible::-webkit-slider-thumb{box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__zoom-slider:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CameraIconComponent, selector: "ea-icon-camera" }, { kind: "component", type: MinusIconComponent, selector: "ea-icon-minus" }, { kind: "component", type: PlusIconComponent, selector: "ea-icon-plus" }, { kind: "component", type: RotateCcwIconComponent, selector: "ea-icon-rotate-ccw" }, { kind: "component", type: SkeletonComponent, selector: "ea-skeleton", inputs: ["variant", "width", "height", "animated"] }, { kind: "component", type: TrashIconComponent, selector: "ea-icon-trash" }, { kind: "component", type: UploadIconComponent, selector: "ea-icon-upload" }, { kind: "directive", type: TooltipDirective, selector: "[eaTooltip]", inputs: ["eaTooltip", "tooltipPosition"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1323
1463
  }
1324
1464
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AvatarEditorComponent, decorators: [{
1325
1465
  type: Component,
@@ -1333,8 +1473,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1333
1473
  TrashIconComponent,
1334
1474
  UploadIconComponent,
1335
1475
  TooltipDirective,
1336
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-avatar-editor\"\n [ngClass]=\"hostClasses()\">\n <input\n #fileInputEl\n type=\"file\"\n class=\"ea-avatar-editor__file-input\"\n [accept]=\"accept()\"\n (change)=\"onFileSelected($event)\" />\n\n @if (!hasImage() && !isLoading()) {\n <button\n type=\"button\"\n class=\"ea-avatar-editor__dropzone\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (click)=\"openFilePicker()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <ea-icon-upload class=\"ea-avatar-editor__upload-icon\" />\n <span class=\"ea-avatar-editor__dropzone-text\">Drop image or click to upload</span>\n </button>\n }\n\n @if (hasImage() || isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-wrapper\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (isLoading()) {\n <ea-skeleton\n [variant]=\"shape() === 'circle' ? 'circle' : 'rect'\"\n [width]=\"canvasSize() + 'px'\"\n [height]=\"canvasSize() + 'px'\" />\n }\n\n @if (hasImage()) {\n <canvas\n #canvasEl\n class=\"ea-avatar-editor__canvas\"\n [style.display]=\"isLoading() ? 'none' : 'block'\"\n [width]=\"canvasSize()\"\n [height]=\"canvasSize()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"></canvas>\n\n @if (!isLoading()) {\n <div class=\"ea-avatar-editor__canvas-overlay\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>Change photo</span>\n </div>\n }\n }\n </div>\n }\n\n <div class=\"ea-avatar-editor__controls\">\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Revert to original'\"\n aria-label=\"Revert to original\"\n [disabled]=\"!canRevert() || isLoading()\"\n (click)=\"revertImage()\">\n <ea-icon-rotate-ccw />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom out'\"\n aria-label=\"Zoom out\"\n [disabled]=\"!hasImage() || isLoading() || zoom() <= minZoom()\"\n (click)=\"setZoom(zoom() - 0.1)\">\n <ea-icon-minus />\n </button>\n\n <input\n type=\"range\"\n class=\"ea-avatar-editor__zoom-slider\"\n [min]=\"minZoom()\"\n [max]=\"maxZoom()\"\n step=\"0.01\"\n [value]=\"zoom()\"\n [disabled]=\"!hasImage() || isLoading()\"\n aria-label=\"Zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom in'\"\n aria-label=\"Zoom in\"\n [disabled]=\"!hasImage() || isLoading() || zoom() >= maxZoom()\"\n (click)=\"setZoom(zoom() + 0.1)\">\n <ea-icon-plus />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn ea-avatar-editor__icon-btn--danger\"\n [eaTooltip]=\"'Remove image'\"\n aria-label=\"Remove image\"\n [disabled]=\"!hasImage() || isLoading()\"\n (click)=\"removeImage()\">\n <ea-icon-trash />\n </button>\n </div>\n</div>\n", styles: [".ea-avatar-editor{display:inline-flex;flex-direction:column;align-items:center;gap:var(--space-3);font-family:var(--font-family-sans)}.ea-avatar-editor__file-input{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;margin:-1px;border:0;white-space:nowrap;clip:rect(0,0,0,0);clip-path:inset(50%)}.ea-avatar-editor__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);font-family:inherit;font-size:var(--font-size-sm);line-height:var(--line-height-normal);border:2px dashed var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-tertiary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__dropzone:hover{border-color:var(--color-border-focus);background-color:var(--color-bg-muted);color:var(--color-text-secondary)}.ea-avatar-editor__dropzone:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor--drag-over .ea-avatar-editor__dropzone{border-color:var(--color-primary-500);background-color:var(--color-primary-50);color:var(--color-primary-600)}.ea-avatar-editor--circle .ea-avatar-editor__dropzone{border-radius:var(--radius-full)}.ea-avatar-editor__upload-icon{width:32px;height:32px;opacity:.6}.ea-avatar-editor__dropzone-text{text-align:center}.ea-avatar-editor__canvas-wrapper{position:relative;overflow:hidden;border-radius:var(--radius-lg)}.ea-avatar-editor--circle .ea-avatar-editor__canvas-wrapper{border-radius:var(--radius-full)}.ea-avatar-editor__canvas{display:block;cursor:grab}.ea-avatar-editor__canvas:active{cursor:grabbing}.ea-avatar-editor__canvas-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);background-color:var(--color-bg-overlay);color:var(--color-text-inverse);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default)}.ea-avatar-editor__overlay-icon{width:24px;height:24px}.ea-avatar-editor__canvas-wrapper:hover .ea-avatar-editor__canvas-overlay{opacity:1}.ea-avatar-editor__controls{display:flex;align-items:center;gap:var(--space-2)}.ea-avatar-editor__icon-btn{display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0}.ea-avatar-editor__icon-btn ea-icon-rotate-ccw,.ea-avatar-editor__icon-btn ea-icon-minus,.ea-avatar-editor__icon-btn ea-icon-plus,.ea-avatar-editor__icon-btn ea-icon-trash{width:1rem;height:1rem}.ea-avatar-editor__icon-btn{border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__icon-btn:hover:not(:disabled){border-color:var(--color-border-focus)}.ea-avatar-editor__icon-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__icon-btn:disabled{opacity:.4;cursor:not-allowed}.ea-avatar-editor__icon-btn--danger{color:var(--color-error-default)}.ea-avatar-editor__icon-btn--danger:hover:not(:disabled){border-color:var(--color-error-default)}.ea-avatar-editor__zoom-slider{width:7rem;height:4px;border-radius:var(--radius-full);background:var(--color-neutral-200);appearance:none;cursor:pointer}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);appearance:none;cursor:grab}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider::-moz-range-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);cursor:grab}.ea-avatar-editor__zoom-slider::-moz-range-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider:focus-visible{outline:none}.ea-avatar-editor__zoom-slider:focus-visible::-webkit-slider-thumb{box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__zoom-slider:disabled{opacity:.4;cursor:not-allowed}\n"] }]
1337
- }], ctorParameters: () => [], propDecorators: { canvasEl: [{ type: i0.ViewChild, args: ['canvasEl', { isSignal: true }] }], fileInputEl: [{ type: i0.ViewChild, args: ['fileInputEl', { isSignal: true }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: false }] }], currentSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentSrc", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], minZoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "minZoom", required: false }] }], maxZoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxZoom", required: false }] }], exportQuality: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportQuality", required: false }] }], exportType: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportType", required: false }] }], cropState: [{ type: i0.Input, args: [{ isSignal: true, alias: "cropState", required: false }] }], cropped: [{ type: i0.Output, args: ["cropped"] }], fileSelected: [{ type: i0.Output, args: ["fileSelected"] }], removed: [{ type: i0.Output, args: ["removed"] }], fileError: [{ type: i0.Output, args: ["fileError"] }], cropStateChange: [{ type: i0.Output, args: ["cropStateChange"] }] } });
1476
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-avatar-editor\"\n [ngClass]=\"hostClasses()\">\n <input\n #fileInputEl\n type=\"file\"\n class=\"ea-avatar-editor__file-input\"\n aria-label=\"Upload image\"\n [accept]=\"accept()\"\n (change)=\"onFileSelected($event)\" />\n\n @if (!hasImage() && !isLoading()) {\n <button\n type=\"button\"\n class=\"ea-avatar-editor__dropzone\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (click)=\"openFilePicker()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <ea-icon-upload class=\"ea-avatar-editor__upload-icon\" />\n <span class=\"ea-avatar-editor__dropzone-text\">Drop image or click to upload</span>\n </button>\n }\n\n @if (hasImage() || isLoading()) {\n <div\n class=\"ea-avatar-editor__canvas-wrapper\"\n [style.width.px]=\"canvasSize()\"\n [style.height.px]=\"canvasSize()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n @if (isLoading()) {\n <ea-skeleton\n [variant]=\"shape() === 'circle' ? 'circle' : 'rect'\"\n [width]=\"canvasSize() + 'px'\"\n [height]=\"canvasSize() + 'px'\" />\n }\n\n @if (hasImage()) {\n <canvas\n #canvasEl\n class=\"ea-avatar-editor__canvas\"\n role=\"img\"\n tabindex=\"0\"\n aria-label=\"Image preview, drag or use arrow keys to pan, slider to zoom\"\n [style.display]=\"isLoading() ? 'none' : 'block'\"\n [width]=\"canvasSize()\"\n [height]=\"canvasSize()\"\n (mousedown)=\"onMouseDown($event)\"\n (touchstart)=\"onTouchStart($event)\"\n (keydown)=\"onCanvasKeydown($event)\"></canvas>\n\n @if (!isLoading()) {\n <div class=\"ea-avatar-editor__canvas-overlay\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>Change photo</span>\n </div>\n }\n }\n </div>\n }\n\n <div class=\"ea-avatar-editor__controls\">\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Revert to original'\"\n aria-label=\"Revert to original\"\n [disabled]=\"!canRevert() || isLoading()\"\n (click)=\"revertImage()\">\n <ea-icon-rotate-ccw />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom out'\"\n aria-label=\"Zoom out\"\n [disabled]=\"!hasImage() || isLoading() || zoom() <= minZoom()\"\n (click)=\"setZoom(zoom() - 0.1)\">\n <ea-icon-minus />\n </button>\n\n <input\n type=\"range\"\n class=\"ea-avatar-editor__zoom-slider\"\n [min]=\"minZoom()\"\n [max]=\"maxZoom()\"\n step=\"0.01\"\n [value]=\"zoom()\"\n [disabled]=\"!hasImage() || isLoading()\"\n aria-label=\"Zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"'Zoom in'\"\n aria-label=\"Zoom in\"\n [disabled]=\"!hasImage() || isLoading() || zoom() >= maxZoom()\"\n (click)=\"setZoom(zoom() + 0.1)\">\n <ea-icon-plus />\n </button>\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn ea-avatar-editor__icon-btn--danger\"\n [eaTooltip]=\"'Remove image'\"\n aria-label=\"Remove image\"\n [disabled]=\"!hasImage() || isLoading()\"\n (click)=\"removeImage()\">\n <ea-icon-trash />\n </button>\n </div>\n</div>\n", styles: [".ea-avatar-editor{display:inline-flex;flex-direction:column;align-items:center;gap:var(--space-3);font-family:var(--font-family-sans)}.ea-avatar-editor__file-input{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;margin:-1px;border:0;white-space:nowrap;clip:rect(0,0,0,0);clip-path:inset(50%)}.ea-avatar-editor__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-2);padding:var(--space-4);font-family:inherit;font-size:var(--font-size-sm);line-height:var(--line-height-normal);border:2px dashed var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-tertiary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__dropzone:hover{border-color:var(--color-border-focus);background-color:var(--color-bg-muted);color:var(--color-text-secondary)}.ea-avatar-editor__dropzone:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor--drag-over .ea-avatar-editor__dropzone{border-color:var(--color-primary-500);background-color:var(--color-primary-50);color:var(--color-primary-600)}.ea-avatar-editor--circle .ea-avatar-editor__dropzone{border-radius:var(--radius-full)}.ea-avatar-editor__upload-icon{width:32px;height:32px;opacity:.6}.ea-avatar-editor__dropzone-text{text-align:center}.ea-avatar-editor__canvas-wrapper{position:relative;overflow:hidden;border-radius:var(--radius-lg)}.ea-avatar-editor--circle .ea-avatar-editor__canvas-wrapper{border-radius:var(--radius-full)}.ea-avatar-editor__canvas{display:block;cursor:grab}.ea-avatar-editor__canvas:active{cursor:grabbing}.ea-avatar-editor__canvas-overlay{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-1);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);background-color:var(--color-bg-overlay);color:var(--color-text-inverse);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default)}.ea-avatar-editor__overlay-icon{width:24px;height:24px}.ea-avatar-editor__canvas-wrapper:hover .ea-avatar-editor__canvas-overlay{opacity:1}.ea-avatar-editor__controls{display:flex;align-items:center;gap:var(--space-2)}.ea-avatar-editor__icon-btn{display:flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0}.ea-avatar-editor__icon-btn ea-icon-rotate-ccw,.ea-avatar-editor__icon-btn ea-icon-minus,.ea-avatar-editor__icon-btn ea-icon-plus,.ea-avatar-editor__icon-btn ea-icon-trash{width:1rem;height:1rem}.ea-avatar-editor__icon-btn{border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-avatar-editor__icon-btn:hover:not(:disabled){border-color:var(--color-border-focus)}.ea-avatar-editor__icon-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__icon-btn:disabled{opacity:.4;cursor:not-allowed}.ea-avatar-editor__icon-btn--danger{color:var(--color-error-default)}.ea-avatar-editor__icon-btn--danger:hover:not(:disabled){border-color:var(--color-error-default)}.ea-avatar-editor__zoom-slider{width:7rem;height:4px;border-radius:var(--radius-full);background:var(--color-neutral-200);appearance:none;cursor:pointer}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);appearance:none;cursor:grab}.ea-avatar-editor__zoom-slider::-webkit-slider-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider::-moz-range-thumb{width:1rem;height:1rem;border:2px solid var(--color-primary-500);border-radius:var(--radius-full);background:var(--color-bg-base);cursor:grab}.ea-avatar-editor__zoom-slider::-moz-range-thumb:active{cursor:grabbing}.ea-avatar-editor__zoom-slider:focus-visible{outline:none}.ea-avatar-editor__zoom-slider:focus-visible::-webkit-slider-thumb{box-shadow:var(--shadow-focus-ring)}.ea-avatar-editor__zoom-slider:disabled{opacity:.4;cursor:not-allowed}\n"] }]
1477
+ }], ctorParameters: () => [], propDecorators: { canvasEl: [{ type: i0.ViewChild, args: ['canvasEl', { isSignal: true }] }], fileInputEl: [{ type: i0.ViewChild, args: ['fileInputEl', { isSignal: true }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: false }] }], currentSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentSrc", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], minZoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "minZoom", required: false }] }], maxZoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxZoom", required: false }] }], exportQuality: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportQuality", required: false }] }], exportType: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportType", required: false }] }], cropState: [{ type: i0.Input, args: [{ isSignal: true, alias: "cropState", required: false }] }], cropped: [{ type: i0.Output, args: ["cropped"] }], fileSelected: [{ type: i0.Output, args: ["fileSelected"] }], removed: [{ type: i0.Output, args: ["removed"] }], errored: [{ type: i0.Output, args: ["errored"] }], cropStateChanged: [{ type: i0.Output, args: ["cropStateChanged"] }] } });
1338
1478
 
1339
1479
  class UserIconComponent {
1340
1480
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1384,6 +1524,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1384
1524
  }]
1385
1525
  }] });
1386
1526
 
1527
+ /**
1528
+ * Compact image used to represent a user or entity. Falls back to initials
1529
+ * when no `src` is provided, then to a generic user icon when neither image
1530
+ * nor initials are available.
1531
+ */
1387
1532
  class AvatarComponent {
1388
1533
  src = input(undefined, ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
1389
1534
  alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
@@ -1401,13 +1546,17 @@ class AvatarComponent {
1401
1546
  event.target.style.display = 'none';
1402
1547
  }
1403
1548
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1404
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AvatarComponent, isStandalone: true, selector: "ea-avatar", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: inline-block; line-height: 0;" }, ngImport: i0, template: "<div\n class=\"ea-avatar\"\n [ngClass]=\"hostClasses()\"\n [attr.aria-label]=\"alt() || null\"\n role=\"img\">\n @if (showImage()) {\n <img\n class=\"ea-avatar__image\"\n [src]=\"src()\"\n [alt]=\"alt()\"\n (error)=\"handleImageError($event)\" />\n }\n @if (showInitials()) {\n <span class=\"ea-avatar__initials\">{{ initials() }}</span>\n }\n @if (showFallback()) {\n <ea-icon-user class=\"ea-avatar__fallback\" />\n }\n</div>\n", styles: [".ea-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden;background-color:var(--color-bg-muted);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{width:1.5rem;height:1.5rem;font-size:var(--font-size-xs)}.ea-avatar--sm{width:2rem;height:2rem;font-size:var(--font-size-sm)}.ea-avatar--md{width:2.5rem;height:2.5rem;font-size:var(--font-size-md)}.ea-avatar--lg{width:3rem;height:3rem;font-size:var(--font-size-lg)}.ea-avatar--xl{width:4rem;height:4rem;font-size:var(--font-size-xl)}.ea-avatar--circle{border-radius:var(--radius-full)}.ea-avatar--square{border-radius:var(--radius-md)}.ea-avatar__image{width:100%;height:100%;object-fit:cover}.ea-avatar__initials{text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{width:60%;height:60%}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: UserIconComponent, selector: "ea-icon-user" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1549
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AvatarComponent, isStandalone: true, selector: "ea-avatar", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null } }, host: { styleAttribute: "display: inline-block; line-height: 0;" }, ngImport: i0, template: "<div\n class=\"ea-avatar\"\n [ngClass]=\"hostClasses()\"\n [attr.aria-label]=\"alt() || initials() || null\"\n role=\"img\">\n @if (showImage()) {\n <img\n class=\"ea-avatar__image\"\n [src]=\"src()\"\n [alt]=\"alt()\"\n (error)=\"handleImageError($event)\" />\n }\n @if (showInitials()) {\n <span class=\"ea-avatar__initials\">{{ initials() }}</span>\n }\n @if (showFallback()) {\n <ea-icon-user class=\"ea-avatar__fallback\" />\n }\n</div>\n", styles: [".ea-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden;background-color:var(--color-bg-muted);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{width:1.5rem;height:1.5rem;font-size:var(--font-size-xs)}.ea-avatar--sm{width:2rem;height:2rem;font-size:var(--font-size-sm)}.ea-avatar--md{width:2.5rem;height:2.5rem;font-size:var(--font-size-md)}.ea-avatar--lg{width:3rem;height:3rem;font-size:var(--font-size-lg)}.ea-avatar--xl{width:4rem;height:4rem;font-size:var(--font-size-xl)}.ea-avatar--circle{border-radius:var(--radius-full)}.ea-avatar--square{border-radius:var(--radius-md)}.ea-avatar__image{width:100%;height:100%;object-fit:cover}.ea-avatar__initials{text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{width:60%;height:60%}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: UserIconComponent, selector: "ea-icon-user" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1405
1550
  }
1406
1551
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AvatarComponent, decorators: [{
1407
1552
  type: Component,
1408
- args: [{ selector: 'ea-avatar', imports: [NgClass, UserIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { style: 'display: inline-block; line-height: 0;' }, template: "<div\n class=\"ea-avatar\"\n [ngClass]=\"hostClasses()\"\n [attr.aria-label]=\"alt() || null\"\n role=\"img\">\n @if (showImage()) {\n <img\n class=\"ea-avatar__image\"\n [src]=\"src()\"\n [alt]=\"alt()\"\n (error)=\"handleImageError($event)\" />\n }\n @if (showInitials()) {\n <span class=\"ea-avatar__initials\">{{ initials() }}</span>\n }\n @if (showFallback()) {\n <ea-icon-user class=\"ea-avatar__fallback\" />\n }\n</div>\n", styles: [".ea-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden;background-color:var(--color-bg-muted);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{width:1.5rem;height:1.5rem;font-size:var(--font-size-xs)}.ea-avatar--sm{width:2rem;height:2rem;font-size:var(--font-size-sm)}.ea-avatar--md{width:2.5rem;height:2.5rem;font-size:var(--font-size-md)}.ea-avatar--lg{width:3rem;height:3rem;font-size:var(--font-size-lg)}.ea-avatar--xl{width:4rem;height:4rem;font-size:var(--font-size-xl)}.ea-avatar--circle{border-radius:var(--radius-full)}.ea-avatar--square{border-radius:var(--radius-md)}.ea-avatar__image{width:100%;height:100%;object-fit:cover}.ea-avatar__initials{text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{width:60%;height:60%}\n"] }]
1553
+ args: [{ selector: 'ea-avatar', imports: [NgClass, UserIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: { style: 'display: inline-block; line-height: 0;' }, template: "<div\n class=\"ea-avatar\"\n [ngClass]=\"hostClasses()\"\n [attr.aria-label]=\"alt() || initials() || null\"\n role=\"img\">\n @if (showImage()) {\n <img\n class=\"ea-avatar__image\"\n [src]=\"src()\"\n [alt]=\"alt()\"\n (error)=\"handleImageError($event)\" />\n }\n @if (showInitials()) {\n <span class=\"ea-avatar__initials\">{{ initials() }}</span>\n }\n @if (showFallback()) {\n <ea-icon-user class=\"ea-avatar__fallback\" />\n }\n</div>\n", styles: [".ea-avatar{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;overflow:hidden;background-color:var(--color-bg-muted);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{width:1.5rem;height:1.5rem;font-size:var(--font-size-xs)}.ea-avatar--sm{width:2rem;height:2rem;font-size:var(--font-size-sm)}.ea-avatar--md{width:2.5rem;height:2.5rem;font-size:var(--font-size-md)}.ea-avatar--lg{width:3rem;height:3rem;font-size:var(--font-size-lg)}.ea-avatar--xl{width:4rem;height:4rem;font-size:var(--font-size-xl)}.ea-avatar--circle{border-radius:var(--radius-full)}.ea-avatar--square{border-radius:var(--radius-md)}.ea-avatar__image{width:100%;height:100%;object-fit:cover}.ea-avatar__initials{text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{width:60%;height:60%}\n"] }]
1409
1554
  }], propDecorators: { src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }] } });
1410
1555
 
1556
+ /**
1557
+ * Compact pill-shaped indicator used to communicate status, counts, or labels
1558
+ * inline with surrounding content.
1559
+ */
1411
1560
  class BadgeComponent {
1412
1561
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1413
1562
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
@@ -1463,11 +1612,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1463
1612
  }]
1464
1613
  }] });
1465
1614
 
1615
+ /**
1616
+ * Navigation trail that shows the user's location within a hierarchy. Items
1617
+ * with an `href` render as links, others render as buttons; the final item is
1618
+ * always treated as the current page and is non-interactive.
1619
+ */
1466
1620
  class BreadcrumbsComponent {
1467
1621
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
1468
1622
  separator = input('chevron', ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
1469
1623
  ariaLabel = input('Breadcrumb', { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
1470
- itemClicked = output();
1624
+ /** Fires when a non-disabled, non-final breadcrumb is activated. */
1625
+ clicked = output();
1471
1626
  isLast(index) {
1472
1627
  return index === this.items().length - 1;
1473
1628
  }
@@ -1476,16 +1631,21 @@ class BreadcrumbsComponent {
1476
1631
  event.preventDefault();
1477
1632
  return;
1478
1633
  }
1479
- this.itemClicked.emit({ item, index, event });
1634
+ this.clicked.emit({ item, index, event });
1480
1635
  }
1481
1636
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BreadcrumbsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1482
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: BreadcrumbsComponent, isStandalone: true, selector: "ea-breadcrumbs", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked" }, ngImport: i0, template: "<nav\n class=\"ea-breadcrumbs\"\n [attr.aria-label]=\"ariaLabel()\">\n <ol class=\"ea-breadcrumbs__list\">\n @for (item of items(); track $index; let i = $index; let last = $last) {\n <li class=\"ea-breadcrumbs__item\">\n @if (last) {\n <span\n class=\"ea-breadcrumbs__current\"\n aria-current=\"page\">\n {{ item.label }}\n </span>\n } @else if (item.disabled) {\n <span class=\"ea-breadcrumbs__link ea-breadcrumbs__link--disabled\">\n {{ item.label }}\n </span>\n } @else if (item.href) {\n <a\n class=\"ea-breadcrumbs__link\"\n [href]=\"item.href\"\n (click)=\"handleClick(item, i, $event)\">\n {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"ea-breadcrumbs__link ea-breadcrumbs__link--button\"\n (click)=\"handleClick(item, i, $event)\">\n {{ item.label }}\n </button>\n }\n\n @if (!last) {\n @if (separator() === 'chevron') {\n <ea-icon-chevron-right\n class=\"ea-breadcrumbs__separator\"\n aria-hidden=\"true\" />\n } @else {\n <span\n class=\"ea-breadcrumbs__separator ea-breadcrumbs__separator--slash\"\n aria-hidden=\"true\">\n /\n </span>\n }\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [".ea-breadcrumbs{font-family:var(--font-family-sans);font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-breadcrumbs__list{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1);padding:0;margin:0;list-style:none}.ea-breadcrumbs__item{display:inline-flex;align-items:center;gap:var(--space-1);min-width:0}.ea-breadcrumbs__link{padding:var(--space-0-5) var(--space-1);border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);font-family:inherit;font-size:inherit;text-decoration:none;cursor:pointer;transition:var(--transition-colors)}.ea-breadcrumbs__link:hover:not(.ea-breadcrumbs__link--disabled){color:var(--color-text-primary);text-decoration:underline}.ea-breadcrumbs__link:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-breadcrumbs__link--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-breadcrumbs__current{padding:var(--space-0-5) var(--space-1);font-weight:var(--font-weight-medium);color:var(--color-text-primary)}.ea-breadcrumbs__separator{display:inline-flex;align-items:center;justify-content:center;width:1rem;height:1rem;color:var(--color-text-tertiary);flex-shrink:0;-webkit-user-select:none;user-select:none}.ea-breadcrumbs__separator--slash{width:auto;height:auto;font-size:var(--font-size-sm)}\n"], dependencies: [{ kind: "component", type: ChevronRightIconComponent, selector: "ea-icon-chevron-right" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1637
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: BreadcrumbsComponent, isStandalone: true, selector: "ea-breadcrumbs", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<nav\n class=\"ea-breadcrumbs\"\n [attr.aria-label]=\"ariaLabel()\">\n <ol class=\"ea-breadcrumbs__list\">\n @for (item of items(); track $index; let i = $index; let last = $last) {\n <li class=\"ea-breadcrumbs__item\">\n @if (last) {\n <span\n class=\"ea-breadcrumbs__current\"\n aria-current=\"page\">\n {{ item.label }}\n </span>\n } @else if (item.disabled) {\n <span class=\"ea-breadcrumbs__link ea-breadcrumbs__link--disabled\">\n {{ item.label }}\n </span>\n } @else if (item.href) {\n <a\n class=\"ea-breadcrumbs__link\"\n [href]=\"item.href\"\n (click)=\"handleClick(item, i, $event)\">\n {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"ea-breadcrumbs__link ea-breadcrumbs__link--button\"\n (click)=\"handleClick(item, i, $event)\">\n {{ item.label }}\n </button>\n }\n\n @if (!last) {\n @if (separator() === 'chevron') {\n <ea-icon-chevron-right\n class=\"ea-breadcrumbs__separator\"\n aria-hidden=\"true\" />\n } @else {\n <span\n class=\"ea-breadcrumbs__separator ea-breadcrumbs__separator--slash\"\n aria-hidden=\"true\">\n /\n </span>\n }\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [".ea-breadcrumbs{font-family:var(--font-family-sans);font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-breadcrumbs__list{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1);padding:0;margin:0;list-style:none}.ea-breadcrumbs__item{display:inline-flex;align-items:center;gap:var(--space-1);min-width:0}.ea-breadcrumbs__link{padding:var(--space-0-5) var(--space-1);border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);font-family:inherit;font-size:inherit;text-decoration:none;cursor:pointer;transition:var(--transition-colors)}.ea-breadcrumbs__link:hover:not(.ea-breadcrumbs__link--disabled){color:var(--color-text-primary);text-decoration:underline}.ea-breadcrumbs__link:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-breadcrumbs__link--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-breadcrumbs__current{padding:var(--space-0-5) var(--space-1);font-weight:var(--font-weight-medium);color:var(--color-text-primary)}.ea-breadcrumbs__separator{display:inline-flex;align-items:center;justify-content:center;width:1rem;height:1rem;color:var(--color-text-tertiary);flex-shrink:0;-webkit-user-select:none;user-select:none}.ea-breadcrumbs__separator--slash{width:auto;height:auto;font-size:var(--font-size-sm)}\n"], dependencies: [{ kind: "component", type: ChevronRightIconComponent, selector: "ea-icon-chevron-right" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1483
1638
  }
1484
1639
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BreadcrumbsComponent, decorators: [{
1485
1640
  type: Component,
1486
1641
  args: [{ selector: 'ea-breadcrumbs', imports: [ChevronRightIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<nav\n class=\"ea-breadcrumbs\"\n [attr.aria-label]=\"ariaLabel()\">\n <ol class=\"ea-breadcrumbs__list\">\n @for (item of items(); track $index; let i = $index; let last = $last) {\n <li class=\"ea-breadcrumbs__item\">\n @if (last) {\n <span\n class=\"ea-breadcrumbs__current\"\n aria-current=\"page\">\n {{ item.label }}\n </span>\n } @else if (item.disabled) {\n <span class=\"ea-breadcrumbs__link ea-breadcrumbs__link--disabled\">\n {{ item.label }}\n </span>\n } @else if (item.href) {\n <a\n class=\"ea-breadcrumbs__link\"\n [href]=\"item.href\"\n (click)=\"handleClick(item, i, $event)\">\n {{ item.label }}\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"ea-breadcrumbs__link ea-breadcrumbs__link--button\"\n (click)=\"handleClick(item, i, $event)\">\n {{ item.label }}\n </button>\n }\n\n @if (!last) {\n @if (separator() === 'chevron') {\n <ea-icon-chevron-right\n class=\"ea-breadcrumbs__separator\"\n aria-hidden=\"true\" />\n } @else {\n <span\n class=\"ea-breadcrumbs__separator ea-breadcrumbs__separator--slash\"\n aria-hidden=\"true\">\n /\n </span>\n }\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [".ea-breadcrumbs{font-family:var(--font-family-sans);font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-breadcrumbs__list{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1);padding:0;margin:0;list-style:none}.ea-breadcrumbs__item{display:inline-flex;align-items:center;gap:var(--space-1);min-width:0}.ea-breadcrumbs__link{padding:var(--space-0-5) var(--space-1);border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);font-family:inherit;font-size:inherit;text-decoration:none;cursor:pointer;transition:var(--transition-colors)}.ea-breadcrumbs__link:hover:not(.ea-breadcrumbs__link--disabled){color:var(--color-text-primary);text-decoration:underline}.ea-breadcrumbs__link:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-breadcrumbs__link--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-breadcrumbs__current{padding:var(--space-0-5) var(--space-1);font-weight:var(--font-weight-medium);color:var(--color-text-primary)}.ea-breadcrumbs__separator{display:inline-flex;align-items:center;justify-content:center;width:1rem;height:1rem;color:var(--color-text-tertiary);flex-shrink:0;-webkit-user-select:none;user-select:none}.ea-breadcrumbs__separator--slash{width:auto;height:auto;font-size:var(--font-size-sm)}\n"] }]
1487
- }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
1642
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
1488
1643
 
1644
+ /**
1645
+ * Standard action button supporting primary, secondary, ghost, and danger
1646
+ * variants. Includes a loading state that swaps the label for a spinner while
1647
+ * preserving the rendered width.
1648
+ */
1489
1649
  class ButtonComponent {
1490
1650
  // Inputs
1491
1651
  variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -1497,6 +1657,7 @@ class ButtonComponent {
1497
1657
  ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
1498
1658
  ariaCurrent = input(undefined, { ...(ngDevMode ? { debugName: "ariaCurrent" } : /* istanbul ignore next */ {}), alias: 'aria-current' });
1499
1659
  // Output
1660
+ /** Fires when the button is activated; suppressed while disabled or loading. */
1500
1661
  clicked = output();
1501
1662
  // Derived
1502
1663
  isDisabled = computed(() => this.disabled() || this.loading(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
@@ -1515,15 +1676,19 @@ class ButtonComponent {
1515
1676
  this.clicked.emit(event);
1516
1677
  }
1517
1678
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1518
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ButtonComponent, isStandalone: true, selector: "ea-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaCurrent: { classPropertyName: "ariaCurrent", publicName: "aria-current", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { properties: { "class.ea-button--full-width": "fullWidth()" } }, ngImport: i0, template: "<button\n class=\"ea-button\"\n [ngClass]=\"hostClasses()\"\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-current]=\"ariaCurrent() || null\"\n [attr.aria-busy]=\"loading() || null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"handleClick($event)\">\n @if (loading()) {\n <span\n class=\"ea-button__spinner\"\n aria-hidden=\"true\">\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-dasharray=\"31.4\"\n stroke-dashoffset=\"10\" />\n </svg>\n </span>\n }\n\n <span\n class=\"ea-button__content\"\n [class.ea-button__content--hidden]=\"loading()\">\n <ng-content select=\"[slot=prefix]\" />\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [".ea-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--inline-xs);position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);font-weight:var(--ea-button-font-weight, var(--font-weight-medium));letter-spacing:var(--letter-spacing-wide);text-decoration:none;line-height:var(--line-height-none);border-width:var(--border-width-thin);border-style:solid;border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);cursor:pointer}.ea-button:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-button--sm{padding:var(--space-1-5) var(--space-3);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2rem}.ea-button--md{padding:var(--space-2) var(--space-4);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2.5rem}.ea-button--lg{padding:var(--space-2-5) var(--space-6);font-size:var(--ea-button-font-size, var(--font-size-md));min-height:3rem}.ea-button--primary{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--color-brand-hover);border-color:var(--color-brand-hover)}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--color-brand-active);border-color:var(--color-brand-active)}.ea-button--secondary{background-color:transparent;border-color:var(--color-border-strong);color:var(--color-text-primary)}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted);border-color:var(--color-neutral-500)}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--ghost{background-color:transparent;border-color:transparent;color:var(--color-text-primary)}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted)}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--danger{background-color:var(--color-error-default);border-color:var(--color-error-default);color:var(--color-text-inverse)}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700)}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700);filter:brightness(.9)}.ea-button--full-width{width:100%}.ea-button--disabled,.ea-button:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.ea-button--loading{cursor:wait;pointer-events:none}.ea-button__content{display:inline-flex;align-items:center;gap:var(--inline-xs)}.ea-button__content--hidden{visibility:hidden}.ea-button__label{display:inline-flex;align-items:center}.ea-button__spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.ea-button__spinner svg{width:1.1em;height:1.1em;animation:ea-spin .75s linear infinite}:host(.ea-button--full-width){display:block;width:100%}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1679
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ButtonComponent, isStandalone: true, selector: "ea-button", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaCurrent: { classPropertyName: "ariaCurrent", publicName: "aria-current", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { properties: { "class.ea-button--full-width": "fullWidth()" } }, ngImport: i0, template: "<button\n class=\"ea-button\"\n [ngClass]=\"hostClasses()\"\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-current]=\"ariaCurrent() || null\"\n [attr.aria-busy]=\"loading() || null\"\n (click)=\"handleClick($event)\">\n @if (loading()) {\n <span\n class=\"ea-button__spinner\"\n aria-hidden=\"true\">\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-dasharray=\"31.4\"\n stroke-dashoffset=\"10\" />\n </svg>\n </span>\n }\n\n <span\n class=\"ea-button__content\"\n [class.ea-button__content--hidden]=\"loading()\">\n <ng-content select=\"[slot=prefix]\" />\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [".ea-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--inline-xs);position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);font-weight:var(--ea-button-font-weight, var(--font-weight-medium));letter-spacing:var(--letter-spacing-wide);text-decoration:none;line-height:var(--line-height-none);border-width:var(--border-width-thin);border-style:solid;border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);cursor:pointer}.ea-button:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-button--sm{padding:var(--space-1-5) var(--space-3);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2rem}.ea-button--md{padding:var(--space-2) var(--space-4);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2.5rem}.ea-button--lg{padding:var(--space-2-5) var(--space-6);font-size:var(--ea-button-font-size, var(--font-size-md));min-height:3rem}.ea-button--primary{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--color-brand-hover);border-color:var(--color-brand-hover)}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--color-brand-active);border-color:var(--color-brand-active)}.ea-button--secondary{background-color:transparent;border-color:var(--color-border-strong);color:var(--color-text-primary)}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted);border-color:var(--color-neutral-500)}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--ghost{background-color:transparent;border-color:transparent;color:var(--color-text-primary)}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted)}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--danger{background-color:var(--color-error-default);border-color:var(--color-error-default);color:var(--color-text-inverse)}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700)}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700);filter:brightness(.9)}.ea-button--full-width{width:100%}.ea-button--disabled,.ea-button:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.ea-button--loading{cursor:wait;pointer-events:none}.ea-button__content{display:inline-flex;align-items:center;gap:var(--inline-xs)}.ea-button__content--hidden{visibility:hidden}.ea-button__label{display:inline-flex;align-items:center}.ea-button__spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.ea-button__spinner svg{width:1.1em;height:1.1em;animation:ea-spin .75s linear infinite}:host(.ea-button--full-width){display:block;width:100%}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1519
1680
  }
1520
1681
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ButtonComponent, decorators: [{
1521
1682
  type: Component,
1522
1683
  args: [{ selector: 'ea-button', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, host: {
1523
1684
  '[class.ea-button--full-width]': 'fullWidth()',
1524
- }, template: "<button\n class=\"ea-button\"\n [ngClass]=\"hostClasses()\"\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-current]=\"ariaCurrent() || null\"\n [attr.aria-busy]=\"loading() || null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n (click)=\"handleClick($event)\">\n @if (loading()) {\n <span\n class=\"ea-button__spinner\"\n aria-hidden=\"true\">\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-dasharray=\"31.4\"\n stroke-dashoffset=\"10\" />\n </svg>\n </span>\n }\n\n <span\n class=\"ea-button__content\"\n [class.ea-button__content--hidden]=\"loading()\">\n <ng-content select=\"[slot=prefix]\" />\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [".ea-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--inline-xs);position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);font-weight:var(--ea-button-font-weight, var(--font-weight-medium));letter-spacing:var(--letter-spacing-wide);text-decoration:none;line-height:var(--line-height-none);border-width:var(--border-width-thin);border-style:solid;border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);cursor:pointer}.ea-button:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-button--sm{padding:var(--space-1-5) var(--space-3);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2rem}.ea-button--md{padding:var(--space-2) var(--space-4);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2.5rem}.ea-button--lg{padding:var(--space-2-5) var(--space-6);font-size:var(--ea-button-font-size, var(--font-size-md));min-height:3rem}.ea-button--primary{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--color-brand-hover);border-color:var(--color-brand-hover)}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--color-brand-active);border-color:var(--color-brand-active)}.ea-button--secondary{background-color:transparent;border-color:var(--color-border-strong);color:var(--color-text-primary)}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted);border-color:var(--color-neutral-500)}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--ghost{background-color:transparent;border-color:transparent;color:var(--color-text-primary)}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted)}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--danger{background-color:var(--color-error-default);border-color:var(--color-error-default);color:var(--color-text-inverse)}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700)}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700);filter:brightness(.9)}.ea-button--full-width{width:100%}.ea-button--disabled,.ea-button:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.ea-button--loading{cursor:wait;pointer-events:none}.ea-button__content{display:inline-flex;align-items:center;gap:var(--inline-xs)}.ea-button__content--hidden{visibility:hidden}.ea-button__label{display:inline-flex;align-items:center}.ea-button__spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.ea-button__spinner svg{width:1.1em;height:1.1em;animation:ea-spin .75s linear infinite}:host(.ea-button--full-width){display:block;width:100%}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
1685
+ }, template: "<button\n class=\"ea-button\"\n [ngClass]=\"hostClasses()\"\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-current]=\"ariaCurrent() || null\"\n [attr.aria-busy]=\"loading() || null\"\n (click)=\"handleClick($event)\">\n @if (loading()) {\n <span\n class=\"ea-button__spinner\"\n aria-hidden=\"true\">\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-dasharray=\"31.4\"\n stroke-dashoffset=\"10\" />\n </svg>\n </span>\n }\n\n <span\n class=\"ea-button__content\"\n [class.ea-button__content--hidden]=\"loading()\">\n <ng-content select=\"[slot=prefix]\" />\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [".ea-button{display:inline-flex;align-items:center;justify-content:center;gap:var(--inline-xs);position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);font-weight:var(--ea-button-font-weight, var(--font-weight-medium));letter-spacing:var(--letter-spacing-wide);text-decoration:none;line-height:var(--line-height-none);border-width:var(--border-width-thin);border-style:solid;border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);cursor:pointer}.ea-button:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-button--sm{padding:var(--space-1-5) var(--space-3);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2rem}.ea-button--md{padding:var(--space-2) var(--space-4);font-size:var(--ea-button-font-size, var(--font-size-sm));min-height:2.5rem}.ea-button--lg{padding:var(--space-2-5) var(--space-6);font-size:var(--ea-button-font-size, var(--font-size-md));min-height:3rem}.ea-button--primary{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--color-brand-hover);border-color:var(--color-brand-hover)}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--color-brand-active);border-color:var(--color-brand-active)}.ea-button--secondary{background-color:transparent;border-color:var(--color-border-strong);color:var(--color-text-primary)}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted);border-color:var(--color-neutral-500)}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--ghost{background-color:transparent;border-color:transparent;color:var(--color-text-primary)}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--color-bg-muted)}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--color-neutral-200)}.ea-button--danger{background-color:var(--color-error-default);border-color:var(--color-error-default);color:var(--color-text-inverse)}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700)}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--color-error-700);border-color:var(--color-error-700);filter:brightness(.9)}.ea-button--full-width{width:100%}.ea-button--disabled,.ea-button:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.ea-button--loading{cursor:wait;pointer-events:none}.ea-button__content{display:inline-flex;align-items:center;gap:var(--inline-xs)}.ea-button__content--hidden{visibility:hidden}.ea-button__label{display:inline-flex;align-items:center}.ea-button__spinner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}.ea-button__spinner svg{width:1.1em;height:1.1em;animation:ea-spin .75s linear infinite}:host(.ea-button--full-width){display:block;width:100%}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
1525
1686
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaCurrent: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-current", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
1526
1687
 
1688
+ /**
1689
+ * Thin separator used to visually divide content. Renders horizontally by
1690
+ * default and may include an optional centred label (e.g. "or").
1691
+ */
1527
1692
  class DividerComponent {
1528
1693
  orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
1529
1694
  label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -1539,6 +1704,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1539
1704
  args: [{ selector: 'ea-divider', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-divider\"\n [ngClass]=\"hostClasses()\"\n [attr.role]=\"'separator'\"\n [attr.aria-orientation]=\"orientation()\">\n @if (label()) {\n <span class=\"ea-divider__label\">{{ label() }}</span>\n }\n</div>\n", styles: [".ea-divider{flex-shrink:0;border:0;font-family:var(--font-family-sans)}.ea-divider--horizontal{display:flex;align-items:center;width:100%;height:1px;background-color:var(--color-border-default)}.ea-divider--vertical{display:inline-block;width:1px;height:100%;min-height:1rem;background-color:var(--color-border-default)}.ea-divider--with-label{height:auto;background-color:transparent;gap:var(--space-3)}.ea-divider--with-label:before,.ea-divider--with-label:after{content:\"\";flex:1;height:1px;background-color:var(--color-border-default)}.ea-divider__label{flex-shrink:0;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary);white-space:nowrap}\n"] }]
1540
1705
  }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
1541
1706
 
1707
+ /**
1708
+ * Surface for grouping related content. Provides optional `header` and
1709
+ * `footer` content slots and supports elevated, outlined, and filled
1710
+ * variants. The card shadow can be customised per instance via the
1711
+ * `--ea-card-shadow` CSS custom property.
1712
+ */
1542
1713
  class CardComponent {
1543
1714
  // Inputs
1544
1715
  variant = input('elevated', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -1553,34 +1724,47 @@ class CardComponent {
1553
1724
  'ea-card--full-width': this.fullWidth(),
1554
1725
  }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
1555
1726
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1556
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CardComponent, isStandalone: true, selector: "ea-card", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, headerAlign: { classPropertyName: "headerAlign", publicName: "headerAlign", isSignal: true, isRequired: false, transformFunction: null }, headerDivider: { classPropertyName: "headerDivider", publicName: "headerDivider", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-card\"\n [ngClass]=\"hostClasses()\">\n <div\n class=\"ea-card__header\"\n [style.text-align]=\"headerAlign()\">\n <ng-content select=\"[eaCardHeader]\" />\n </div>\n\n @if (headerDivider()) {\n <ea-divider class=\"ea-card__divider\" />\n }\n\n <div class=\"ea-card__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-card__footer\">\n <ng-content select=\"[eaCardFooter]\" />\n </div>\n</div>\n", styles: ["ea-card{display:block;min-height:0}.ea-card{display:flex;flex-direction:column;min-height:0;border-radius:var(--radius-lg);font-family:var(--font-family-sans);color:var(--color-text-primary);overflow:hidden}.ea-card--elevated{background-color:var(--color-bg-base);box-shadow:var(--ea-card-shadow, var(--shadow-md))}.ea-card--outlined{background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default)}.ea-card--filled{background-color:var(--color-bg-subtle)}.ea-card--padding-none .ea-card__header{padding:var(--ea-card-header-padding, 0)}.ea-card--padding-none .ea-card__body{padding:var(--ea-card-body-padding, 0)}.ea-card--padding-none .ea-card__footer{padding:var(--ea-card-footer-padding, 0)}.ea-card--padding-sm .ea-card__header{padding:var(--ea-card-header-padding, var(--space-3) var(--space-3) 0)}.ea-card--padding-sm .ea-card__body{padding:var(--ea-card-body-padding, var(--space-3))}.ea-card--padding-sm .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-3) var(--space-3))}.ea-card--padding-md .ea-card__header{padding:var(--ea-card-header-padding, var(--space-4) var(--space-4) 0)}.ea-card--padding-md .ea-card__body{padding:var(--ea-card-body-padding, var(--space-4))}.ea-card--padding-md .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-4) var(--space-4))}.ea-card--padding-lg .ea-card__header{padding:var(--ea-card-header-padding, var(--space-6) var(--space-6) 0)}.ea-card--padding-lg .ea-card__body{padding:var(--ea-card-body-padding, var(--space-6))}.ea-card--padding-lg .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-6) var(--space-6))}.ea-card--padding-xl .ea-card__header{padding:var(--ea-card-header-padding, var(--space-8) var(--space-8) 0)}.ea-card--padding-xl .ea-card__body{padding:var(--ea-card-body-padding, var(--space-8))}.ea-card--padding-xl .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-8) var(--space-8))}.ea-card--full-width{width:100%}.ea-card__divider{margin:var(--space-2) var(--space-4) 0}.ea-card__header:empty,.ea-card__footer:empty{display:none}.ea-card__header{font-size:var(--text-label-lg-size);font-weight:var(--text-label-lg-weight);line-height:var(--text-label-lg-lh)}.ea-card__body{flex:1;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-card__footer{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}.ea-card__footer>*{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: DividerComponent, selector: "ea-divider", inputs: ["orientation", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1727
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CardComponent, isStandalone: true, selector: "ea-card", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, headerAlign: { classPropertyName: "headerAlign", publicName: "headerAlign", isSignal: true, isRequired: false, transformFunction: null }, headerDivider: { classPropertyName: "headerDivider", publicName: "headerDivider", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-card\"\n [ngClass]=\"hostClasses()\">\n <div\n class=\"ea-card__header\"\n [style.text-align]=\"headerAlign()\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n @if (headerDivider()) {\n <ea-divider class=\"ea-card__divider\" />\n }\n\n <div class=\"ea-card__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-card__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n</div>\n", styles: ["ea-card{display:block;min-height:0}.ea-card{display:flex;flex-direction:column;min-height:0;border-radius:var(--radius-lg);font-family:var(--font-family-sans);color:var(--color-text-primary);overflow:hidden}.ea-card--elevated{background-color:var(--color-bg-base);box-shadow:var(--ea-card-shadow, var(--shadow-md))}.ea-card--outlined{background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default)}.ea-card--filled{background-color:var(--color-bg-subtle)}.ea-card--padding-none .ea-card__header{padding:var(--ea-card-header-padding, 0)}.ea-card--padding-none .ea-card__body{padding:var(--ea-card-body-padding, 0)}.ea-card--padding-none .ea-card__footer{padding:var(--ea-card-footer-padding, 0)}.ea-card--padding-sm .ea-card__header{padding:var(--ea-card-header-padding, var(--space-3) var(--space-3) 0)}.ea-card--padding-sm .ea-card__body{padding:var(--ea-card-body-padding, var(--space-3))}.ea-card--padding-sm .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-3) var(--space-3))}.ea-card--padding-md .ea-card__header{padding:var(--ea-card-header-padding, var(--space-4) var(--space-4) 0)}.ea-card--padding-md .ea-card__body{padding:var(--ea-card-body-padding, var(--space-4))}.ea-card--padding-md .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-4) var(--space-4))}.ea-card--padding-lg .ea-card__header{padding:var(--ea-card-header-padding, var(--space-6) var(--space-6) 0)}.ea-card--padding-lg .ea-card__body{padding:var(--ea-card-body-padding, var(--space-6))}.ea-card--padding-lg .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-6) var(--space-6))}.ea-card--padding-xl .ea-card__header{padding:var(--ea-card-header-padding, var(--space-8) var(--space-8) 0)}.ea-card--padding-xl .ea-card__body{padding:var(--ea-card-body-padding, var(--space-8))}.ea-card--padding-xl .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-8) var(--space-8))}.ea-card--full-width{width:100%}.ea-card__divider{margin:var(--space-2) var(--space-4) 0}.ea-card__header:empty,.ea-card__footer:empty{display:none}.ea-card__header{font-size:var(--text-label-lg-size);font-weight:var(--text-label-lg-weight);line-height:var(--text-label-lg-lh)}.ea-card__body{flex:1;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-card__footer{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}.ea-card__footer>*{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: DividerComponent, selector: "ea-divider", inputs: ["orientation", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1557
1728
  }
1558
1729
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CardComponent, decorators: [{
1559
1730
  type: Component,
1560
- args: [{ selector: 'ea-card', imports: [NgClass, DividerComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-card\"\n [ngClass]=\"hostClasses()\">\n <div\n class=\"ea-card__header\"\n [style.text-align]=\"headerAlign()\">\n <ng-content select=\"[eaCardHeader]\" />\n </div>\n\n @if (headerDivider()) {\n <ea-divider class=\"ea-card__divider\" />\n }\n\n <div class=\"ea-card__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-card__footer\">\n <ng-content select=\"[eaCardFooter]\" />\n </div>\n</div>\n", styles: ["ea-card{display:block;min-height:0}.ea-card{display:flex;flex-direction:column;min-height:0;border-radius:var(--radius-lg);font-family:var(--font-family-sans);color:var(--color-text-primary);overflow:hidden}.ea-card--elevated{background-color:var(--color-bg-base);box-shadow:var(--ea-card-shadow, var(--shadow-md))}.ea-card--outlined{background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default)}.ea-card--filled{background-color:var(--color-bg-subtle)}.ea-card--padding-none .ea-card__header{padding:var(--ea-card-header-padding, 0)}.ea-card--padding-none .ea-card__body{padding:var(--ea-card-body-padding, 0)}.ea-card--padding-none .ea-card__footer{padding:var(--ea-card-footer-padding, 0)}.ea-card--padding-sm .ea-card__header{padding:var(--ea-card-header-padding, var(--space-3) var(--space-3) 0)}.ea-card--padding-sm .ea-card__body{padding:var(--ea-card-body-padding, var(--space-3))}.ea-card--padding-sm .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-3) var(--space-3))}.ea-card--padding-md .ea-card__header{padding:var(--ea-card-header-padding, var(--space-4) var(--space-4) 0)}.ea-card--padding-md .ea-card__body{padding:var(--ea-card-body-padding, var(--space-4))}.ea-card--padding-md .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-4) var(--space-4))}.ea-card--padding-lg .ea-card__header{padding:var(--ea-card-header-padding, var(--space-6) var(--space-6) 0)}.ea-card--padding-lg .ea-card__body{padding:var(--ea-card-body-padding, var(--space-6))}.ea-card--padding-lg .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-6) var(--space-6))}.ea-card--padding-xl .ea-card__header{padding:var(--ea-card-header-padding, var(--space-8) var(--space-8) 0)}.ea-card--padding-xl .ea-card__body{padding:var(--ea-card-body-padding, var(--space-8))}.ea-card--padding-xl .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-8) var(--space-8))}.ea-card--full-width{width:100%}.ea-card__divider{margin:var(--space-2) var(--space-4) 0}.ea-card__header:empty,.ea-card__footer:empty{display:none}.ea-card__header{font-size:var(--text-label-lg-size);font-weight:var(--text-label-lg-weight);line-height:var(--text-label-lg-lh)}.ea-card__body{flex:1;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-card__footer{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}.ea-card__footer>*{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}\n"] }]
1731
+ args: [{ selector: 'ea-card', imports: [NgClass, DividerComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-card\"\n [ngClass]=\"hostClasses()\">\n <div\n class=\"ea-card__header\"\n [style.text-align]=\"headerAlign()\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n @if (headerDivider()) {\n <ea-divider class=\"ea-card__divider\" />\n }\n\n <div class=\"ea-card__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-card__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n</div>\n", styles: ["ea-card{display:block;min-height:0}.ea-card{display:flex;flex-direction:column;min-height:0;border-radius:var(--radius-lg);font-family:var(--font-family-sans);color:var(--color-text-primary);overflow:hidden}.ea-card--elevated{background-color:var(--color-bg-base);box-shadow:var(--ea-card-shadow, var(--shadow-md))}.ea-card--outlined{background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default)}.ea-card--filled{background-color:var(--color-bg-subtle)}.ea-card--padding-none .ea-card__header{padding:var(--ea-card-header-padding, 0)}.ea-card--padding-none .ea-card__body{padding:var(--ea-card-body-padding, 0)}.ea-card--padding-none .ea-card__footer{padding:var(--ea-card-footer-padding, 0)}.ea-card--padding-sm .ea-card__header{padding:var(--ea-card-header-padding, var(--space-3) var(--space-3) 0)}.ea-card--padding-sm .ea-card__body{padding:var(--ea-card-body-padding, var(--space-3))}.ea-card--padding-sm .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-3) var(--space-3))}.ea-card--padding-md .ea-card__header{padding:var(--ea-card-header-padding, var(--space-4) var(--space-4) 0)}.ea-card--padding-md .ea-card__body{padding:var(--ea-card-body-padding, var(--space-4))}.ea-card--padding-md .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-4) var(--space-4))}.ea-card--padding-lg .ea-card__header{padding:var(--ea-card-header-padding, var(--space-6) var(--space-6) 0)}.ea-card--padding-lg .ea-card__body{padding:var(--ea-card-body-padding, var(--space-6))}.ea-card--padding-lg .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-6) var(--space-6))}.ea-card--padding-xl .ea-card__header{padding:var(--ea-card-header-padding, var(--space-8) var(--space-8) 0)}.ea-card--padding-xl .ea-card__body{padding:var(--ea-card-body-padding, var(--space-8))}.ea-card--padding-xl .ea-card__footer{padding:var(--ea-card-footer-padding, 0 var(--space-8) var(--space-8))}.ea-card--full-width{width:100%}.ea-card__divider{margin:var(--space-2) var(--space-4) 0}.ea-card__header:empty,.ea-card__footer:empty{display:none}.ea-card__header{font-size:var(--text-label-lg-size);font-weight:var(--text-label-lg-weight);line-height:var(--text-label-lg-lh)}.ea-card__body{flex:1;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-card__footer{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}.ea-card__footer>*{display:flex;align-items:center;justify-content:center;gap:var(--space-3)}\n"] }]
1561
1732
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], headerAlign: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerAlign", required: false }] }], headerDivider: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerDivider", required: false }] }] } });
1562
1733
 
1734
+ /**
1735
+ * Boolean form control with support for an indeterminate visual state. Pairs
1736
+ * a visually hidden native input with a custom checkmark and integrates with
1737
+ * Angular forms via `ControlValueAccessor`.
1738
+ */
1563
1739
  class CheckboxComponent {
1564
1740
  // Inputs
1565
1741
  label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1742
+ hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
1743
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
1566
1744
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1567
1745
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
1568
1746
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
1569
1747
  indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
1748
+ ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
1570
1749
  id = input(`ea-checkbox-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
1571
1750
  // Two-way checked binding
1572
1751
  checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
1573
1752
  // Outputs
1753
+ /** Fires with the new checked state whenever the user toggles the checkbox. */
1574
1754
  changed = output();
1575
1755
  // Internal state
1576
1756
  _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
1577
1757
  // Computed
1578
1758
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
1759
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
1760
+ showError = this.hasError;
1761
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
1579
1762
  hostClasses = computed(() => ({
1580
1763
  [`ea-checkbox--${this.size()}`]: true,
1581
1764
  'ea-checkbox--disabled': this.isDisabled(),
1582
1765
  'ea-checkbox--checked': this.checked(),
1583
1766
  'ea-checkbox--indeterminate': this.indeterminate(),
1767
+ 'ea-checkbox--error': this.hasError(),
1584
1768
  }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
1585
1769
  // ControlValueAccessor callbacks
1586
1770
  onChange = () => { };
@@ -1609,13 +1793,13 @@ class CheckboxComponent {
1609
1793
  this.changed.emit(newValue);
1610
1794
  }
1611
1795
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1612
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CheckboxComponent, isStandalone: true, selector: "ea-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", changed: "changed" }, providers: [
1796
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CheckboxComponent, isStandalone: true, selector: "ea-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", changed: "changed" }, providers: [
1613
1797
  {
1614
1798
  provide: NG_VALUE_ACCESSOR,
1615
1799
  useExisting: forwardRef(() => CheckboxComponent),
1616
1800
  multi: true,
1617
1801
  },
1618
- ], ngImport: i0, template: "<label\n class=\"ea-checkbox\"\n [ngClass]=\"hostClasses()\"\n [for]=\"id()\">\n <input\n #inputEl\n type=\"checkbox\"\n class=\"ea-checkbox__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.aria-checked]=\"indeterminate() ? 'mixed' : checked()\"\n (change)=\"handleChange()\" />\n\n <span\n class=\"ea-checkbox__box\"\n aria-hidden=\"true\">\n @if (indeterminate()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M4 8h8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\" />\n </svg>\n } @else if (checked()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n }\n </span>\n\n @if (label()) {\n <span class=\"ea-checkbox__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".ea-checkbox{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--sm .ea-checkbox__box{width:1rem;height:1rem;border-radius:var(--radius-sm)}.ea-checkbox--sm .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1rem}.ea-checkbox--md .ea-checkbox__box{width:1.25rem;height:1.25rem;border-radius:var(--radius-sm)}.ea-checkbox--md .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1.25rem}.ea-checkbox--lg .ea-checkbox__box{width:1.5rem;height:1.5rem;border-radius:var(--radius-sm)}.ea-checkbox--lg .ea-checkbox__label{font-size:var(--font-size-md);line-height:1.5rem}.ea-checkbox--disabled{opacity:.45;cursor:not-allowed}.ea-checkbox--checked .ea-checkbox__box,.ea-checkbox--indeterminate .ea-checkbox__box{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-checkbox:hover:not(.ea-checkbox--disabled) .ea-checkbox__box{border-color:var(--color-brand-default)}.ea-checkbox__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-checkbox__input:focus-visible+.ea-checkbox__box{box-shadow:var(--shadow-focus-ring)}.ea-checkbox__box{position:relative;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-strong);transition:var(--transition-colors),var(--transition-shadow)}.ea-checkbox__box svg{position:absolute;width:65%;height:65%}.ea-checkbox__label{font-weight:var(--font-weight-regular)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1802
+ ], ngImport: i0, template: "<div class=\"ea-checkbox-field\">\n <label\n class=\"ea-checkbox\"\n [ngClass]=\"hostClasses()\"\n [for]=\"id()\">\n <input\n #inputEl\n type=\"checkbox\"\n class=\"ea-checkbox__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.aria-checked]=\"indeterminate() ? 'mixed' : checked()\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (change)=\"handleChange()\" />\n\n <span\n class=\"ea-checkbox__box\"\n aria-hidden=\"true\">\n @if (indeterminate()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M4 8h8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\" />\n </svg>\n } @else if (checked()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n }\n </span>\n\n @if (label()) {\n <span\n class=\"ea-checkbox__label\"\n [class.ea-checkbox__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n </label>\n\n @if (showError()) {\n <p\n class=\"ea-checkbox-field__message ea-checkbox-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-checkbox-field__message ea-checkbox-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-checkbox-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-checkbox-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-checkbox-field__message--hint{color:var(--color-text-secondary)}.ea-checkbox-field__message--error{color:var(--color-error-default)}.ea-checkbox{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--sm .ea-checkbox__box{width:1rem;height:1rem;border-radius:var(--radius-sm)}.ea-checkbox--sm .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1rem}.ea-checkbox--md .ea-checkbox__box{width:1.25rem;height:1.25rem;border-radius:var(--radius-sm)}.ea-checkbox--md .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1.25rem}.ea-checkbox--lg .ea-checkbox__box{width:1.5rem;height:1.5rem;border-radius:var(--radius-sm)}.ea-checkbox--lg .ea-checkbox__label{font-size:var(--font-size-md);line-height:1.5rem}.ea-checkbox--disabled{opacity:.45;cursor:not-allowed}.ea-checkbox--checked .ea-checkbox__box,.ea-checkbox--indeterminate .ea-checkbox__box{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-checkbox:hover:not(.ea-checkbox--disabled) .ea-checkbox__box{border-color:var(--color-brand-default)}.ea-checkbox__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-checkbox__input:focus-visible+.ea-checkbox__box{box-shadow:var(--shadow-focus-ring)}.ea-checkbox__box{position:relative;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-strong);transition:var(--transition-colors),var(--transition-shadow)}.ea-checkbox__box svg{position:absolute;width:65%;height:65%}.ea-checkbox__label{font-weight:var(--font-weight-regular)}.ea-checkbox__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-checkbox--error .ea-checkbox__box{border-color:var(--color-error-default)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1619
1803
  }
1620
1804
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CheckboxComponent, decorators: [{
1621
1805
  type: Component,
@@ -1625,8 +1809,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1625
1809
  useExisting: forwardRef(() => CheckboxComponent),
1626
1810
  multi: true,
1627
1811
  },
1628
- ], template: "<label\n class=\"ea-checkbox\"\n [ngClass]=\"hostClasses()\"\n [for]=\"id()\">\n <input\n #inputEl\n type=\"checkbox\"\n class=\"ea-checkbox__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.aria-checked]=\"indeterminate() ? 'mixed' : checked()\"\n (change)=\"handleChange()\" />\n\n <span\n class=\"ea-checkbox__box\"\n aria-hidden=\"true\">\n @if (indeterminate()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M4 8h8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\" />\n </svg>\n } @else if (checked()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n }\n </span>\n\n @if (label()) {\n <span class=\"ea-checkbox__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".ea-checkbox{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--sm .ea-checkbox__box{width:1rem;height:1rem;border-radius:var(--radius-sm)}.ea-checkbox--sm .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1rem}.ea-checkbox--md .ea-checkbox__box{width:1.25rem;height:1.25rem;border-radius:var(--radius-sm)}.ea-checkbox--md .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1.25rem}.ea-checkbox--lg .ea-checkbox__box{width:1.5rem;height:1.5rem;border-radius:var(--radius-sm)}.ea-checkbox--lg .ea-checkbox__label{font-size:var(--font-size-md);line-height:1.5rem}.ea-checkbox--disabled{opacity:.45;cursor:not-allowed}.ea-checkbox--checked .ea-checkbox__box,.ea-checkbox--indeterminate .ea-checkbox__box{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-checkbox:hover:not(.ea-checkbox--disabled) .ea-checkbox__box{border-color:var(--color-brand-default)}.ea-checkbox__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-checkbox__input:focus-visible+.ea-checkbox__box{box-shadow:var(--shadow-focus-ring)}.ea-checkbox__box{position:relative;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-strong);transition:var(--transition-colors),var(--transition-shadow)}.ea-checkbox__box svg{position:absolute;width:65%;height:65%}.ea-checkbox__label{font-weight:var(--font-weight-regular)}\n"] }]
1629
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
1812
+ ], template: "<div class=\"ea-checkbox-field\">\n <label\n class=\"ea-checkbox\"\n [ngClass]=\"hostClasses()\"\n [for]=\"id()\">\n <input\n #inputEl\n type=\"checkbox\"\n class=\"ea-checkbox__input\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [indeterminate]=\"indeterminate()\"\n [attr.aria-checked]=\"indeterminate() ? 'mixed' : checked()\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (change)=\"handleChange()\" />\n\n <span\n class=\"ea-checkbox__box\"\n aria-hidden=\"true\">\n @if (indeterminate()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M4 8h8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\" />\n </svg>\n } @else if (checked()) {\n <svg\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n }\n </span>\n\n @if (label()) {\n <span\n class=\"ea-checkbox__label\"\n [class.ea-checkbox__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n </label>\n\n @if (showError()) {\n <p\n class=\"ea-checkbox-field__message ea-checkbox-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-checkbox-field__message ea-checkbox-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-checkbox-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-checkbox-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-checkbox-field__message--hint{color:var(--color-text-secondary)}.ea-checkbox-field__message--error{color:var(--color-error-default)}.ea-checkbox{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--sm .ea-checkbox__box{width:1rem;height:1rem;border-radius:var(--radius-sm)}.ea-checkbox--sm .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1rem}.ea-checkbox--md .ea-checkbox__box{width:1.25rem;height:1.25rem;border-radius:var(--radius-sm)}.ea-checkbox--md .ea-checkbox__label{font-size:var(--font-size-sm);line-height:1.25rem}.ea-checkbox--lg .ea-checkbox__box{width:1.5rem;height:1.5rem;border-radius:var(--radius-sm)}.ea-checkbox--lg .ea-checkbox__label{font-size:var(--font-size-md);line-height:1.5rem}.ea-checkbox--disabled{opacity:.45;cursor:not-allowed}.ea-checkbox--checked .ea-checkbox__box,.ea-checkbox--indeterminate .ea-checkbox__box{background-color:var(--color-brand-default);border-color:var(--color-brand-default);color:var(--color-text-inverse)}.ea-checkbox:hover:not(.ea-checkbox--disabled) .ea-checkbox__box{border-color:var(--color-brand-default)}.ea-checkbox__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-checkbox__input:focus-visible+.ea-checkbox__box{box-shadow:var(--shadow-focus-ring)}.ea-checkbox__box{position:relative;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-sizing:border-box;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-strong);transition:var(--transition-colors),var(--transition-shadow)}.ea-checkbox__box svg{position:absolute;width:65%;height:65%}.ea-checkbox__label{font-weight:var(--font-weight-regular)}.ea-checkbox__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-checkbox--error .ea-checkbox__box{border-color:var(--color-error-default)}\n"] }]
1813
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
1630
1814
 
1631
1815
  class ArrowDownIconComponent {
1632
1816
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ArrowDownIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -1770,6 +1954,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1770
1954
  }]
1771
1955
  }] });
1772
1956
 
1957
+ /**
1958
+ * Table for tabular data with sortable columns, sticky headers, and density
1959
+ * presets. Supports striping, borders, hoverable rows, and custom cell or
1960
+ * header templates via `ng-template`. Sort state is exposed as a two-way
1961
+ * `model()` binding.
1962
+ */
1773
1963
  class DataTableComponent {
1774
1964
  columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
1775
1965
  data = input.required(...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -1781,7 +1971,8 @@ class DataTableComponent {
1781
1971
  bordered = input(false, ...(ngDevMode ? [{ debugName: "bordered" }] : /* istanbul ignore next */ []));
1782
1972
  noDataText = input('No data available', ...(ngDevMode ? [{ debugName: "noDataText" }] : /* istanbul ignore next */ []));
1783
1973
  sort = model({ column: '', direction: null }, ...(ngDevMode ? [{ debugName: "sort" }] : /* istanbul ignore next */ []));
1784
- sortChange = output();
1974
+ /** Fires whenever the sort column or direction changes via header click. */
1975
+ sorted = output();
1785
1976
  noDataTemplate = contentChild('noData', ...(ngDevMode ? [{ debugName: "noDataTemplate" }] : /* istanbul ignore next */ []));
1786
1977
  hostClasses = computed(() => ({
1787
1978
  [`ea-data-table--${this.density()}`]: true,
@@ -1838,14 +2029,14 @@ class DataTableComponent {
1838
2029
  }
1839
2030
  const next = { column: direction ? col.key : '', direction };
1840
2031
  this.sort.set(next);
1841
- this.sortChange.emit(next);
2032
+ this.sorted.emit(next);
1842
2033
  }
1843
2034
  trackByFn(_index, item) {
1844
2035
  const key = this.trackBy();
1845
2036
  return key ? item[key] : _index;
1846
2037
  }
1847
2038
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1848
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DataTableComponent, isStandalone: true, selector: "ea-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, noDataText: { classPropertyName: "noDataText", publicName: "noDataText", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sortChange", sortChange: "sortChange" }, queries: [{ propertyName: "noDataTemplate", first: true, predicate: ["noData"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ea-data-table\"\n [ngClass]=\"hostClasses()\"\n role=\"grid\">\n <table class=\"ea-data-table__table\">\n <thead class=\"ea-data-table__head\">\n <tr class=\"ea-data-table__row ea-data-table__row--header\">\n @for (col of columns(); track col.key) {\n <th\n class=\"ea-data-table__cell ea-data-table__cell--header\"\n [class.ea-data-table__cell--sortable]=\"col.sortable\"\n [class.ea-data-table__cell--sorted]=\"\n sort().column === col.key && sort().direction\n \"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n [style.width]=\"col.width ?? null\"\n [attr.aria-sort]=\"\n sort().column === col.key && sort().direction === 'asc'\n ? 'ascending'\n : sort().column === col.key && sort().direction === 'desc'\n ? 'descending'\n : col.sortable\n ? 'none'\n : null\n \"\n (click)=\"onHeaderClick(col)\"\n (keydown.enter)=\"onHeaderClick(col)\"\n (keydown.space)=\"$event.preventDefault(); onHeaderClick(col)\"\n [attr.tabindex]=\"col.sortable ? 0 : null\"\n [attr.role]=\"col.sortable ? 'columnheader button' : 'columnheader'\">\n @if (col.headerTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.headerTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\" />\n } @else {\n <span class=\"ea-data-table__header-text\">{{ col.label }}</span>\n }\n @if (col.sortable) {\n <span class=\"ea-data-table__sort-icon\">\n @if (sort().column === col.key && sort().direction === 'asc') {\n <ea-icon-arrow-up />\n } @else if (sort().column === col.key && sort().direction === 'desc') {\n <ea-icon-arrow-down />\n } @else {\n <ea-icon-chevrons-up-down />\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"ea-data-table__body\">\n @if (sortedData().length === 0) {\n <tr class=\"ea-data-table__row ea-data-table__row--empty\">\n <td\n class=\"ea-data-table__cell ea-data-table__cell--empty\"\n [attr.colspan]=\"columns().length\">\n @if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()!\" />\n } @else {\n {{ noDataText() }}\n }\n </td>\n </tr>\n } @else {\n @for (row of sortedData(); track trackByFn($index, row)) {\n <tr\n class=\"ea-data-table__row\"\n role=\"row\">\n @for (col of columns(); track col.key) {\n <td\n class=\"ea-data-table__cell\"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n role=\"gridcell\">\n @if (col.cellTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n value: getCellValue(row, col.key),\n }\" />\n } @else if (col.format) {\n {{ col.format(getCellValue(row, col.key)) }}\n } @else {\n {{ getCellValue(row, col.key) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n <ng-content select=\"ea-paginator\" />\n</div>\n", styles: [".ea-data-table{overflow-x:auto;width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-base)}.ea-data-table__table{width:100%;border-spacing:0;border-collapse:collapse;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);table-layout:auto}.ea-data-table__head{background-color:var(--color-bg-subtle)}.ea-data-table__cell--header{position:relative;font-weight:var(--font-weight-medium);font-size:var(--text-label-sm-size);line-height:var(--text-label-sm-lh);letter-spacing:var(--letter-spacing-wide);text-transform:uppercase;text-align:left;white-space:nowrap;color:var(--color-text-secondary);border-bottom:var(--border-width-thin) solid var(--color-border-default);-webkit-user-select:none;user-select:none}.ea-data-table__cell--sortable{cursor:pointer;transition:var(--transition-colors)}.ea-data-table__cell--sortable:hover{color:var(--color-text-primary);background-color:var(--color-bg-muted)}.ea-data-table__cell--sortable:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-data-table__cell--sorted{color:var(--color-brand-default)}.ea-data-table__header-text{display:inline;vertical-align:middle}.ea-data-table__sort-icon{display:inline-flex;vertical-align:middle;width:1em;height:1em;margin-left:var(--space-1);opacity:.5;transition:var(--transition-opacity)}.ea-data-table__cell--sortable:hover .ea-data-table__sort-icon,.ea-data-table__cell--sorted .ea-data-table__sort-icon{opacity:1}.ea-data-table__row{border-bottom:var(--border-width-thin) solid var(--color-border-default);transition:var(--transition-colors)}.ea-data-table__row:last-child{border-bottom:none}.ea-data-table__cell{text-align:left;vertical-align:middle}.ea-data-table__cell--align-center{text-align:center}.ea-data-table__cell--align-right{text-align:right}.ea-data-table__cell--empty{text-align:center;color:var(--color-text-tertiary);font-style:italic}.ea-data-table--compact .ea-data-table__cell{padding:var(--space-1-5) var(--space-3)}.ea-data-table--comfortable .ea-data-table__cell{padding:var(--space-2-5) var(--space-4)}.ea-data-table--spacious .ea-data-table__cell{padding:var(--space-4) var(--space-6)}.ea-data-table--sticky{max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__table{display:flex;flex-direction:column;max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__head{display:block;flex-shrink:0}.ea-data-table--sticky .ea-data-table__head .ea-data-table__row--header{display:table;width:100%;table-layout:fixed}.ea-data-table--sticky .ea-data-table__body{display:block;overflow-y:auto;flex:1 1 auto;min-height:0}.ea-data-table--sticky .ea-data-table__body .ea-data-table__row{display:table;width:100%;table-layout:fixed}.ea-data-table--striped .ea-data-table__body .ea-data-table__row:nth-child(2n){background-color:var(--color-bg-subtle)}.ea-data-table--hoverable .ea-data-table__body .ea-data-table__row:not(.ea-data-table__row--empty):hover{background-color:var(--color-bg-muted)}.ea-data-table--bordered .ea-data-table__cell{border-right:var(--border-width-thin) solid var(--color-border-default)}.ea-data-table--bordered .ea-data-table__cell:last-child{border-right:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ArrowUpIconComponent, selector: "ea-icon-arrow-up" }, { kind: "component", type: ArrowDownIconComponent, selector: "ea-icon-arrow-down" }, { kind: "component", type: ChevronsUpDownIconComponent, selector: "ea-icon-chevrons-up-down" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2039
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DataTableComponent, isStandalone: true, selector: "ea-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, trackBy: { classPropertyName: "trackBy", publicName: "trackBy", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, noDataText: { classPropertyName: "noDataText", publicName: "noDataText", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sortChange", sorted: "sorted" }, queries: [{ propertyName: "noDataTemplate", first: true, predicate: ["noData"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ea-data-table\"\n [ngClass]=\"hostClasses()\"\n role=\"grid\">\n <table class=\"ea-data-table__table\">\n <thead class=\"ea-data-table__head\">\n <tr class=\"ea-data-table__row ea-data-table__row--header\">\n @for (col of columns(); track col.key) {\n <th\n class=\"ea-data-table__cell ea-data-table__cell--header\"\n [class.ea-data-table__cell--sortable]=\"col.sortable\"\n [class.ea-data-table__cell--sorted]=\"\n sort().column === col.key && sort().direction\n \"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n [style.width]=\"col.width ?? null\"\n [attr.aria-sort]=\"\n sort().column === col.key && sort().direction === 'asc'\n ? 'ascending'\n : sort().column === col.key && sort().direction === 'desc'\n ? 'descending'\n : col.sortable\n ? 'none'\n : null\n \"\n (click)=\"onHeaderClick(col)\"\n (keydown.enter)=\"onHeaderClick(col)\"\n (keydown.space)=\"$event.preventDefault(); onHeaderClick(col)\"\n [attr.tabindex]=\"col.sortable ? 0 : null\">\n @if (col.headerTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.headerTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\" />\n } @else {\n <span class=\"ea-data-table__header-text\">{{ col.label }}</span>\n }\n @if (col.sortable) {\n <span class=\"ea-data-table__sort-icon\">\n @if (sort().column === col.key && sort().direction === 'asc') {\n <ea-icon-arrow-up />\n } @else if (sort().column === col.key && sort().direction === 'desc') {\n <ea-icon-arrow-down />\n } @else {\n <ea-icon-chevrons-up-down />\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"ea-data-table__body\">\n @if (sortedData().length === 0) {\n <tr class=\"ea-data-table__row ea-data-table__row--empty\">\n <td\n class=\"ea-data-table__cell ea-data-table__cell--empty\"\n [attr.colspan]=\"columns().length\">\n @if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()!\" />\n } @else {\n {{ noDataText() }}\n }\n </td>\n </tr>\n } @else {\n @for (row of sortedData(); track trackByFn($index, row)) {\n <tr\n class=\"ea-data-table__row\"\n role=\"row\">\n @for (col of columns(); track col.key) {\n <td\n class=\"ea-data-table__cell\"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n role=\"gridcell\">\n @if (col.cellTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n value: getCellValue(row, col.key),\n }\" />\n } @else if (col.format) {\n {{ col.format(getCellValue(row, col.key)) }}\n } @else {\n {{ getCellValue(row, col.key) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n <ng-content select=\"ea-paginator\" />\n</div>\n", styles: [".ea-data-table{overflow-x:auto;width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-base)}.ea-data-table__table{width:100%;border-spacing:0;border-collapse:collapse;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);table-layout:auto}.ea-data-table__head{background-color:var(--color-bg-subtle)}.ea-data-table__cell--header{position:relative;font-weight:var(--font-weight-medium);font-size:var(--text-label-sm-size);line-height:var(--text-label-sm-lh);letter-spacing:var(--letter-spacing-wide);text-transform:uppercase;text-align:left;white-space:nowrap;color:var(--color-text-secondary);border-bottom:var(--border-width-thin) solid var(--color-border-default);-webkit-user-select:none;user-select:none}.ea-data-table__cell--sortable{cursor:pointer;transition:var(--transition-colors)}.ea-data-table__cell--sortable:hover{color:var(--color-text-primary);background-color:var(--color-bg-muted)}.ea-data-table__cell--sortable:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-data-table__cell--sorted{color:var(--color-brand-default)}.ea-data-table__header-text{display:inline;vertical-align:middle}.ea-data-table__sort-icon{display:inline-flex;vertical-align:middle;width:1em;height:1em;margin-left:var(--space-1);opacity:.5;transition:var(--transition-opacity)}.ea-data-table__cell--sortable:hover .ea-data-table__sort-icon,.ea-data-table__cell--sorted .ea-data-table__sort-icon{opacity:1}.ea-data-table__row{border-bottom:var(--border-width-thin) solid var(--color-border-default);transition:var(--transition-colors)}.ea-data-table__row:last-child{border-bottom:none}.ea-data-table__cell{text-align:left;vertical-align:middle}.ea-data-table__cell--align-center{text-align:center}.ea-data-table__cell--align-right{text-align:right}.ea-data-table__cell--empty{text-align:center;color:var(--color-text-tertiary);font-style:italic}.ea-data-table--compact .ea-data-table__cell{padding:var(--space-1-5) var(--space-3)}.ea-data-table--comfortable .ea-data-table__cell{padding:var(--space-2-5) var(--space-4)}.ea-data-table--spacious .ea-data-table__cell{padding:var(--space-4) var(--space-6)}.ea-data-table--sticky{max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__table{display:flex;flex-direction:column;max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__head{display:block;flex-shrink:0}.ea-data-table--sticky .ea-data-table__head .ea-data-table__row--header{display:table;width:100%;table-layout:fixed}.ea-data-table--sticky .ea-data-table__body{display:block;overflow-y:auto;flex:1 1 auto;min-height:0}.ea-data-table--sticky .ea-data-table__body .ea-data-table__row{display:table;width:100%;table-layout:fixed}.ea-data-table--striped .ea-data-table__body .ea-data-table__row:nth-child(2n){background-color:var(--color-bg-subtle)}.ea-data-table--hoverable .ea-data-table__body .ea-data-table__row:not(.ea-data-table__row--empty):hover{background-color:var(--color-bg-muted)}.ea-data-table--bordered .ea-data-table__cell{border-right:var(--border-width-thin) solid var(--color-border-default)}.ea-data-table--bordered .ea-data-table__cell:last-child{border-right:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ArrowUpIconComponent, selector: "ea-icon-arrow-up" }, { kind: "component", type: ArrowDownIconComponent, selector: "ea-icon-arrow-down" }, { kind: "component", type: ChevronsUpDownIconComponent, selector: "ea-icon-chevrons-up-down" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1849
2040
  }
1850
2041
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DataTableComponent, decorators: [{
1851
2042
  type: Component,
@@ -1855,19 +2046,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1855
2046
  ArrowUpIconComponent,
1856
2047
  ArrowDownIconComponent,
1857
2048
  ChevronsUpDownIconComponent,
1858
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-data-table\"\n [ngClass]=\"hostClasses()\"\n role=\"grid\">\n <table class=\"ea-data-table__table\">\n <thead class=\"ea-data-table__head\">\n <tr class=\"ea-data-table__row ea-data-table__row--header\">\n @for (col of columns(); track col.key) {\n <th\n class=\"ea-data-table__cell ea-data-table__cell--header\"\n [class.ea-data-table__cell--sortable]=\"col.sortable\"\n [class.ea-data-table__cell--sorted]=\"\n sort().column === col.key && sort().direction\n \"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n [style.width]=\"col.width ?? null\"\n [attr.aria-sort]=\"\n sort().column === col.key && sort().direction === 'asc'\n ? 'ascending'\n : sort().column === col.key && sort().direction === 'desc'\n ? 'descending'\n : col.sortable\n ? 'none'\n : null\n \"\n (click)=\"onHeaderClick(col)\"\n (keydown.enter)=\"onHeaderClick(col)\"\n (keydown.space)=\"$event.preventDefault(); onHeaderClick(col)\"\n [attr.tabindex]=\"col.sortable ? 0 : null\"\n [attr.role]=\"col.sortable ? 'columnheader button' : 'columnheader'\">\n @if (col.headerTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.headerTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\" />\n } @else {\n <span class=\"ea-data-table__header-text\">{{ col.label }}</span>\n }\n @if (col.sortable) {\n <span class=\"ea-data-table__sort-icon\">\n @if (sort().column === col.key && sort().direction === 'asc') {\n <ea-icon-arrow-up />\n } @else if (sort().column === col.key && sort().direction === 'desc') {\n <ea-icon-arrow-down />\n } @else {\n <ea-icon-chevrons-up-down />\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"ea-data-table__body\">\n @if (sortedData().length === 0) {\n <tr class=\"ea-data-table__row ea-data-table__row--empty\">\n <td\n class=\"ea-data-table__cell ea-data-table__cell--empty\"\n [attr.colspan]=\"columns().length\">\n @if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()!\" />\n } @else {\n {{ noDataText() }}\n }\n </td>\n </tr>\n } @else {\n @for (row of sortedData(); track trackByFn($index, row)) {\n <tr\n class=\"ea-data-table__row\"\n role=\"row\">\n @for (col of columns(); track col.key) {\n <td\n class=\"ea-data-table__cell\"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n role=\"gridcell\">\n @if (col.cellTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n value: getCellValue(row, col.key),\n }\" />\n } @else if (col.format) {\n {{ col.format(getCellValue(row, col.key)) }}\n } @else {\n {{ getCellValue(row, col.key) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n <ng-content select=\"ea-paginator\" />\n</div>\n", styles: [".ea-data-table{overflow-x:auto;width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-base)}.ea-data-table__table{width:100%;border-spacing:0;border-collapse:collapse;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);table-layout:auto}.ea-data-table__head{background-color:var(--color-bg-subtle)}.ea-data-table__cell--header{position:relative;font-weight:var(--font-weight-medium);font-size:var(--text-label-sm-size);line-height:var(--text-label-sm-lh);letter-spacing:var(--letter-spacing-wide);text-transform:uppercase;text-align:left;white-space:nowrap;color:var(--color-text-secondary);border-bottom:var(--border-width-thin) solid var(--color-border-default);-webkit-user-select:none;user-select:none}.ea-data-table__cell--sortable{cursor:pointer;transition:var(--transition-colors)}.ea-data-table__cell--sortable:hover{color:var(--color-text-primary);background-color:var(--color-bg-muted)}.ea-data-table__cell--sortable:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-data-table__cell--sorted{color:var(--color-brand-default)}.ea-data-table__header-text{display:inline;vertical-align:middle}.ea-data-table__sort-icon{display:inline-flex;vertical-align:middle;width:1em;height:1em;margin-left:var(--space-1);opacity:.5;transition:var(--transition-opacity)}.ea-data-table__cell--sortable:hover .ea-data-table__sort-icon,.ea-data-table__cell--sorted .ea-data-table__sort-icon{opacity:1}.ea-data-table__row{border-bottom:var(--border-width-thin) solid var(--color-border-default);transition:var(--transition-colors)}.ea-data-table__row:last-child{border-bottom:none}.ea-data-table__cell{text-align:left;vertical-align:middle}.ea-data-table__cell--align-center{text-align:center}.ea-data-table__cell--align-right{text-align:right}.ea-data-table__cell--empty{text-align:center;color:var(--color-text-tertiary);font-style:italic}.ea-data-table--compact .ea-data-table__cell{padding:var(--space-1-5) var(--space-3)}.ea-data-table--comfortable .ea-data-table__cell{padding:var(--space-2-5) var(--space-4)}.ea-data-table--spacious .ea-data-table__cell{padding:var(--space-4) var(--space-6)}.ea-data-table--sticky{max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__table{display:flex;flex-direction:column;max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__head{display:block;flex-shrink:0}.ea-data-table--sticky .ea-data-table__head .ea-data-table__row--header{display:table;width:100%;table-layout:fixed}.ea-data-table--sticky .ea-data-table__body{display:block;overflow-y:auto;flex:1 1 auto;min-height:0}.ea-data-table--sticky .ea-data-table__body .ea-data-table__row{display:table;width:100%;table-layout:fixed}.ea-data-table--striped .ea-data-table__body .ea-data-table__row:nth-child(2n){background-color:var(--color-bg-subtle)}.ea-data-table--hoverable .ea-data-table__body .ea-data-table__row:not(.ea-data-table__row--empty):hover{background-color:var(--color-bg-muted)}.ea-data-table--bordered .ea-data-table__cell{border-right:var(--border-width-thin) solid var(--color-border-default)}.ea-data-table--bordered .ea-data-table__cell:last-child{border-right:none}\n"] }]
1859
- }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], noDataText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noDataText", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }, { type: i0.Output, args: ["sortChange"] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], noDataTemplate: [{ type: i0.ContentChild, args: ['noData', { isSignal: true }] }] } });
2049
+ ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-data-table\"\n [ngClass]=\"hostClasses()\"\n role=\"grid\">\n <table class=\"ea-data-table__table\">\n <thead class=\"ea-data-table__head\">\n <tr class=\"ea-data-table__row ea-data-table__row--header\">\n @for (col of columns(); track col.key) {\n <th\n class=\"ea-data-table__cell ea-data-table__cell--header\"\n [class.ea-data-table__cell--sortable]=\"col.sortable\"\n [class.ea-data-table__cell--sorted]=\"\n sort().column === col.key && sort().direction\n \"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n [style.width]=\"col.width ?? null\"\n [attr.aria-sort]=\"\n sort().column === col.key && sort().direction === 'asc'\n ? 'ascending'\n : sort().column === col.key && sort().direction === 'desc'\n ? 'descending'\n : col.sortable\n ? 'none'\n : null\n \"\n (click)=\"onHeaderClick(col)\"\n (keydown.enter)=\"onHeaderClick(col)\"\n (keydown.space)=\"$event.preventDefault(); onHeaderClick(col)\"\n [attr.tabindex]=\"col.sortable ? 0 : null\">\n @if (col.headerTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.headerTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: col }\" />\n } @else {\n <span class=\"ea-data-table__header-text\">{{ col.label }}</span>\n }\n @if (col.sortable) {\n <span class=\"ea-data-table__sort-icon\">\n @if (sort().column === col.key && sort().direction === 'asc') {\n <ea-icon-arrow-up />\n } @else if (sort().column === col.key && sort().direction === 'desc') {\n <ea-icon-arrow-down />\n } @else {\n <ea-icon-chevrons-up-down />\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"ea-data-table__body\">\n @if (sortedData().length === 0) {\n <tr class=\"ea-data-table__row ea-data-table__row--empty\">\n <td\n class=\"ea-data-table__cell ea-data-table__cell--empty\"\n [attr.colspan]=\"columns().length\">\n @if (noDataTemplate()) {\n <ng-container [ngTemplateOutlet]=\"noDataTemplate()!\" />\n } @else {\n {{ noDataText() }}\n }\n </td>\n </tr>\n } @else {\n @for (row of sortedData(); track trackByFn($index, row)) {\n <tr\n class=\"ea-data-table__row\"\n role=\"row\">\n @for (col of columns(); track col.key) {\n <td\n class=\"ea-data-table__cell\"\n [class.ea-data-table__cell--align-center]=\"col.align === 'center'\"\n [class.ea-data-table__cell--align-right]=\"col.align === 'right'\"\n role=\"gridcell\">\n @if (col.cellTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"col.cellTemplate\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n value: getCellValue(row, col.key),\n }\" />\n } @else if (col.format) {\n {{ col.format(getCellValue(row, col.key)) }}\n } @else {\n {{ getCellValue(row, col.key) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n <ng-content select=\"ea-paginator\" />\n</div>\n", styles: [".ea-data-table{overflow-x:auto;width:100%;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-base)}.ea-data-table__table{width:100%;border-spacing:0;border-collapse:collapse;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);table-layout:auto}.ea-data-table__head{background-color:var(--color-bg-subtle)}.ea-data-table__cell--header{position:relative;font-weight:var(--font-weight-medium);font-size:var(--text-label-sm-size);line-height:var(--text-label-sm-lh);letter-spacing:var(--letter-spacing-wide);text-transform:uppercase;text-align:left;white-space:nowrap;color:var(--color-text-secondary);border-bottom:var(--border-width-thin) solid var(--color-border-default);-webkit-user-select:none;user-select:none}.ea-data-table__cell--sortable{cursor:pointer;transition:var(--transition-colors)}.ea-data-table__cell--sortable:hover{color:var(--color-text-primary);background-color:var(--color-bg-muted)}.ea-data-table__cell--sortable:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-data-table__cell--sorted{color:var(--color-brand-default)}.ea-data-table__header-text{display:inline;vertical-align:middle}.ea-data-table__sort-icon{display:inline-flex;vertical-align:middle;width:1em;height:1em;margin-left:var(--space-1);opacity:.5;transition:var(--transition-opacity)}.ea-data-table__cell--sortable:hover .ea-data-table__sort-icon,.ea-data-table__cell--sorted .ea-data-table__sort-icon{opacity:1}.ea-data-table__row{border-bottom:var(--border-width-thin) solid var(--color-border-default);transition:var(--transition-colors)}.ea-data-table__row:last-child{border-bottom:none}.ea-data-table__cell{text-align:left;vertical-align:middle}.ea-data-table__cell--align-center{text-align:center}.ea-data-table__cell--align-right{text-align:right}.ea-data-table__cell--empty{text-align:center;color:var(--color-text-tertiary);font-style:italic}.ea-data-table--compact .ea-data-table__cell{padding:var(--space-1-5) var(--space-3)}.ea-data-table--comfortable .ea-data-table__cell{padding:var(--space-2-5) var(--space-4)}.ea-data-table--spacious .ea-data-table__cell{padding:var(--space-4) var(--space-6)}.ea-data-table--sticky{max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__table{display:flex;flex-direction:column;max-height:inherit;height:inherit}.ea-data-table--sticky .ea-data-table__head{display:block;flex-shrink:0}.ea-data-table--sticky .ea-data-table__head .ea-data-table__row--header{display:table;width:100%;table-layout:fixed}.ea-data-table--sticky .ea-data-table__body{display:block;overflow-y:auto;flex:1 1 auto;min-height:0}.ea-data-table--sticky .ea-data-table__body .ea-data-table__row{display:table;width:100%;table-layout:fixed}.ea-data-table--striped .ea-data-table__body .ea-data-table__row:nth-child(2n){background-color:var(--color-bg-subtle)}.ea-data-table--hoverable .ea-data-table__body .ea-data-table__row:not(.ea-data-table__row--empty):hover{background-color:var(--color-bg-muted)}.ea-data-table--bordered .ea-data-table__cell{border-right:var(--border-width-thin) solid var(--color-border-default)}.ea-data-table--bordered .ea-data-table__cell:last-child{border-right:none}\n"] }]
2050
+ }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], trackBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackBy", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], noDataText: [{ type: i0.Input, args: [{ isSignal: true, alias: "noDataText", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }, { type: i0.Output, args: ["sortChange"] }], sorted: [{ type: i0.Output, args: ["sorted"] }], noDataTemplate: [{ type: i0.ContentChild, args: ['noData', { isSignal: true }] }] } });
1860
2051
 
2052
+ /**
2053
+ * Verification code entry made up of one input per digit. Auto-advances on
2054
+ * input, supports paste of the full code at once, and integrates with Angular
2055
+ * forms via `ControlValueAccessor`.
2056
+ */
1861
2057
  class CodeInputComponent {
1862
2058
  digitEls = viewChildren('digitEl', ...(ngDevMode ? [{ debugName: "digitEls" }] : /* istanbul ignore next */ []));
1863
2059
  // Inputs
1864
2060
  label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2061
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
1865
2062
  length = input(6, ...(ngDevMode ? [{ debugName: "length" }] : /* istanbul ignore next */ []));
1866
2063
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1867
- status = input('default', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
1868
2064
  hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
1869
- errorMsg = input(undefined, { ...(ngDevMode ? { debugName: "errorMsg" } : /* istanbul ignore next */ {}), alias: 'error' });
2065
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
1870
2066
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
2067
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
1871
2068
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
1872
2069
  id = input(`ea-code-input-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
1873
2070
  // Two-way value binding
@@ -1876,15 +2073,16 @@ class CodeInputComponent {
1876
2073
  focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
1877
2074
  _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
1878
2075
  // Outputs
2076
+ /** Fires with the full code once every digit has been entered. */
1879
2077
  completed = output();
1880
2078
  // ControlValueAccessor callbacks
1881
2079
  onChange = () => { };
1882
2080
  onTouched = () => { };
1883
2081
  // Computed
1884
2082
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
1885
- resolvedStatus = computed(() => this.errorMsg() ? 'error' : this.status(), ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
1886
- showError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
1887
- showHint = computed(() => !!this.hint() && !this.showError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
2083
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
2084
+ showError = this.hasError;
2085
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
1888
2086
  digits = computed(() => {
1889
2087
  const val = this.value();
1890
2088
  const len = this.length();
@@ -1904,6 +2102,8 @@ class CodeInputComponent {
1904
2102
  this._formDisabled.set(isDisabled);
1905
2103
  }
1906
2104
  handleInput(event, index) {
2105
+ if (this.readonly())
2106
+ return;
1907
2107
  const input = event.target;
1908
2108
  const char = input.value.replace(/[^0-9]/g, '').slice(-1);
1909
2109
  input.value = char;
@@ -1923,6 +2123,8 @@ class CodeInputComponent {
1923
2123
  handleKeydown(event, index) {
1924
2124
  const inputs = this.digitEls();
1925
2125
  if (event.key === 'Backspace') {
2126
+ if (this.readonly())
2127
+ return;
1926
2128
  event.preventDefault();
1927
2129
  const current = this.value();
1928
2130
  const chars = current.padEnd(this.length(), ' ').split('');
@@ -1948,6 +2150,8 @@ class CodeInputComponent {
1948
2150
  }
1949
2151
  handlePaste(event) {
1950
2152
  event.preventDefault();
2153
+ if (this.readonly())
2154
+ return;
1951
2155
  const pasted = (event.clipboardData?.getData('text') ?? '').replace(/[^0-9]/g, '');
1952
2156
  if (!pasted)
1953
2157
  return;
@@ -1969,6 +2173,7 @@ class CodeInputComponent {
1969
2173
  this.focusedIndex.set(-1);
1970
2174
  this.onTouched();
1971
2175
  }
2176
+ /** Moves keyboard focus to the next empty digit (or the last one when full). */
1972
2177
  focus() {
1973
2178
  const val = this.value();
1974
2179
  const index = Math.min(val.length, this.length() - 1);
@@ -1978,13 +2183,13 @@ class CodeInputComponent {
1978
2183
  this.digitEls()[index]?.nativeElement.focus();
1979
2184
  }
1980
2185
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CodeInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1981
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CodeInputComponent, isStandalone: true, selector: "ea-code-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", completed: "completed" }, providers: [
2186
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: CodeInputComponent, isStandalone: true, selector: "ea-code-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", completed: "completed" }, providers: [
1982
2187
  {
1983
2188
  provide: NG_VALUE_ACCESSOR,
1984
2189
  useExisting: forwardRef(() => CodeInputComponent),
1985
2190
  multi: true,
1986
2191
  },
1987
- ], viewQueries: [{ propertyName: "digitEls", predicate: ["digitEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-code-input-field\">\n @if (label()) {\n <label\n class=\"ea-code-input-field__label\"\n [class.ea-code-input-field__label--required]=\"required()\"\n [id]=\"id() + '-label'\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-code-input-group\"\n [class.ea-code-input-group--sm]=\"size() === 'sm'\"\n [class.ea-code-input-group--md]=\"size() === 'md'\"\n [class.ea-code-input-group--lg]=\"size() === 'lg'\"\n [class.ea-code-input-group--error]=\"resolvedStatus() === 'error'\"\n [class.ea-code-input-group--success]=\"resolvedStatus() === 'success'\"\n [class.ea-code-input-group--disabled]=\"isDisabled()\"\n role=\"group\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n @for (i of indices(); track i) {\n <input\n #digitEl\n class=\"ea-code-input\"\n [class.ea-code-input--focused]=\"focusedIndex() === i\"\n [class.ea-code-input--filled]=\"digits()[i] !== ''\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"1\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [value]=\"digits()[i]\"\n [attr.aria-label]=\"'Digit ' + (i + 1) + ' of ' + length()\"\n (input)=\"handleInput($event, i)\"\n (keydown)=\"handleKeydown($event, i)\"\n (paste)=\"handlePaste($event)\"\n (focus)=\"handleFocus(i)\"\n (blur)=\"handleBlur()\" />\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-code-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-code-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-code-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-code-input-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-code-input-field__message--hint{color:inherit}.ea-code-input-field__message--error{color:var(--color-error-default)}.ea-code-input-group{display:flex;gap:var(--space-2)}.ea-code-input-group--sm .ea-code-input{width:2rem;height:2.5rem;font-size:var(--font-size-md)}.ea-code-input-group--md .ea-code-input{width:2.5rem;height:3rem;font-size:var(--font-size-xl)}.ea-code-input-group--lg .ea-code-input{width:3rem;height:3.5rem;font-size:var(--font-size-2xl)}.ea-code-input-group--error .ea-code-input{border-color:var(--color-error-default)}.ea-code-input-group--error .ea-code-input--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-code-input-group--success .ea-code-input{border-color:var(--color-success-default)}.ea-code-input-group--success .ea-code-input--focused{box-shadow:var(--shadow-focus-ring-success)}.ea-code-input-group--disabled{opacity:.6}.ea-code-input-group--disabled .ea-code-input{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed}.ea-code-input{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-semibold);text-align:center;font-family:var(--font-family-sans);line-height:var(--line-height-none);letter-spacing:var(--letter-spacing-normal);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);outline:none;color:var(--color-text-primary);caret-color:transparent;transition:var(--transition-colors),var(--transition-shadow)}.ea-code-input::placeholder{color:var(--color-text-tertiary)}.ea-code-input--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-code-input--filled{border-color:var(--color-border-strong)}.ea-code-input:disabled{cursor:not-allowed}.ea-code-input::-webkit-outer-spin-button,.ea-code-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2192
+ ], viewQueries: [{ propertyName: "digitEls", predicate: ["digitEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-code-input-field\">\n @if (label()) {\n <label\n class=\"ea-code-input-field__label\"\n [class.ea-code-input-field__label--required]=\"required()\"\n [id]=\"id() + '-label'\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-code-input-group\"\n [class.ea-code-input-group--sm]=\"size() === 'sm'\"\n [class.ea-code-input-group--md]=\"size() === 'md'\"\n [class.ea-code-input-group--lg]=\"size() === 'lg'\"\n [class.ea-code-input-group--error]=\"hasError()\"\n [class.ea-code-input-group--disabled]=\"isDisabled()\"\n role=\"group\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? 'Verification code, ' + length() + ' digits' : null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n @for (i of indices(); track i) {\n <input\n #digitEl\n class=\"ea-code-input\"\n [class.ea-code-input--focused]=\"focusedIndex() === i\"\n [class.ea-code-input--filled]=\"digits()[i] !== ''\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"1\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"digits()[i]\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"'Digit ' + (i + 1) + ' of ' + length()\"\n [attr.aria-invalid]=\"hasError() || null\"\n (input)=\"handleInput($event, i)\"\n (keydown)=\"handleKeydown($event, i)\"\n (paste)=\"handlePaste($event)\"\n (focus)=\"handleFocus(i)\"\n (blur)=\"handleBlur()\" />\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-code-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-code-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-code-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-code-input-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-code-input-field__message--hint{color:inherit}.ea-code-input-field__message--error{color:var(--color-error-default)}.ea-code-input-group{display:flex;gap:var(--space-2)}.ea-code-input-group--sm .ea-code-input{width:2rem;height:2.5rem;font-size:var(--font-size-md)}.ea-code-input-group--md .ea-code-input{width:2.5rem;height:3rem;font-size:var(--font-size-xl)}.ea-code-input-group--lg .ea-code-input{width:3rem;height:3.5rem;font-size:var(--font-size-2xl)}.ea-code-input-group--error .ea-code-input{border-color:var(--color-error-default)}.ea-code-input-group--error .ea-code-input--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-code-input-group--disabled{opacity:.6}.ea-code-input-group--disabled .ea-code-input{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed}.ea-code-input{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-semibold);text-align:center;font-family:var(--font-family-sans);line-height:var(--line-height-none);letter-spacing:var(--letter-spacing-normal);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);outline:none;color:var(--color-text-primary);caret-color:transparent;transition:var(--transition-colors),var(--transition-shadow)}.ea-code-input::placeholder{color:var(--color-text-tertiary)}.ea-code-input--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-code-input--filled{border-color:var(--color-border-strong)}.ea-code-input:disabled{cursor:not-allowed}.ea-code-input::-webkit-outer-spin-button,.ea-code-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1988
2193
  }
1989
2194
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CodeInputComponent, decorators: [{
1990
2195
  type: Component,
@@ -1994,8 +2199,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1994
2199
  useExisting: forwardRef(() => CodeInputComponent),
1995
2200
  multi: true,
1996
2201
  },
1997
- ], template: "<div class=\"ea-code-input-field\">\n @if (label()) {\n <label\n class=\"ea-code-input-field__label\"\n [class.ea-code-input-field__label--required]=\"required()\"\n [id]=\"id() + '-label'\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-code-input-group\"\n [class.ea-code-input-group--sm]=\"size() === 'sm'\"\n [class.ea-code-input-group--md]=\"size() === 'md'\"\n [class.ea-code-input-group--lg]=\"size() === 'lg'\"\n [class.ea-code-input-group--error]=\"resolvedStatus() === 'error'\"\n [class.ea-code-input-group--success]=\"resolvedStatus() === 'success'\"\n [class.ea-code-input-group--disabled]=\"isDisabled()\"\n role=\"group\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n @for (i of indices(); track i) {\n <input\n #digitEl\n class=\"ea-code-input\"\n [class.ea-code-input--focused]=\"focusedIndex() === i\"\n [class.ea-code-input--filled]=\"digits()[i] !== ''\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"1\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [value]=\"digits()[i]\"\n [attr.aria-label]=\"'Digit ' + (i + 1) + ' of ' + length()\"\n (input)=\"handleInput($event, i)\"\n (keydown)=\"handleKeydown($event, i)\"\n (paste)=\"handlePaste($event)\"\n (focus)=\"handleFocus(i)\"\n (blur)=\"handleBlur()\" />\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-code-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-code-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-code-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-code-input-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-code-input-field__message--hint{color:inherit}.ea-code-input-field__message--error{color:var(--color-error-default)}.ea-code-input-group{display:flex;gap:var(--space-2)}.ea-code-input-group--sm .ea-code-input{width:2rem;height:2.5rem;font-size:var(--font-size-md)}.ea-code-input-group--md .ea-code-input{width:2.5rem;height:3rem;font-size:var(--font-size-xl)}.ea-code-input-group--lg .ea-code-input{width:3rem;height:3.5rem;font-size:var(--font-size-2xl)}.ea-code-input-group--error .ea-code-input{border-color:var(--color-error-default)}.ea-code-input-group--error .ea-code-input--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-code-input-group--success .ea-code-input{border-color:var(--color-success-default)}.ea-code-input-group--success .ea-code-input--focused{box-shadow:var(--shadow-focus-ring-success)}.ea-code-input-group--disabled{opacity:.6}.ea-code-input-group--disabled .ea-code-input{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed}.ea-code-input{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-semibold);text-align:center;font-family:var(--font-family-sans);line-height:var(--line-height-none);letter-spacing:var(--letter-spacing-normal);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);outline:none;color:var(--color-text-primary);caret-color:transparent;transition:var(--transition-colors),var(--transition-shadow)}.ea-code-input::placeholder{color:var(--color-text-tertiary)}.ea-code-input--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-code-input--filled{border-color:var(--color-border-strong)}.ea-code-input:disabled{cursor:not-allowed}.ea-code-input::-webkit-outer-spin-button,.ea-code-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] }]
1998
- }], propDecorators: { digitEls: [{ type: i0.ViewChildren, args: ['digitEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], completed: [{ type: i0.Output, args: ["completed"] }] } });
2202
+ ], template: "<div class=\"ea-code-input-field\">\n @if (label()) {\n <label\n class=\"ea-code-input-field__label\"\n [class.ea-code-input-field__label--required]=\"required()\"\n [id]=\"id() + '-label'\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-code-input-group\"\n [class.ea-code-input-group--sm]=\"size() === 'sm'\"\n [class.ea-code-input-group--md]=\"size() === 'md'\"\n [class.ea-code-input-group--lg]=\"size() === 'lg'\"\n [class.ea-code-input-group--error]=\"hasError()\"\n [class.ea-code-input-group--disabled]=\"isDisabled()\"\n role=\"group\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? 'Verification code, ' + length() + ' digits' : null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n @for (i of indices(); track i) {\n <input\n #digitEl\n class=\"ea-code-input\"\n [class.ea-code-input--focused]=\"focusedIndex() === i\"\n [class.ea-code-input--filled]=\"digits()[i] !== ''\"\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n maxlength=\"1\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"digits()[i]\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"'Digit ' + (i + 1) + ' of ' + length()\"\n [attr.aria-invalid]=\"hasError() || null\"\n (input)=\"handleInput($event, i)\"\n (keydown)=\"handleKeydown($event, i)\"\n (paste)=\"handlePaste($event)\"\n (focus)=\"handleFocus(i)\"\n (blur)=\"handleBlur()\" />\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-code-input-field__message ea-code-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-code-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-code-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-code-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-code-input-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-code-input-field__message--hint{color:inherit}.ea-code-input-field__message--error{color:var(--color-error-default)}.ea-code-input-group{display:flex;gap:var(--space-2)}.ea-code-input-group--sm .ea-code-input{width:2rem;height:2.5rem;font-size:var(--font-size-md)}.ea-code-input-group--md .ea-code-input{width:2.5rem;height:3rem;font-size:var(--font-size-xl)}.ea-code-input-group--lg .ea-code-input{width:3rem;height:3.5rem;font-size:var(--font-size-2xl)}.ea-code-input-group--error .ea-code-input{border-color:var(--color-error-default)}.ea-code-input-group--error .ea-code-input--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-code-input-group--disabled{opacity:.6}.ea-code-input-group--disabled .ea-code-input{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed}.ea-code-input{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-semibold);text-align:center;font-family:var(--font-family-sans);line-height:var(--line-height-none);letter-spacing:var(--letter-spacing-normal);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);outline:none;color:var(--color-text-primary);caret-color:transparent;transition:var(--transition-colors),var(--transition-shadow)}.ea-code-input::placeholder{color:var(--color-text-tertiary)}.ea-code-input--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-code-input--filled{border-color:var(--color-border-strong)}.ea-code-input:disabled{cursor:not-allowed}.ea-code-input::-webkit-outer-spin-button,.ea-code-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\n"] }]
2203
+ }], propDecorators: { digitEls: [{ type: i0.ViewChildren, args: ['digitEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], completed: [{ type: i0.Output, args: ["completed"] }] } });
1999
2204
 
2000
2205
  class CalendarIconComponent {
2001
2206
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CalendarIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -2119,17 +2324,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2119
2324
  }]
2120
2325
  }] });
2121
2326
 
2327
+ /**
2328
+ * Calendar popover for selecting a single date. Supports `min`/`max` bounds,
2329
+ * configurable week start, locale-aware formatting via `Intl.DateTimeFormat`,
2330
+ * and full keyboard navigation (arrows, PageUp/PageDown, Home/End, Enter,
2331
+ * Escape). Integrates with Angular forms via `ControlValueAccessor`.
2332
+ */
2122
2333
  class DatePickerComponent {
2123
2334
  hostEl = viewChild('hostEl', ...(ngDevMode ? [{ debugName: "hostEl" }] : /* istanbul ignore next */ []));
2124
2335
  triggerEl = viewChild('triggerEl', ...(ngDevMode ? [{ debugName: "triggerEl" }] : /* istanbul ignore next */ []));
2336
+ injector = inject(Injector);
2125
2337
  // Inputs
2126
2338
  label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2127
2339
  placeholder = input('Select date…', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
2128
2340
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2129
2341
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
2342
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
2130
2343
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
2131
2344
  hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
2132
- errorMsg = input(undefined, { ...(ngDevMode ? { debugName: "errorMsg" } : /* istanbul ignore next */ {}), alias: 'error' });
2345
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
2133
2346
  minDate = input(null, ...(ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []));
2134
2347
  maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []));
2135
2348
  format = input('medium', ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
@@ -2139,6 +2352,7 @@ class DatePickerComponent {
2139
2352
  // Two-way value binding (Date at local midnight, or null)
2140
2353
  value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2141
2354
  // Outputs
2355
+ /** Fires when the selected date changes, including when cleared. */
2142
2356
  changed = output();
2143
2357
  // Internal state
2144
2358
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
@@ -2151,12 +2365,12 @@ class DatePickerComponent {
2151
2365
  onTouched = () => { };
2152
2366
  // Computed
2153
2367
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
2154
- resolvedStatus = computed(() => (this.errorMsg() ? 'error' : 'default'), ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
2155
- showError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
2156
- showHint = computed(() => !!this.hint() && !this.showError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
2368
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
2369
+ showError = this.hasError;
2370
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
2157
2371
  triggerClasses = computed(() => ({
2158
2372
  [`ea-date-picker__trigger--${this.size()}`]: true,
2159
- [`ea-date-picker__trigger--${this.resolvedStatus()}`]: true,
2373
+ 'ea-date-picker__trigger--error': this.hasError(),
2160
2374
  'ea-date-picker__trigger--open': this.isOpen(),
2161
2375
  'ea-date-picker__trigger--disabled': this.isDisabled(),
2162
2376
  }), ...(ngDevMode ? [{ debugName: "triggerClasses" }] : /* istanbul ignore next */ []));
@@ -2239,8 +2453,9 @@ class DatePickerComponent {
2239
2453
  this._formDisabled.set(isDisabled);
2240
2454
  }
2241
2455
  // Handlers
2456
+ /** Toggles the calendar popover between open and closed. */
2242
2457
  toggle() {
2243
- if (this.isDisabled())
2458
+ if (this.isDisabled() || this.readonly())
2244
2459
  return;
2245
2460
  if (this.isOpen()) {
2246
2461
  this.close();
@@ -2249,19 +2464,31 @@ class DatePickerComponent {
2249
2464
  this.open();
2250
2465
  }
2251
2466
  }
2467
+ /** Opens the calendar popover and moves focus to the focused day cell. */
2252
2468
  open() {
2253
- if (this.isDisabled())
2469
+ if (this.isDisabled() || this.readonly())
2254
2470
  return;
2255
2471
  const current = this.value() ?? new Date();
2256
2472
  this.viewYear.set(current.getFullYear());
2257
2473
  this.viewMonth.set(current.getMonth());
2258
2474
  this.focusedDate.set(this.startOfDay(current));
2259
2475
  this.isOpen.set(true);
2476
+ afterNextRender(() => this.focusFocusedDayCell(), { injector: this.injector });
2260
2477
  }
2478
+ /** Closes the calendar popover. */
2261
2479
  close() {
2262
2480
  this.isOpen.set(false);
2263
2481
  this.focusedDate.set(null);
2264
2482
  }
2483
+ focusFocusedDayCell() {
2484
+ const host = this.hostEl()?.nativeElement;
2485
+ const focusedCell = host?.querySelector('.ea-date-picker__day--focused');
2486
+ focusedCell?.focus();
2487
+ }
2488
+ /** Moves keyboard focus to the trigger button. */
2489
+ focus() {
2490
+ this.triggerEl()?.nativeElement.focus();
2491
+ }
2265
2492
  selectDay(day) {
2266
2493
  if (day.isDisabled)
2267
2494
  return;
@@ -2273,9 +2500,10 @@ class DatePickerComponent {
2273
2500
  this.close();
2274
2501
  this.triggerEl()?.nativeElement.focus();
2275
2502
  }
2503
+ /** Clears the selected date and emits `changed` with `null`. */
2276
2504
  clear(event) {
2277
2505
  event.stopPropagation();
2278
- if (this.isDisabled())
2506
+ if (this.isDisabled() || this.readonly())
2279
2507
  return;
2280
2508
  this.value.set(null);
2281
2509
  this.onChange(null);
@@ -2447,13 +2675,13 @@ class DatePickerComponent {
2447
2675
  return result;
2448
2676
  }
2449
2677
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DatePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2450
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DatePickerComponent, isStandalone: true, selector: "ea-date-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, weekStartsOn: { classPropertyName: "weekStartsOn", publicName: "weekStartsOn", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
2678
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DatePickerComponent, isStandalone: true, selector: "ea-date-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, weekStartsOn: { classPropertyName: "weekStartsOn", publicName: "weekStartsOn", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
2451
2679
  {
2452
2680
  provide: NG_VALUE_ACCESSOR,
2453
2681
  useExisting: forwardRef(() => DatePickerComponent),
2454
2682
  multi: true,
2455
2683
  },
2456
- ], viewQueries: [{ propertyName: "hostEl", first: true, predicate: ["hostEl"], descendants: true, isSignal: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #hostEl\n class=\"ea-date-picker-field\">\n @if (label()) {\n <label\n class=\"ea-date-picker-field__label\"\n [for]=\"id()\"\n [class.ea-date-picker-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-date-picker\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-date-picker__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\">\n <ea-icon-calendar\n class=\"ea-date-picker__trigger-icon\"\n aria-hidden=\"true\" />\n <span\n class=\"ea-date-picker__trigger-value\"\n [class.ea-date-picker__trigger-value--placeholder]=\"!displayValue()\">\n {{ displayValue() || placeholder() }}\n </span>\n @if (value() && !isDisabled()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__clear\"\n aria-label=\"Clear date\"\n tabindex=\"-1\"\n (click)=\"clear($event)\">\n <span aria-hidden=\"true\">\u00D7</span>\n </button>\n }\n </button>\n\n @if (isOpen()) {\n <div\n class=\"ea-date-picker__popover\"\n role=\"dialog\"\n aria-modal=\"false\"\n [attr.aria-labelledby]=\"id() + '-label'\"\n (keydown)=\"handleGridKeydown($event)\">\n <div class=\"ea-date-picker__header\">\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous year\"\n (click)=\"goToPrevYear()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous month\"\n (click)=\"goToPrevMonth()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <span\n class=\"ea-date-picker__month-label\"\n [id]=\"id() + '-label'\"\n aria-live=\"polite\">\n {{ monthYearLabel() }}\n </span>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next year\"\n (click)=\"goToNextYear()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n </div>\n\n <div\n class=\"ea-date-picker__grid\"\n role=\"grid\">\n <div\n class=\"ea-date-picker__weekday-row\"\n role=\"row\">\n @for (label of weekdayLabels(); track label) {\n <div\n class=\"ea-date-picker__weekday\"\n role=\"columnheader\">\n {{ label }}\n </div>\n }\n </div>\n @for (week of weeks(); track $index) {\n <div\n class=\"ea-date-picker__week\"\n role=\"row\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__day\"\n role=\"gridcell\"\n [class.ea-date-picker__day--outside]=\"!day.isCurrentMonth\"\n [class.ea-date-picker__day--today]=\"day.isToday\"\n [class.ea-date-picker__day--selected]=\"day.isSelected\"\n [class.ea-date-picker__day--focused]=\"day.isFocused\"\n [class.ea-date-picker__day--disabled]=\"day.isDisabled\"\n [disabled]=\"day.isDisabled\"\n [attr.aria-selected]=\"day.isSelected\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [attr.tabindex]=\"day.isFocused ? 0 : -1\"\n (click)=\"selectDay(day)\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n\n <div class=\"ea-date-picker__footer\">\n <button\n type=\"button\"\n class=\"ea-date-picker__today-btn\"\n (click)=\"goToToday()\">\n Today\n </button>\n </div>\n </div>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-date-picker-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-date-picker-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-date-picker-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-date-picker-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-date-picker-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-date-picker-field__message--hint{color:var(--color-text-secondary)}.ea-date-picker-field__message--error{color:var(--color-error-default)}.ea-date-picker-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-date-picker{position:relative}.ea-date-picker__trigger{display:flex;align-items:center;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-date-picker__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-date-picker__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-date-picker__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-date-picker__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--error{border-color:var(--color-error-default)}.ea-date-picker__trigger--error.ea-date-picker__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-date-picker__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-date-picker__trigger-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-secondary)}.ea-date-picker__trigger-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-date-picker__trigger-value--placeholder{color:var(--color-text-tertiary)}.ea-date-picker__clear{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.25rem;height:1.25rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);font-size:1rem;line-height:1;cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__clear:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__popover{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:var(--z-index-dropdown);display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);min-width:17.5rem;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg)}.ea-date-picker__header{display:flex;align-items:center;gap:var(--space-1)}.ea-date-picker__nav-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__nav-btn:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__nav-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__nav-btn ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right{width:.875em;height:.875em}.ea-date-picker__nav-btn ea-icon-chevron-left+ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right+ea-icon-chevron-right{margin-left:-.375em}.ea-date-picker__month-label{flex:1;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);text-align:center;color:var(--color-text-primary)}.ea-date-picker__grid{display:flex;flex-direction:column;gap:var(--space-1)}.ea-date-picker__weekday-row,.ea-date-picker__week{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--space-1)}.ea-date-picker__weekday{display:flex;align-items:center;justify-content:center;height:1.5rem;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);text-transform:uppercase;color:var(--color-text-tertiary)}.ea-date-picker__day{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__day:hover:not(:disabled){background-color:var(--color-bg-muted)}.ea-date-picker__day:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__day--outside{color:var(--color-text-tertiary)}.ea-date-picker__day--today{font-weight:var(--font-weight-semibold);color:var(--color-brand-default)}.ea-date-picker__day--focused:not(.ea-date-picker__day--selected){background-color:var(--color-bg-muted)}.ea-date-picker__day--selected{background-color:var(--color-brand-default);color:var(--color-text-inverse);font-weight:var(--font-weight-medium)}.ea-date-picker__day--selected:hover{background-color:var(--color-brand-hover)}.ea-date-picker__day--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-date-picker__day--disabled:hover{background-color:transparent}.ea-date-picker__footer{display:flex;justify-content:flex-end;padding-top:var(--space-2);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-date-picker__today-btn{padding:var(--space-1) var(--space-2);border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-brand-default);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__today-btn:hover{background-color:var(--color-brand-subtle)}.ea-date-picker__today-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }, { kind: "component", type: CalendarIconComponent, selector: "ea-icon-calendar" }, { kind: "component", type: ChevronLeftIconComponent, selector: "ea-icon-chevron-left" }, { kind: "component", type: ChevronRightIconComponent, selector: "ea-icon-chevron-right" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2684
+ ], viewQueries: [{ propertyName: "hostEl", first: true, predicate: ["hostEl"], descendants: true, isSignal: true }, { propertyName: "triggerEl", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #hostEl\n class=\"ea-date-picker-field\">\n @if (label()) {\n <label\n class=\"ea-date-picker-field__label\"\n [for]=\"id()\"\n [class.ea-date-picker-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-date-picker\">\n <div class=\"ea-date-picker__trigger-wrapper\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-date-picker__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\">\n <ea-icon-calendar\n class=\"ea-date-picker__trigger-icon\"\n aria-hidden=\"true\" />\n <span\n class=\"ea-date-picker__trigger-value\"\n [class.ea-date-picker__trigger-value--placeholder]=\"!displayValue()\">\n {{ displayValue() || placeholder() }}\n </span>\n </button>\n @if (value() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__clear\"\n aria-label=\"Clear date\"\n (click)=\"clear($event)\">\n <span aria-hidden=\"true\">\u00D7</span>\n </button>\n }\n </div>\n\n @if (isOpen()) {\n <div\n class=\"ea-date-picker__popover\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"id() + '-label'\"\n (keydown)=\"handleGridKeydown($event)\">\n <div class=\"ea-date-picker__header\">\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous year\"\n (click)=\"goToPrevYear()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous month\"\n (click)=\"goToPrevMonth()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <span\n class=\"ea-date-picker__month-label\"\n [id]=\"id() + '-label'\"\n aria-live=\"polite\">\n {{ monthYearLabel() }}\n </span>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next year\"\n (click)=\"goToNextYear()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n </div>\n\n <div\n class=\"ea-date-picker__grid\"\n role=\"grid\">\n <div\n class=\"ea-date-picker__weekday-row\"\n role=\"row\">\n @for (label of weekdayLabels(); track label) {\n <div\n class=\"ea-date-picker__weekday\"\n role=\"columnheader\">\n {{ label }}\n </div>\n }\n </div>\n @for (week of weeks(); track $index) {\n <div\n class=\"ea-date-picker__week\"\n role=\"row\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__day\"\n role=\"gridcell\"\n [class.ea-date-picker__day--outside]=\"!day.isCurrentMonth\"\n [class.ea-date-picker__day--today]=\"day.isToday\"\n [class.ea-date-picker__day--selected]=\"day.isSelected\"\n [class.ea-date-picker__day--focused]=\"day.isFocused\"\n [class.ea-date-picker__day--disabled]=\"day.isDisabled\"\n [disabled]=\"day.isDisabled\"\n [attr.aria-selected]=\"day.isSelected\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [attr.tabindex]=\"day.isFocused ? 0 : -1\"\n (click)=\"selectDay(day)\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n\n <div class=\"ea-date-picker__footer\">\n <button\n type=\"button\"\n class=\"ea-date-picker__today-btn\"\n (click)=\"goToToday()\">\n Today\n </button>\n </div>\n </div>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-date-picker-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-date-picker-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-date-picker-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-date-picker-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-date-picker-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-date-picker-field__message--hint{color:var(--color-text-secondary)}.ea-date-picker-field__message--error{color:var(--color-error-default)}.ea-date-picker-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-date-picker,.ea-date-picker__trigger-wrapper{position:relative}.ea-date-picker__trigger{display:flex;align-items:center;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-date-picker__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-date-picker__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-date-picker__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-date-picker__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--error{border-color:var(--color-error-default)}.ea-date-picker__trigger--error.ea-date-picker__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-date-picker__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-date-picker__trigger-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-secondary)}.ea-date-picker__trigger-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-date-picker__trigger-value--placeholder{color:var(--color-text-tertiary)}.ea-date-picker__clear{position:absolute;top:50%;right:var(--space-2);z-index:1;display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.25rem;height:1.25rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);font-size:1rem;line-height:1;cursor:pointer;transition:var(--transition-colors);transform:translateY(-50%)}.ea-date-picker__clear:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__clear:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__popover{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:var(--z-index-dropdown);display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);min-width:17.5rem;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg)}.ea-date-picker__header{display:flex;align-items:center;gap:var(--space-1)}.ea-date-picker__nav-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__nav-btn:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__nav-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__nav-btn ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right{width:.875em;height:.875em}.ea-date-picker__nav-btn ea-icon-chevron-left+ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right+ea-icon-chevron-right{margin-left:-.375em}.ea-date-picker__month-label{flex:1;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);text-align:center;color:var(--color-text-primary)}.ea-date-picker__grid{display:flex;flex-direction:column;gap:var(--space-1)}.ea-date-picker__weekday-row,.ea-date-picker__week{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--space-1)}.ea-date-picker__weekday{display:flex;align-items:center;justify-content:center;height:1.5rem;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);text-transform:uppercase;color:var(--color-text-tertiary)}.ea-date-picker__day{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__day:hover:not(:disabled){background-color:var(--color-bg-muted)}.ea-date-picker__day:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__day--outside{color:var(--color-text-tertiary)}.ea-date-picker__day--today{font-weight:var(--font-weight-semibold);color:var(--color-brand-default)}.ea-date-picker__day--focused:not(.ea-date-picker__day--selected){background-color:var(--color-bg-muted)}.ea-date-picker__day--selected{background-color:var(--color-brand-default);color:var(--color-text-inverse);font-weight:var(--font-weight-medium)}.ea-date-picker__day--selected:hover{background-color:var(--color-brand-hover)}.ea-date-picker__day--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-date-picker__day--disabled:hover{background-color:transparent}.ea-date-picker__footer{display:flex;justify-content:flex-end;padding-top:var(--space-2);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-date-picker__today-btn{padding:var(--space-1) var(--space-2);border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-brand-default);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__today-btn:hover{background-color:var(--color-brand-subtle)}.ea-date-picker__today-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }, { kind: "component", type: CalendarIconComponent, selector: "ea-icon-calendar" }, { kind: "component", type: ChevronLeftIconComponent, selector: "ea-icon-chevron-left" }, { kind: "component", type: ChevronRightIconComponent, selector: "ea-icon-chevron-right" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2457
2685
  }
2458
2686
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DatePickerComponent, decorators: [{
2459
2687
  type: Component,
@@ -2469,24 +2697,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2469
2697
  useExisting: forwardRef(() => DatePickerComponent),
2470
2698
  multi: true,
2471
2699
  },
2472
- ], template: "<div\n #hostEl\n class=\"ea-date-picker-field\">\n @if (label()) {\n <label\n class=\"ea-date-picker-field__label\"\n [for]=\"id()\"\n [class.ea-date-picker-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-date-picker\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-date-picker__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\">\n <ea-icon-calendar\n class=\"ea-date-picker__trigger-icon\"\n aria-hidden=\"true\" />\n <span\n class=\"ea-date-picker__trigger-value\"\n [class.ea-date-picker__trigger-value--placeholder]=\"!displayValue()\">\n {{ displayValue() || placeholder() }}\n </span>\n @if (value() && !isDisabled()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__clear\"\n aria-label=\"Clear date\"\n tabindex=\"-1\"\n (click)=\"clear($event)\">\n <span aria-hidden=\"true\">\u00D7</span>\n </button>\n }\n </button>\n\n @if (isOpen()) {\n <div\n class=\"ea-date-picker__popover\"\n role=\"dialog\"\n aria-modal=\"false\"\n [attr.aria-labelledby]=\"id() + '-label'\"\n (keydown)=\"handleGridKeydown($event)\">\n <div class=\"ea-date-picker__header\">\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous year\"\n (click)=\"goToPrevYear()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous month\"\n (click)=\"goToPrevMonth()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <span\n class=\"ea-date-picker__month-label\"\n [id]=\"id() + '-label'\"\n aria-live=\"polite\">\n {{ monthYearLabel() }}\n </span>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next year\"\n (click)=\"goToNextYear()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n </div>\n\n <div\n class=\"ea-date-picker__grid\"\n role=\"grid\">\n <div\n class=\"ea-date-picker__weekday-row\"\n role=\"row\">\n @for (label of weekdayLabels(); track label) {\n <div\n class=\"ea-date-picker__weekday\"\n role=\"columnheader\">\n {{ label }}\n </div>\n }\n </div>\n @for (week of weeks(); track $index) {\n <div\n class=\"ea-date-picker__week\"\n role=\"row\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__day\"\n role=\"gridcell\"\n [class.ea-date-picker__day--outside]=\"!day.isCurrentMonth\"\n [class.ea-date-picker__day--today]=\"day.isToday\"\n [class.ea-date-picker__day--selected]=\"day.isSelected\"\n [class.ea-date-picker__day--focused]=\"day.isFocused\"\n [class.ea-date-picker__day--disabled]=\"day.isDisabled\"\n [disabled]=\"day.isDisabled\"\n [attr.aria-selected]=\"day.isSelected\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [attr.tabindex]=\"day.isFocused ? 0 : -1\"\n (click)=\"selectDay(day)\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n\n <div class=\"ea-date-picker__footer\">\n <button\n type=\"button\"\n class=\"ea-date-picker__today-btn\"\n (click)=\"goToToday()\">\n Today\n </button>\n </div>\n </div>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-date-picker-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-date-picker-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-date-picker-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-date-picker-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-date-picker-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-date-picker-field__message--hint{color:var(--color-text-secondary)}.ea-date-picker-field__message--error{color:var(--color-error-default)}.ea-date-picker-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-date-picker{position:relative}.ea-date-picker__trigger{display:flex;align-items:center;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-date-picker__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-date-picker__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-date-picker__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-date-picker__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--error{border-color:var(--color-error-default)}.ea-date-picker__trigger--error.ea-date-picker__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-date-picker__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-date-picker__trigger-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-secondary)}.ea-date-picker__trigger-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-date-picker__trigger-value--placeholder{color:var(--color-text-tertiary)}.ea-date-picker__clear{display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.25rem;height:1.25rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);font-size:1rem;line-height:1;cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__clear:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__popover{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:var(--z-index-dropdown);display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);min-width:17.5rem;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg)}.ea-date-picker__header{display:flex;align-items:center;gap:var(--space-1)}.ea-date-picker__nav-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__nav-btn:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__nav-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__nav-btn ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right{width:.875em;height:.875em}.ea-date-picker__nav-btn ea-icon-chevron-left+ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right+ea-icon-chevron-right{margin-left:-.375em}.ea-date-picker__month-label{flex:1;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);text-align:center;color:var(--color-text-primary)}.ea-date-picker__grid{display:flex;flex-direction:column;gap:var(--space-1)}.ea-date-picker__weekday-row,.ea-date-picker__week{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--space-1)}.ea-date-picker__weekday{display:flex;align-items:center;justify-content:center;height:1.5rem;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);text-transform:uppercase;color:var(--color-text-tertiary)}.ea-date-picker__day{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__day:hover:not(:disabled){background-color:var(--color-bg-muted)}.ea-date-picker__day:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__day--outside{color:var(--color-text-tertiary)}.ea-date-picker__day--today{font-weight:var(--font-weight-semibold);color:var(--color-brand-default)}.ea-date-picker__day--focused:not(.ea-date-picker__day--selected){background-color:var(--color-bg-muted)}.ea-date-picker__day--selected{background-color:var(--color-brand-default);color:var(--color-text-inverse);font-weight:var(--font-weight-medium)}.ea-date-picker__day--selected:hover{background-color:var(--color-brand-hover)}.ea-date-picker__day--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-date-picker__day--disabled:hover{background-color:transparent}.ea-date-picker__footer{display:flex;justify-content:flex-end;padding-top:var(--space-2);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-date-picker__today-btn{padding:var(--space-1) var(--space-2);border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-brand-default);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__today-btn:hover{background-color:var(--color-brand-subtle)}.ea-date-picker__today-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"] }]
2473
- }], propDecorators: { hostEl: [{ type: i0.ViewChild, args: ['hostEl', { isSignal: true }] }], triggerEl: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], weekStartsOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekStartsOn", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }], onDocumentClick: [{
2700
+ ], template: "<div\n #hostEl\n class=\"ea-date-picker-field\">\n @if (label()) {\n <label\n class=\"ea-date-picker-field__label\"\n [for]=\"id()\"\n [class.ea-date-picker-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-date-picker\">\n <div class=\"ea-date-picker__trigger-wrapper\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-date-picker__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\">\n <ea-icon-calendar\n class=\"ea-date-picker__trigger-icon\"\n aria-hidden=\"true\" />\n <span\n class=\"ea-date-picker__trigger-value\"\n [class.ea-date-picker__trigger-value--placeholder]=\"!displayValue()\">\n {{ displayValue() || placeholder() }}\n </span>\n </button>\n @if (value() && !isDisabled() && !readonly()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__clear\"\n aria-label=\"Clear date\"\n (click)=\"clear($event)\">\n <span aria-hidden=\"true\">\u00D7</span>\n </button>\n }\n </div>\n\n @if (isOpen()) {\n <div\n class=\"ea-date-picker__popover\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"id() + '-label'\"\n (keydown)=\"handleGridKeydown($event)\">\n <div class=\"ea-date-picker__header\">\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous year\"\n (click)=\"goToPrevYear()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Previous month\"\n (click)=\"goToPrevMonth()\">\n <ea-icon-chevron-left aria-hidden=\"true\" />\n </button>\n <span\n class=\"ea-date-picker__month-label\"\n [id]=\"id() + '-label'\"\n aria-live=\"polite\">\n {{ monthYearLabel() }}\n </span>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n class=\"ea-date-picker__nav-btn\"\n aria-label=\"Next year\"\n (click)=\"goToNextYear()\">\n <ea-icon-chevron-right aria-hidden=\"true\" />\n <ea-icon-chevron-right aria-hidden=\"true\" />\n </button>\n </div>\n\n <div\n class=\"ea-date-picker__grid\"\n role=\"grid\">\n <div\n class=\"ea-date-picker__weekday-row\"\n role=\"row\">\n @for (label of weekdayLabels(); track label) {\n <div\n class=\"ea-date-picker__weekday\"\n role=\"columnheader\">\n {{ label }}\n </div>\n }\n </div>\n @for (week of weeks(); track $index) {\n <div\n class=\"ea-date-picker__week\"\n role=\"row\">\n @for (day of week; track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"ea-date-picker__day\"\n role=\"gridcell\"\n [class.ea-date-picker__day--outside]=\"!day.isCurrentMonth\"\n [class.ea-date-picker__day--today]=\"day.isToday\"\n [class.ea-date-picker__day--selected]=\"day.isSelected\"\n [class.ea-date-picker__day--focused]=\"day.isFocused\"\n [class.ea-date-picker__day--disabled]=\"day.isDisabled\"\n [disabled]=\"day.isDisabled\"\n [attr.aria-selected]=\"day.isSelected\"\n [attr.aria-current]=\"day.isToday ? 'date' : null\"\n [attr.tabindex]=\"day.isFocused ? 0 : -1\"\n (click)=\"selectDay(day)\">\n {{ day.day }}\n </button>\n }\n </div>\n }\n </div>\n\n <div class=\"ea-date-picker__footer\">\n <button\n type=\"button\"\n class=\"ea-date-picker__today-btn\"\n (click)=\"goToToday()\">\n Today\n </button>\n </div>\n </div>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-date-picker-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-date-picker-field__message ea-date-picker-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-date-picker-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-date-picker-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-date-picker-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-date-picker-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-date-picker-field__message--hint{color:var(--color-text-secondary)}.ea-date-picker-field__message--error{color:var(--color-error-default)}.ea-date-picker-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-date-picker,.ea-date-picker__trigger-wrapper{position:relative}.ea-date-picker__trigger{display:flex;align-items:center;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-date-picker__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-date-picker__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-date-picker__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-date-picker__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-date-picker__trigger--error{border-color:var(--color-error-default)}.ea-date-picker__trigger--error.ea-date-picker__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-date-picker__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-date-picker__trigger-icon{flex-shrink:0;width:1em;height:1em;color:var(--color-text-secondary)}.ea-date-picker__trigger-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-date-picker__trigger-value--placeholder{color:var(--color-text-tertiary)}.ea-date-picker__clear{position:absolute;top:50%;right:var(--space-2);z-index:1;display:flex;align-items:center;justify-content:center;flex-shrink:0;width:1.25rem;height:1.25rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);font-size:1rem;line-height:1;cursor:pointer;transition:var(--transition-colors);transform:translateY(-50%)}.ea-date-picker__clear:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__clear:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__popover{position:absolute;top:calc(100% + var(--space-1));left:0;z-index:var(--z-index-dropdown);display:flex;flex-direction:column;gap:var(--space-2);padding:var(--space-3);min-width:17.5rem;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg)}.ea-date-picker__header{display:flex;align-items:center;gap:var(--space-1)}.ea-date-picker__nav-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.75rem;height:1.75rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__nav-btn:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-date-picker__nav-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__nav-btn ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right{width:.875em;height:.875em}.ea-date-picker__nav-btn ea-icon-chevron-left+ea-icon-chevron-left,.ea-date-picker__nav-btn ea-icon-chevron-right+ea-icon-chevron-right{margin-left:-.375em}.ea-date-picker__month-label{flex:1;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);text-align:center;color:var(--color-text-primary)}.ea-date-picker__grid{display:flex;flex-direction:column;gap:var(--space-1)}.ea-date-picker__weekday-row,.ea-date-picker__week{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--space-1)}.ea-date-picker__weekday{display:flex;align-items:center;justify-content:center;height:1.5rem;font-size:var(--font-size-xs);font-weight:var(--font-weight-medium);text-transform:uppercase;color:var(--color-text-tertiary)}.ea-date-picker__day{display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__day:hover:not(:disabled){background-color:var(--color-bg-muted)}.ea-date-picker__day:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-date-picker__day--outside{color:var(--color-text-tertiary)}.ea-date-picker__day--today{font-weight:var(--font-weight-semibold);color:var(--color-brand-default)}.ea-date-picker__day--focused:not(.ea-date-picker__day--selected){background-color:var(--color-bg-muted)}.ea-date-picker__day--selected{background-color:var(--color-brand-default);color:var(--color-text-inverse);font-weight:var(--font-weight-medium)}.ea-date-picker__day--selected:hover{background-color:var(--color-brand-hover)}.ea-date-picker__day--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-date-picker__day--disabled:hover{background-color:transparent}.ea-date-picker__footer{display:flex;justify-content:flex-end;padding-top:var(--space-2);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-date-picker__today-btn{padding:var(--space-1) var(--space-2);border:none;border-radius:var(--radius-sm);background:none;font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-brand-default);cursor:pointer;transition:var(--transition-colors)}.ea-date-picker__today-btn:hover{background-color:var(--color-brand-subtle)}.ea-date-picker__today-btn:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}\n"] }]
2701
+ }], propDecorators: { hostEl: [{ type: i0.ViewChild, args: ['hostEl', { isSignal: true }] }], triggerEl: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], weekStartsOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekStartsOn", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }], onDocumentClick: [{
2474
2702
  type: HostListener,
2475
2703
  args: ['document:click', ['$event']]
2476
2704
  }] } });
2477
2705
 
2706
+ /**
2707
+ * Modal dialog backed by the native `<dialog>` element. Uses `showModal()`
2708
+ * for browser-managed focus trapping, supports backdrop and Escape dismissal,
2709
+ * and exposes `header`, default, and `footer` content slots. The `open` state
2710
+ * is a two-way `model()` binding.
2711
+ */
2478
2712
  class DialogComponent {
2479
2713
  dialogEl = viewChild('dialogEl', ...(ngDevMode ? [{ debugName: "dialogEl" }] : /* istanbul ignore next */ []));
2714
+ previouslyFocused = null;
2480
2715
  // Inputs
2481
2716
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2482
2717
  closeOnBackdrop = input(true, ...(ngDevMode ? [{ debugName: "closeOnBackdrop" }] : /* istanbul ignore next */ []));
2483
2718
  closeOnEscape = input(true, ...(ngDevMode ? [{ debugName: "closeOnEscape" }] : /* istanbul ignore next */ []));
2484
2719
  showClose = input(true, ...(ngDevMode ? [{ debugName: "showClose" }] : /* istanbul ignore next */ []));
2485
2720
  ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
2721
+ id = input(`ea-dialog-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2486
2722
  // Two-way open binding
2487
2723
  open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
2488
2724
  // Outputs
2725
+ /** Fires once the dialog has been shown via `showModal()`. */
2489
2726
  opened = output();
2727
+ /** Fires when the dialog closes (via close button, backdrop, or Escape). */
2490
2728
  closed = output();
2491
2729
  // Computed
2492
2730
  panelClasses = computed(() => ({
@@ -2499,6 +2737,7 @@ class DialogComponent {
2499
2737
  return;
2500
2738
  if (this.open()) {
2501
2739
  if (!dialogRef.open) {
2740
+ this.previouslyFocused = document.activeElement;
2502
2741
  dialogRef.showModal();
2503
2742
  this.opened.emit();
2504
2743
  }
@@ -2506,6 +2745,8 @@ class DialogComponent {
2506
2745
  else {
2507
2746
  if (dialogRef.open) {
2508
2747
  dialogRef.close();
2748
+ this.previouslyFocused?.focus?.();
2749
+ this.previouslyFocused = null;
2509
2750
  }
2510
2751
  }
2511
2752
  });
@@ -2530,15 +2771,22 @@ class DialogComponent {
2530
2771
  this.handleClose();
2531
2772
  }
2532
2773
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2533
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DialogComponent, isStandalone: true, selector: "ea-dialog", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed" }, viewQueries: [{ propertyName: "dialogEl", first: true, predicate: ["dialogEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<dialog\n #dialogEl\n class=\"ea-dialog\"\n [attr.aria-label]=\"ariaLabel()\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-dialog__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-dialog__close\"\n aria-label=\"Close dialog\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div class=\"ea-dialog__header\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-dialog__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-dialog__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-dialog{border:none;background:transparent;padding:0;margin:auto;max-width:none;max-height:none;overflow:visible}.ea-dialog::backdrop{background-color:var(--color-bg-overlay)}.ea-dialog__panel{position:relative;display:flex;flex-direction:column;background-color:var(--color-bg-base);border-radius:var(--radius-xl);box-shadow:var(--shadow-2xl);max-height:85vh;overflow:hidden}.ea-dialog__panel--sm{width:24rem}.ea-dialog__panel--md{width:32rem}.ea-dialog__panel--lg{width:42rem}.ea-dialog__panel--full{width:calc(100vw - 2rem);height:calc(100vh - 2rem);max-height:calc(100vh - 2rem)}.ea-dialog__close{position:absolute;top:var(--space-3);right:var(--space-3);display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors);z-index:1}.ea-dialog__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-dialog__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dialog__close svg{width:1rem;height:1rem}.ea-dialog__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-dialog__header:empty{display:none}.ea-dialog__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-dialog__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-dialog__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-dialog__footer:empty{display:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2774
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DialogComponent, isStandalone: true, selector: "ea-dialog", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed" }, viewQueries: [{ propertyName: "dialogEl", first: true, predicate: ["dialogEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<dialog\n #dialogEl\n class=\"ea-dialog\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"!ariaLabel() ? id() + '-header' : null\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-dialog__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-dialog__close\"\n aria-label=\"Close dialog\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div\n class=\"ea-dialog__header\"\n [id]=\"id() + '-header'\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-dialog__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-dialog__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-dialog{border:none;background:transparent;padding:0;margin:auto;max-width:none;max-height:none;overflow:visible}.ea-dialog::backdrop{background-color:var(--color-bg-overlay)}.ea-dialog__panel{position:relative;display:flex;flex-direction:column;background-color:var(--color-bg-base);border-radius:var(--radius-xl);box-shadow:var(--shadow-2xl);max-height:85vh;overflow:hidden}.ea-dialog__panel--sm{width:24rem}.ea-dialog__panel--md{width:32rem}.ea-dialog__panel--lg{width:42rem}.ea-dialog__panel--full{width:calc(100vw - 2rem);height:calc(100vh - 2rem);max-height:calc(100vh - 2rem)}.ea-dialog__close{position:absolute;top:var(--space-3);right:var(--space-3);display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors);z-index:1}.ea-dialog__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-dialog__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dialog__close svg{width:1rem;height:1rem}.ea-dialog__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-dialog__header:empty{display:none}.ea-dialog__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-dialog__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-dialog__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-dialog__footer:empty{display:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2534
2775
  }
2535
2776
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DialogComponent, decorators: [{
2536
2777
  type: Component,
2537
- args: [{ selector: 'ea-dialog', imports: [NgClass, XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<dialog\n #dialogEl\n class=\"ea-dialog\"\n [attr.aria-label]=\"ariaLabel()\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-dialog__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-dialog__close\"\n aria-label=\"Close dialog\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div class=\"ea-dialog__header\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-dialog__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-dialog__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-dialog{border:none;background:transparent;padding:0;margin:auto;max-width:none;max-height:none;overflow:visible}.ea-dialog::backdrop{background-color:var(--color-bg-overlay)}.ea-dialog__panel{position:relative;display:flex;flex-direction:column;background-color:var(--color-bg-base);border-radius:var(--radius-xl);box-shadow:var(--shadow-2xl);max-height:85vh;overflow:hidden}.ea-dialog__panel--sm{width:24rem}.ea-dialog__panel--md{width:32rem}.ea-dialog__panel--lg{width:42rem}.ea-dialog__panel--full{width:calc(100vw - 2rem);height:calc(100vh - 2rem);max-height:calc(100vh - 2rem)}.ea-dialog__close{position:absolute;top:var(--space-3);right:var(--space-3);display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors);z-index:1}.ea-dialog__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-dialog__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dialog__close svg{width:1rem;height:1rem}.ea-dialog__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-dialog__header:empty{display:none}.ea-dialog__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-dialog__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-dialog__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-dialog__footer:empty{display:none}\n"] }]
2538
- }], ctorParameters: () => [], propDecorators: { dialogEl: [{ type: i0.ViewChild, args: ['dialogEl', { isSignal: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
2778
+ args: [{ selector: 'ea-dialog', imports: [NgClass, XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<dialog\n #dialogEl\n class=\"ea-dialog\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"!ariaLabel() ? id() + '-header' : null\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-dialog__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-dialog__close\"\n aria-label=\"Close dialog\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div\n class=\"ea-dialog__header\"\n [id]=\"id() + '-header'\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-dialog__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-dialog__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-dialog{border:none;background:transparent;padding:0;margin:auto;max-width:none;max-height:none;overflow:visible}.ea-dialog::backdrop{background-color:var(--color-bg-overlay)}.ea-dialog__panel{position:relative;display:flex;flex-direction:column;background-color:var(--color-bg-base);border-radius:var(--radius-xl);box-shadow:var(--shadow-2xl);max-height:85vh;overflow:hidden}.ea-dialog__panel--sm{width:24rem}.ea-dialog__panel--md{width:32rem}.ea-dialog__panel--lg{width:42rem}.ea-dialog__panel--full{width:calc(100vw - 2rem);height:calc(100vh - 2rem);max-height:calc(100vh - 2rem)}.ea-dialog__close{position:absolute;top:var(--space-3);right:var(--space-3);display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors);z-index:1}.ea-dialog__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-dialog__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dialog__close svg{width:1rem;height:1rem}.ea-dialog__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-dialog__header:empty{display:none}.ea-dialog__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-dialog__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-dialog__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-dialog__footer:empty{display:none}\n"] }]
2779
+ }], ctorParameters: () => [], propDecorators: { dialogEl: [{ type: i0.ViewChild, args: ['dialogEl', { isSignal: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
2539
2780
 
2781
+ /**
2782
+ * Side panel backed by the native `<dialog>` element for browser-managed
2783
+ * focus trapping. Slides in from a configurable edge, supports backdrop and
2784
+ * Escape dismissal, and exposes `header`, default, and `footer` content
2785
+ * slots. The `open` state is a two-way `model()` binding.
2786
+ */
2540
2787
  class DrawerComponent {
2541
2788
  drawerEl = viewChild('drawerEl', ...(ngDevMode ? [{ debugName: "drawerEl" }] : /* istanbul ignore next */ []));
2789
+ previouslyFocused = null;
2542
2790
  // Inputs
2543
2791
  position = input('right', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
2544
2792
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
@@ -2546,10 +2794,13 @@ class DrawerComponent {
2546
2794
  closeOnEscape = input(true, ...(ngDevMode ? [{ debugName: "closeOnEscape" }] : /* istanbul ignore next */ []));
2547
2795
  showClose = input(true, ...(ngDevMode ? [{ debugName: "showClose" }] : /* istanbul ignore next */ []));
2548
2796
  ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
2797
+ id = input(`ea-drawer-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2549
2798
  // Two-way open binding
2550
2799
  open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
2551
2800
  // Outputs
2801
+ /** Fires once the drawer has been shown via `showModal()`. */
2552
2802
  opened = output();
2803
+ /** Fires when the drawer closes (via close button, backdrop, or Escape). */
2553
2804
  closed = output();
2554
2805
  // Computed
2555
2806
  panelClasses = computed(() => ({
@@ -2563,6 +2814,7 @@ class DrawerComponent {
2563
2814
  return;
2564
2815
  if (this.open()) {
2565
2816
  if (!drawerRef.open) {
2817
+ this.previouslyFocused = document.activeElement;
2566
2818
  drawerRef.showModal();
2567
2819
  this.opened.emit();
2568
2820
  }
@@ -2570,6 +2822,8 @@ class DrawerComponent {
2570
2822
  else {
2571
2823
  if (drawerRef.open) {
2572
2824
  drawerRef.close();
2825
+ this.previouslyFocused?.focus?.();
2826
+ this.previouslyFocused = null;
2573
2827
  }
2574
2828
  }
2575
2829
  });
@@ -2594,13 +2848,19 @@ class DrawerComponent {
2594
2848
  this.handleClose();
2595
2849
  }
2596
2850
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2597
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DrawerComponent, isStandalone: true, selector: "ea-drawer", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed" }, viewQueries: [{ propertyName: "drawerEl", first: true, predicate: ["drawerEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<dialog\n #drawerEl\n class=\"ea-drawer\"\n [attr.aria-label]=\"ariaLabel()\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-drawer__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-drawer__close\"\n aria-label=\"Close drawer\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div class=\"ea-drawer__header\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-drawer__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-drawer__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-drawer{position:fixed;inset:0;width:100vw;max-width:none;height:100vh;max-height:none;padding:0;margin:0;border:none;background:transparent;overflow:hidden}.ea-drawer::backdrop{background-color:var(--color-bg-overlay)}.ea-drawer__panel{position:absolute;display:flex;flex-direction:column;background-color:var(--color-bg-base);box-shadow:var(--shadow-2xl);overflow:hidden}.ea-drawer__panel--right{top:0;right:0;bottom:0;height:100%}.ea-drawer__panel--right.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--right.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--right.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--right.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--left{top:0;left:0;bottom:0;height:100%}.ea-drawer__panel--left.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--left.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--left.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--left.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--top{top:0;left:0;right:0;width:100%}.ea-drawer__panel--top.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--top.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--top.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--top.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__panel--bottom{bottom:0;left:0;right:0;width:100%}.ea-drawer__panel--bottom.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--bottom.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--bottom.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--bottom.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__close{position:absolute;top:var(--space-3);right:var(--space-3);z-index:1;display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-drawer__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-drawer__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-drawer__close svg{width:1rem;height:1rem}.ea-drawer__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-drawer__header:empty{display:none}.ea-drawer__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-drawer__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-drawer__footer:empty{display:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2851
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DrawerComponent, isStandalone: true, selector: "ea-drawer", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed" }, viewQueries: [{ propertyName: "drawerEl", first: true, predicate: ["drawerEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<dialog\n #drawerEl\n class=\"ea-drawer\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"!ariaLabel() ? id() + '-header' : null\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-drawer__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-drawer__close\"\n aria-label=\"Close drawer\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div\n class=\"ea-drawer__header\"\n [id]=\"id() + '-header'\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-drawer__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-drawer__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-drawer{position:fixed;inset:0;width:100vw;max-width:none;height:100vh;max-height:none;padding:0;margin:0;border:none;background:transparent;overflow:hidden}.ea-drawer::backdrop{background-color:var(--color-bg-overlay)}.ea-drawer__panel{position:absolute;display:flex;flex-direction:column;background-color:var(--color-bg-base);box-shadow:var(--shadow-2xl);overflow:hidden}.ea-drawer__panel--right{top:0;right:0;bottom:0;height:100%}.ea-drawer__panel--right.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--right.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--right.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--right.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--left{top:0;left:0;bottom:0;height:100%}.ea-drawer__panel--left.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--left.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--left.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--left.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--top{top:0;left:0;right:0;width:100%}.ea-drawer__panel--top.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--top.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--top.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--top.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__panel--bottom{bottom:0;left:0;right:0;width:100%}.ea-drawer__panel--bottom.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--bottom.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--bottom.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--bottom.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__close{position:absolute;top:var(--space-3);right:var(--space-3);z-index:1;display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-drawer__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-drawer__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-drawer__close svg{width:1rem;height:1rem}.ea-drawer__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-drawer__header:empty{display:none}.ea-drawer__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-drawer__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-drawer__footer:empty{display:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2598
2852
  }
2599
2853
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DrawerComponent, decorators: [{
2600
2854
  type: Component,
2601
- args: [{ selector: 'ea-drawer', imports: [NgClass, XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<dialog\n #drawerEl\n class=\"ea-drawer\"\n [attr.aria-label]=\"ariaLabel()\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-drawer__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-drawer__close\"\n aria-label=\"Close drawer\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div class=\"ea-drawer__header\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-drawer__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-drawer__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-drawer{position:fixed;inset:0;width:100vw;max-width:none;height:100vh;max-height:none;padding:0;margin:0;border:none;background:transparent;overflow:hidden}.ea-drawer::backdrop{background-color:var(--color-bg-overlay)}.ea-drawer__panel{position:absolute;display:flex;flex-direction:column;background-color:var(--color-bg-base);box-shadow:var(--shadow-2xl);overflow:hidden}.ea-drawer__panel--right{top:0;right:0;bottom:0;height:100%}.ea-drawer__panel--right.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--right.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--right.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--right.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--left{top:0;left:0;bottom:0;height:100%}.ea-drawer__panel--left.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--left.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--left.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--left.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--top{top:0;left:0;right:0;width:100%}.ea-drawer__panel--top.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--top.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--top.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--top.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__panel--bottom{bottom:0;left:0;right:0;width:100%}.ea-drawer__panel--bottom.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--bottom.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--bottom.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--bottom.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__close{position:absolute;top:var(--space-3);right:var(--space-3);z-index:1;display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-drawer__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-drawer__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-drawer__close svg{width:1rem;height:1rem}.ea-drawer__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-drawer__header:empty{display:none}.ea-drawer__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-drawer__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-drawer__footer:empty{display:none}\n"] }]
2602
- }], ctorParameters: () => [], propDecorators: { drawerEl: [{ type: i0.ViewChild, args: ['drawerEl', { isSignal: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
2855
+ args: [{ selector: 'ea-drawer', imports: [NgClass, XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<dialog\n #drawerEl\n class=\"ea-drawer\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"!ariaLabel() ? id() + '-header' : null\"\n (click)=\"handleBackdropClick($event)\"\n (cancel)=\"handleCancel($event)\">\n <div\n class=\"ea-drawer__panel\"\n [ngClass]=\"panelClasses()\">\n @if (showClose()) {\n <button\n type=\"button\"\n class=\"ea-drawer__close\"\n aria-label=\"Close drawer\"\n (click)=\"handleClose()\">\n <ea-icon-x />\n </button>\n }\n\n <div\n class=\"ea-drawer__header\"\n [id]=\"id() + '-header'\">\n <ng-content select=\"[slot=header]\" />\n </div>\n\n <div class=\"ea-drawer__body\">\n <ng-content />\n </div>\n\n <div class=\"ea-drawer__footer\">\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n</dialog>\n", styles: [".ea-drawer{position:fixed;inset:0;width:100vw;max-width:none;height:100vh;max-height:none;padding:0;margin:0;border:none;background:transparent;overflow:hidden}.ea-drawer::backdrop{background-color:var(--color-bg-overlay)}.ea-drawer__panel{position:absolute;display:flex;flex-direction:column;background-color:var(--color-bg-base);box-shadow:var(--shadow-2xl);overflow:hidden}.ea-drawer__panel--right{top:0;right:0;bottom:0;height:100%}.ea-drawer__panel--right.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--right.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--right.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--right.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--left{top:0;left:0;bottom:0;height:100%}.ea-drawer__panel--left.ea-drawer__panel--sm{width:20rem}.ea-drawer__panel--left.ea-drawer__panel--md{width:28rem}.ea-drawer__panel--left.ea-drawer__panel--lg{width:36rem}.ea-drawer__panel--left.ea-drawer__panel--full{width:calc(100vw - 3rem)}.ea-drawer__panel--top{top:0;left:0;right:0;width:100%}.ea-drawer__panel--top.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--top.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--top.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--top.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__panel--bottom{bottom:0;left:0;right:0;width:100%}.ea-drawer__panel--bottom.ea-drawer__panel--sm{height:12rem}.ea-drawer__panel--bottom.ea-drawer__panel--md{height:20rem}.ea-drawer__panel--bottom.ea-drawer__panel--lg{height:28rem}.ea-drawer__panel--bottom.ea-drawer__panel--full{height:calc(100vh - 3rem)}.ea-drawer__close{position:absolute;top:var(--space-3);right:var(--space-3);z-index:1;display:flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-drawer__close:hover{background-color:var(--color-bg-muted);color:var(--color-text-primary)}.ea-drawer__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-drawer__close svg{width:1rem;height:1rem}.ea-drawer__header{padding:var(--space-5) var(--space-6) var(--space-3);font-size:var(--text-h4-size);font-weight:var(--text-h4-weight);line-height:var(--text-h4-lh);color:var(--color-text-primary)}.ea-drawer__header:empty{display:none}.ea-drawer__body{flex:1;padding:var(--space-3) var(--space-6);overflow-y:auto;font-size:var(--font-size-sm);line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-drawer__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-3);padding:var(--space-3) var(--space-6) var(--space-5)}.ea-drawer__footer>*{display:flex;align-items:center;gap:var(--space-3)}.ea-drawer__footer:empty{display:none}\n"] }]
2856
+ }], ctorParameters: () => [], propDecorators: { drawerEl: [{ type: i0.ViewChild, args: ['drawerEl', { isSignal: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
2603
2857
 
2858
+ /**
2859
+ * Single-select dropdown with a custom popup list. Supports keyboard
2860
+ * navigation (arrow keys, Enter/Space to select, Escape to close), closes
2861
+ * on outside click or viewport scroll/resize, and integrates with Angular
2862
+ * forms via `ControlValueAccessor`.
2863
+ */
2604
2864
  class DropdownComponent {
2605
2865
  elRef = viewChild('triggerEl', ...(ngDevMode ? [{ debugName: "elRef" }] : /* istanbul ignore next */ []));
2606
2866
  menuEl = viewChild('menuEl', ...(ngDevMode ? [{ debugName: "menuEl" }] : /* istanbul ignore next */ []));
@@ -2611,13 +2871,15 @@ class DropdownComponent {
2611
2871
  options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
2612
2872
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2613
2873
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
2874
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
2614
2875
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
2615
2876
  hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
2616
- errorMsg = input(undefined, { ...(ngDevMode ? { debugName: "errorMsg" } : /* istanbul ignore next */ {}), alias: 'error' });
2877
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
2617
2878
  id = input(`ea-dropdown-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
2618
2879
  // Two-way value binding
2619
2880
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2620
2881
  // Outputs
2882
+ /** Fires with the new value when the user selects an option. */
2621
2883
  changed = output();
2622
2884
  // Internal state
2623
2885
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
@@ -2628,16 +2890,16 @@ class DropdownComponent {
2628
2890
  onTouched = () => { };
2629
2891
  // Computed
2630
2892
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
2631
- resolvedStatus = computed(() => (this.errorMsg() ? 'error' : 'default'), ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
2632
- showError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
2633
- showHint = computed(() => !!this.hint() && !this.showError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
2893
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
2894
+ showError = this.hasError;
2895
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
2634
2896
  selectedLabel = computed(() => {
2635
2897
  const opt = this.options().find(o => o.value === this.value());
2636
2898
  return opt?.label ?? '';
2637
2899
  }, ...(ngDevMode ? [{ debugName: "selectedLabel" }] : /* istanbul ignore next */ []));
2638
2900
  triggerClasses = computed(() => ({
2639
2901
  [`ea-dropdown__trigger--${this.size()}`]: true,
2640
- [`ea-dropdown__trigger--${this.resolvedStatus()}`]: true,
2902
+ 'ea-dropdown__trigger--error': this.hasError(),
2641
2903
  'ea-dropdown__trigger--open': this.isOpen(),
2642
2904
  'ea-dropdown__trigger--disabled': this.isDisabled(),
2643
2905
  }), ...(ngDevMode ? [{ debugName: "triggerClasses" }] : /* istanbul ignore next */ []));
@@ -2680,8 +2942,9 @@ class DropdownComponent {
2680
2942
  this._formDisabled.set(isDisabled);
2681
2943
  }
2682
2944
  // Handlers
2945
+ /** Toggles the dropdown list between open and closed. */
2683
2946
  toggle() {
2684
- if (this.isDisabled())
2947
+ if (this.isDisabled() || this.readonly())
2685
2948
  return;
2686
2949
  this.isOpen.set(!this.isOpen());
2687
2950
  if (this.isOpen()) {
@@ -2689,8 +2952,9 @@ class DropdownComponent {
2689
2952
  this.focusedIndex.set(idx >= 0 ? idx : 0);
2690
2953
  }
2691
2954
  }
2955
+ /** Programmatically selects the given option, closing the list. */
2692
2956
  select(option) {
2693
- if (option.disabled || this.isDisabled())
2957
+ if (option.disabled || this.isDisabled() || this.readonly())
2694
2958
  return;
2695
2959
  this.value.set(option.value);
2696
2960
  this.onChange(option.value);
@@ -2698,12 +2962,17 @@ class DropdownComponent {
2698
2962
  this.changed.emit(option.value);
2699
2963
  this.close();
2700
2964
  }
2965
+ /** Closes the dropdown list without changing the current value. */
2701
2966
  close() {
2702
2967
  this.isOpen.set(false);
2703
2968
  this.focusedIndex.set(-1);
2704
2969
  }
2970
+ /** Moves keyboard focus to the dropdown trigger. */
2971
+ focus() {
2972
+ this.elRef()?.nativeElement.focus();
2973
+ }
2705
2974
  handleKeydown(event) {
2706
- if (this.isDisabled())
2975
+ if (this.isDisabled() || this.readonly())
2707
2976
  return;
2708
2977
  switch (event.key) {
2709
2978
  case 'Enter':
@@ -2765,13 +3034,13 @@ class DropdownComponent {
2765
3034
  }
2766
3035
  }
2767
3036
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2768
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DropdownComponent, isStandalone: true, selector: "ea-dropdown", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
3037
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DropdownComponent, isStandalone: true, selector: "ea-dropdown", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
2769
3038
  {
2770
3039
  provide: NG_VALUE_ACCESSOR,
2771
3040
  useExisting: forwardRef(() => DropdownComponent),
2772
3041
  multi: true,
2773
3042
  },
2774
- ], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "menuEl", first: true, predicate: ["menuEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-dropdown-field\">\n @if (label()) {\n <label\n class=\"ea-dropdown-field__label\"\n [for]=\"id()\"\n [class.ea-dropdown-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-dropdown\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-dropdown__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-labelledby]=\"label() ? id() : null\"\n (click)=\"toggle()\"\n (keydown)=\"handleKeydown($event)\">\n <span\n class=\"ea-dropdown__value\"\n [class.ea-dropdown__value--placeholder]=\"!selectedLabel()\">\n {{ selectedLabel() || placeholder() }}\n </span>\n <ea-icon-chevron-down\n class=\"ea-dropdown__chevron\"\n [class.ea-dropdown__chevron--open]=\"isOpen()\" />\n </button>\n\n @if (isOpen()) {\n <ul\n #menuEl\n class=\"ea-dropdown__menu\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \">\n @for (option of options(); track option.value; let i = $index) {\n <li\n class=\"ea-dropdown__option\"\n [class.ea-dropdown__option--selected]=\"option.value === value()\"\n [class.ea-dropdown__option--focused]=\"i === focusedIndex()\"\n [class.ea-dropdown__option--disabled]=\"option.disabled\"\n [id]=\"id() + '-option-' + i\"\n role=\"option\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (click)=\"select(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n </ul>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-dropdown-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-dropdown-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-dropdown-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-dropdown-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-dropdown-field__message--hint{color:var(--color-text-secondary)}.ea-dropdown-field__message--error{color:var(--color-error-default)}.ea-dropdown{position:relative}.ea-dropdown__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-dropdown__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-dropdown__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-dropdown__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-dropdown__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--error{border-color:var(--color-error-default)}.ea-dropdown__trigger--error.ea-dropdown__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-dropdown__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-dropdown__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-dropdown__value--placeholder{color:var(--color-text-tertiary)}.ea-dropdown__chevron{width:1em;height:1em;flex-shrink:0;color:var(--color-text-secondary);transition:var(--transition-transform)}.ea-dropdown__chevron--open{transform:rotate(180deg)}.ea-dropdown__menu{position:fixed;z-index:var(--z-index-dropdown);max-height:15rem;overflow-y:auto;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);padding:var(--space-1) 0;margin:0;list-style:none}.ea-dropdown__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);white-space:nowrap;font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-dropdown__option--focused{background-color:var(--color-bg-muted)}.ea-dropdown__option--selected{color:var(--color-brand-default);font-weight:var(--font-weight-medium)}.ea-dropdown__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ChevronDownIconComponent, selector: "ea-icon-chevron-down" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3043
+ ], viewQueries: [{ propertyName: "elRef", first: true, predicate: ["triggerEl"], descendants: true, isSignal: true }, { propertyName: "menuEl", first: true, predicate: ["menuEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-dropdown-field\">\n @if (label()) {\n <label\n class=\"ea-dropdown-field__label\"\n [for]=\"id()\"\n [id]=\"id() + '-label'\"\n [class.ea-dropdown-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-dropdown\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-dropdown__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (click)=\"toggle()\"\n (keydown)=\"handleKeydown($event)\">\n <span\n class=\"ea-dropdown__value\"\n [class.ea-dropdown__value--placeholder]=\"!selectedLabel()\">\n {{ selectedLabel() || placeholder() }}\n </span>\n <ea-icon-chevron-down\n class=\"ea-dropdown__chevron\"\n [class.ea-dropdown__chevron--open]=\"isOpen()\" />\n </button>\n\n @if (isOpen()) {\n <ul\n #menuEl\n class=\"ea-dropdown__menu\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \">\n @for (option of options(); track option.value; let i = $index) {\n <li\n class=\"ea-dropdown__option\"\n [class.ea-dropdown__option--selected]=\"option.value === value()\"\n [class.ea-dropdown__option--focused]=\"i === focusedIndex()\"\n [class.ea-dropdown__option--disabled]=\"option.disabled\"\n [id]=\"id() + '-option-' + i\"\n role=\"option\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (click)=\"select(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n </ul>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-dropdown-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-dropdown-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-dropdown-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-dropdown-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-dropdown-field__message--hint{color:var(--color-text-secondary)}.ea-dropdown-field__message--error{color:var(--color-error-default)}.ea-dropdown{position:relative}.ea-dropdown__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-dropdown__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-dropdown__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-dropdown__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-dropdown__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--error{border-color:var(--color-error-default)}.ea-dropdown__trigger--error.ea-dropdown__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-dropdown__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-dropdown__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-dropdown__value--placeholder{color:var(--color-text-tertiary)}.ea-dropdown__chevron{width:1em;height:1em;flex-shrink:0;color:var(--color-text-secondary);transition:var(--transition-transform)}.ea-dropdown__chevron--open{transform:rotate(180deg)}.ea-dropdown__menu{position:fixed;z-index:var(--z-index-dropdown);max-height:15rem;overflow-y:auto;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);padding:var(--space-1) 0;margin:0;list-style:none}.ea-dropdown__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);white-space:nowrap;font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-dropdown__option--focused{background-color:var(--color-bg-muted)}.ea-dropdown__option--selected{color:var(--color-brand-default);font-weight:var(--font-weight-medium)}.ea-dropdown__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: ChevronDownIconComponent, selector: "ea-icon-chevron-down" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2775
3044
  }
2776
3045
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DropdownComponent, decorators: [{
2777
3046
  type: Component,
@@ -2781,8 +3050,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2781
3050
  useExisting: forwardRef(() => DropdownComponent),
2782
3051
  multi: true,
2783
3052
  },
2784
- ], template: "<div class=\"ea-dropdown-field\">\n @if (label()) {\n <label\n class=\"ea-dropdown-field__label\"\n [for]=\"id()\"\n [class.ea-dropdown-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-dropdown\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-dropdown__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-labelledby]=\"label() ? id() : null\"\n (click)=\"toggle()\"\n (keydown)=\"handleKeydown($event)\">\n <span\n class=\"ea-dropdown__value\"\n [class.ea-dropdown__value--placeholder]=\"!selectedLabel()\">\n {{ selectedLabel() || placeholder() }}\n </span>\n <ea-icon-chevron-down\n class=\"ea-dropdown__chevron\"\n [class.ea-dropdown__chevron--open]=\"isOpen()\" />\n </button>\n\n @if (isOpen()) {\n <ul\n #menuEl\n class=\"ea-dropdown__menu\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \">\n @for (option of options(); track option.value; let i = $index) {\n <li\n class=\"ea-dropdown__option\"\n [class.ea-dropdown__option--selected]=\"option.value === value()\"\n [class.ea-dropdown__option--focused]=\"i === focusedIndex()\"\n [class.ea-dropdown__option--disabled]=\"option.disabled\"\n [id]=\"id() + '-option-' + i\"\n role=\"option\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (click)=\"select(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n </ul>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-dropdown-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-dropdown-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-dropdown-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-dropdown-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-dropdown-field__message--hint{color:var(--color-text-secondary)}.ea-dropdown-field__message--error{color:var(--color-error-default)}.ea-dropdown{position:relative}.ea-dropdown__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-dropdown__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-dropdown__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-dropdown__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-dropdown__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--error{border-color:var(--color-error-default)}.ea-dropdown__trigger--error.ea-dropdown__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-dropdown__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-dropdown__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-dropdown__value--placeholder{color:var(--color-text-tertiary)}.ea-dropdown__chevron{width:1em;height:1em;flex-shrink:0;color:var(--color-text-secondary);transition:var(--transition-transform)}.ea-dropdown__chevron--open{transform:rotate(180deg)}.ea-dropdown__menu{position:fixed;z-index:var(--z-index-dropdown);max-height:15rem;overflow-y:auto;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);padding:var(--space-1) 0;margin:0;list-style:none}.ea-dropdown__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);white-space:nowrap;font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-dropdown__option--focused{background-color:var(--color-bg-muted)}.ea-dropdown__option--selected{color:var(--color-brand-default);font-weight:var(--font-weight-medium)}.ea-dropdown__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}\n"] }]
2785
- }], ctorParameters: () => [], propDecorators: { elRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], menuEl: [{ type: i0.ViewChild, args: ['menuEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }], onDocumentClick: [{
3053
+ ], template: "<div class=\"ea-dropdown-field\">\n @if (label()) {\n <label\n class=\"ea-dropdown-field__label\"\n [for]=\"id()\"\n [id]=\"id() + '-label'\"\n [class.ea-dropdown-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"ea-dropdown\">\n <button\n #triggerEl\n type=\"button\"\n class=\"ea-dropdown__trigger\"\n [ngClass]=\"triggerClasses()\"\n [id]=\"id()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (click)=\"toggle()\"\n (keydown)=\"handleKeydown($event)\">\n <span\n class=\"ea-dropdown__value\"\n [class.ea-dropdown__value--placeholder]=\"!selectedLabel()\">\n {{ selectedLabel() || placeholder() }}\n </span>\n <ea-icon-chevron-down\n class=\"ea-dropdown__chevron\"\n [class.ea-dropdown__chevron--open]=\"isOpen()\" />\n </button>\n\n @if (isOpen()) {\n <ul\n #menuEl\n class=\"ea-dropdown__menu\"\n role=\"listbox\"\n [attr.aria-activedescendant]=\"\n focusedIndex() >= 0 ? id() + '-option-' + focusedIndex() : null\n \">\n @for (option of options(); track option.value; let i = $index) {\n <li\n class=\"ea-dropdown__option\"\n [class.ea-dropdown__option--selected]=\"option.value === value()\"\n [class.ea-dropdown__option--focused]=\"i === focusedIndex()\"\n [class.ea-dropdown__option--disabled]=\"option.disabled\"\n [id]=\"id() + '-option-' + i\"\n role=\"option\"\n [attr.aria-selected]=\"option.value === value()\"\n [attr.aria-disabled]=\"option.disabled || null\"\n (click)=\"select(option)\"\n (mouseenter)=\"focusedIndex.set(i)\">\n {{ option.label }}\n </li>\n }\n </ul>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-dropdown-field__message ea-dropdown-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-dropdown-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-dropdown-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-dropdown-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-dropdown-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-dropdown-field__message--hint{color:var(--color-text-secondary)}.ea-dropdown-field__message--error{color:var(--color-error-default)}.ea-dropdown{position:relative}.ea-dropdown__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2);width:100%;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);text-align:left}.ea-dropdown__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--sm{padding:var(--space-1-5) var(--space-2);font-size:var(--font-size-sm);min-height:2rem}.ea-dropdown__trigger--md{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);min-height:2.5rem}.ea-dropdown__trigger--lg{padding:var(--space-2-5) var(--space-4);font-size:var(--font-size-md);min-height:3rem}.ea-dropdown__trigger--open{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-dropdown__trigger--error{border-color:var(--color-error-default)}.ea-dropdown__trigger--error.ea-dropdown__trigger--open{box-shadow:var(--shadow-focus-ring-error)}.ea-dropdown__trigger--disabled{background-color:var(--color-bg-muted);opacity:.6;cursor:not-allowed}.ea-dropdown__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ea-dropdown__value--placeholder{color:var(--color-text-tertiary)}.ea-dropdown__chevron{width:1em;height:1em;flex-shrink:0;color:var(--color-text-secondary);transition:var(--transition-transform)}.ea-dropdown__chevron--open{transform:rotate(180deg)}.ea-dropdown__menu{position:fixed;z-index:var(--z-index-dropdown);max-height:15rem;overflow-y:auto;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);padding:var(--space-1) 0;margin:0;list-style:none}.ea-dropdown__option{padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);white-space:nowrap;font-family:var(--font-family-sans);color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-dropdown__option--focused{background-color:var(--color-bg-muted)}.ea-dropdown__option--selected{color:var(--color-brand-default);font-weight:var(--font-weight-medium)}.ea-dropdown__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}\n"] }]
3054
+ }], ctorParameters: () => [], propDecorators: { elRef: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }], menuEl: [{ type: i0.ViewChild, args: ['menuEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }], onDocumentClick: [{
2786
3055
  type: HostListener,
2787
3056
  args: ['document:click', ['$event']]
2788
3057
  }] } });
@@ -3163,6 +3432,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
3163
3432
  }]
3164
3433
  }] });
3165
3434
 
3435
+ /**
3436
+ * Branded eagami wordmark logo. Scales continuously from a single `size`
3437
+ * pixel value and supports four content variants paired with stacked or
3438
+ * inline layouts.
3439
+ */
3166
3440
  class EagamiWordmarkComponent {
3167
3441
  variant = input(1, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
3168
3442
  layout = input('stacked', ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
@@ -3197,6 +3471,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
3197
3471
  }, template: "<a\n class=\"ea-eagami-wordmark\"\n [class.ea-eagami-wordmark--inline]=\"layout() === 'inline'\"\n href=\"https://eagami.com\"\n target=\"_blank\"\n rel=\"noopener\"\n [attr.aria-label]=\"ariaLabel()\">\n <ea-icon-eagami\n class=\"ea-eagami-wordmark__logo\"\n aria-hidden=\"true\" />\n\n <span class=\"ea-eagami-wordmark__text\">\n @if (showOverline()) {\n <span class=\"ea-eagami-wordmark__overline\">handcrafted by</span>\n }\n <span class=\"ea-eagami-wordmark__brand\">{{ brandText() }}</span>\n @if (showTagline()) {\n @if (layout() === 'inline') {\n <span\n class=\"ea-eagami-wordmark__separator\"\n aria-hidden=\"true\">\n \u2014\n </span>\n }\n <span class=\"ea-eagami-wordmark__tagline\">elegant web design</span>\n }\n </span>\n</a>\n", styles: ["@import\"https://fonts.googleapis.com/css2?family=Syne:wght@400;500&display=swap\";:host{display:inline-block;line-height:var(--line-height-none)}.ea-eagami-wordmark{display:inline-flex;align-items:center;border-radius:var(--radius-sm);color:var(--color-text-primary);text-decoration:none;transition:var(--transition-opacity)}.ea-eagami-wordmark:hover{opacity:.75}.ea-eagami-wordmark:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-eagami-wordmark__logo{flex-shrink:0;font-size:calc(var(--_size) * 1px)}.ea-eagami-wordmark__text{display:inline-flex;flex-direction:column;align-items:center;justify-content:center;line-height:var(--line-height-tight)}.ea-eagami-wordmark__overline,.ea-eagami-wordmark__brand,.ea-eagami-wordmark__tagline{white-space:nowrap;text-transform:lowercase}.ea-eagami-wordmark__overline,.ea-eagami-wordmark__separator,.ea-eagami-wordmark__tagline{font-size:calc(var(--_size) * .2px);font-weight:var(--font-weight-regular);letter-spacing:var(--letter-spacing-widest);font-family:var(--font-family-sans);color:var(--color-text-secondary)}.ea-eagami-wordmark__brand{font-size:calc(var(--_size) * .5px);font-weight:var(--font-weight-medium);letter-spacing:var(--letter-spacing-wide);font-family:var(--font-family-brand)}.ea-eagami-wordmark--inline .ea-eagami-wordmark__text{flex-direction:row;align-items:baseline;gap:calc(var(--_size) * .1px)}.ea-eagami-wordmark--inline .ea-eagami-wordmark__overline,.ea-eagami-wordmark--inline .ea-eagami-wordmark__separator,.ea-eagami-wordmark--inline .ea-eagami-wordmark__tagline{font-size:calc(var(--_size) * .5px)}\n"] }]
3198
3472
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
3199
3473
 
3474
+ /**
3475
+ * Pattern for "no results" or "nothing here yet" screens. Combines an
3476
+ * optional title and description with `[slot=media]` (icon or illustration)
3477
+ * and `[slot=actions]` (follow-up buttons) content slots.
3478
+ */
3479
+ class EmptyStateComponent {
3480
+ title = input(undefined, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
3481
+ description = input(undefined, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
3482
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
3483
+ headingLevel = input('h2', ...(ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []));
3484
+ hostClasses = computed(() => ({
3485
+ [`ea-empty-state--${this.size()}`]: true,
3486
+ }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
3487
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3488
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: EmptyStateComponent, isStandalone: true, selector: "ea-empty-state", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-empty-state\"\n [ngClass]=\"hostClasses()\">\n <div class=\"ea-empty-state__media\">\n <ng-content select=\"[slot=media]\" />\n </div>\n\n @if (title()) {\n @switch (headingLevel()) {\n @case ('h2') {\n <h2 class=\"ea-empty-state__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"ea-empty-state__title\">{{ title() }}</h3>\n }\n @case ('h4') {\n <h4 class=\"ea-empty-state__title\">{{ title() }}</h4>\n }\n @case ('h5') {\n <h5 class=\"ea-empty-state__title\">{{ title() }}</h5>\n }\n @case ('h6') {\n <h6 class=\"ea-empty-state__title\">{{ title() }}</h6>\n }\n @default {\n <h2 class=\"ea-empty-state__title\">{{ title() }}</h2>\n }\n }\n }\n\n @if (description()) {\n <p class=\"ea-empty-state__description\">{{ description() }}</p>\n }\n\n <div class=\"ea-empty-state__actions\">\n <ng-content select=\"[slot=actions]\" />\n </div>\n</div>\n", styles: [".ea-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;font-family:var(--font-family-sans);color:var(--color-text-secondary)}.ea-empty-state--sm{gap:var(--space-2);padding:var(--space-6) var(--space-4)}.ea-empty-state--sm .ea-empty-state__media{font-size:2rem}.ea-empty-state--sm .ea-empty-state__title{font-size:var(--font-size-md)}.ea-empty-state--sm .ea-empty-state__description{font-size:var(--font-size-sm);max-width:24rem}.ea-empty-state--md{gap:var(--space-3);padding:var(--space-8) var(--space-6)}.ea-empty-state--md .ea-empty-state__media{font-size:3rem}.ea-empty-state--md .ea-empty-state__title{font-size:var(--font-size-lg)}.ea-empty-state--md .ea-empty-state__description{font-size:var(--font-size-md);max-width:32rem}.ea-empty-state--lg{gap:var(--space-4);padding:var(--space-12) var(--space-8)}.ea-empty-state--lg .ea-empty-state__media{font-size:4rem}.ea-empty-state--lg .ea-empty-state__title{font-size:var(--font-size-xl)}.ea-empty-state--lg .ea-empty-state__description{font-size:var(--font-size-md);max-width:36rem}.ea-empty-state__media{display:flex;align-items:center;justify-content:center;color:var(--color-text-tertiary)}.ea-empty-state__media:empty{display:none}.ea-empty-state__title{margin:0;font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);color:var(--color-text-primary)}.ea-empty-state__description{margin:0;line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-empty-state__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--space-2);margin-top:var(--space-2)}.ea-empty-state__actions:empty{display:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3489
+ }
3490
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EmptyStateComponent, decorators: [{
3491
+ type: Component,
3492
+ args: [{ selector: 'ea-empty-state', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass], template: "<div\n class=\"ea-empty-state\"\n [ngClass]=\"hostClasses()\">\n <div class=\"ea-empty-state__media\">\n <ng-content select=\"[slot=media]\" />\n </div>\n\n @if (title()) {\n @switch (headingLevel()) {\n @case ('h2') {\n <h2 class=\"ea-empty-state__title\">{{ title() }}</h2>\n }\n @case ('h3') {\n <h3 class=\"ea-empty-state__title\">{{ title() }}</h3>\n }\n @case ('h4') {\n <h4 class=\"ea-empty-state__title\">{{ title() }}</h4>\n }\n @case ('h5') {\n <h5 class=\"ea-empty-state__title\">{{ title() }}</h5>\n }\n @case ('h6') {\n <h6 class=\"ea-empty-state__title\">{{ title() }}</h6>\n }\n @default {\n <h2 class=\"ea-empty-state__title\">{{ title() }}</h2>\n }\n }\n }\n\n @if (description()) {\n <p class=\"ea-empty-state__description\">{{ description() }}</p>\n }\n\n <div class=\"ea-empty-state__actions\">\n <ng-content select=\"[slot=actions]\" />\n </div>\n</div>\n", styles: [".ea-empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;font-family:var(--font-family-sans);color:var(--color-text-secondary)}.ea-empty-state--sm{gap:var(--space-2);padding:var(--space-6) var(--space-4)}.ea-empty-state--sm .ea-empty-state__media{font-size:2rem}.ea-empty-state--sm .ea-empty-state__title{font-size:var(--font-size-md)}.ea-empty-state--sm .ea-empty-state__description{font-size:var(--font-size-sm);max-width:24rem}.ea-empty-state--md{gap:var(--space-3);padding:var(--space-8) var(--space-6)}.ea-empty-state--md .ea-empty-state__media{font-size:3rem}.ea-empty-state--md .ea-empty-state__title{font-size:var(--font-size-lg)}.ea-empty-state--md .ea-empty-state__description{font-size:var(--font-size-md);max-width:32rem}.ea-empty-state--lg{gap:var(--space-4);padding:var(--space-12) var(--space-8)}.ea-empty-state--lg .ea-empty-state__media{font-size:4rem}.ea-empty-state--lg .ea-empty-state__title{font-size:var(--font-size-xl)}.ea-empty-state--lg .ea-empty-state__description{font-size:var(--font-size-md);max-width:36rem}.ea-empty-state__media{display:flex;align-items:center;justify-content:center;color:var(--color-text-tertiary)}.ea-empty-state__media:empty{display:none}.ea-empty-state__title{margin:0;font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);color:var(--color-text-primary)}.ea-empty-state__description{margin:0;line-height:var(--line-height-normal);color:var(--color-text-secondary)}.ea-empty-state__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--space-2);margin-top:var(--space-2)}.ea-empty-state__actions:empty{display:none}\n"] }]
3493
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], headingLevel: [{ type: i0.Input, args: [{ isSignal: true, alias: "headingLevel", required: false }] }] } });
3494
+
3200
3495
  class AlertTriangleIconComponent {
3201
3496
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AlertTriangleIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3202
3497
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: AlertTriangleIconComponent, isStandalone: true, selector: "ea-icon-alert-triangle", host: { styleAttribute: "display: inline-flex; width: 1em; height: 1em;" }, ngImport: i0, template: `
@@ -4871,6 +5166,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
4871
5166
  }]
4872
5167
  }] });
4873
5168
 
5169
+ /**
5170
+ * Single-line text field with label, hint, and error message support.
5171
+ * Includes a built-in show/hide toggle for `password` inputs and integrates
5172
+ * with Angular forms via `ControlValueAccessor`. Prefix and suffix content
5173
+ * can be projected via the `prefix` and `suffix` slots.
5174
+ */
4874
5175
  class InputComponent {
4875
5176
  inputEl = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputEl" }] : /* istanbul ignore next */ []));
4876
5177
  // Inputs
@@ -4878,9 +5179,8 @@ class InputComponent {
4878
5179
  type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
4879
5180
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
4880
5181
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4881
- status = input('default', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
4882
5182
  hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
4883
- errorMsg = input(undefined, { ...(ngDevMode ? { debugName: "errorMsg" } : /* istanbul ignore next */ {}), alias: 'error' });
5183
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
4884
5184
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
4885
5185
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
4886
5186
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
@@ -4891,25 +5191,27 @@ class InputComponent {
4891
5191
  // Two-way value binding
4892
5192
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
4893
5193
  // Internal state
4894
- focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
5194
+ isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
4895
5195
  passwordVisible = signal(false, ...(ngDevMode ? [{ debugName: "passwordVisible" }] : /* istanbul ignore next */ []));
4896
5196
  _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
4897
5197
  // Outputs
4898
- inputFocused = output();
4899
- inputBlurred = output();
5198
+ /** Fires when the input receives focus. */
5199
+ focused = output();
5200
+ /** Fires when the input loses focus. */
5201
+ blurred = output();
4900
5202
  // ControlValueAccessor callbacks
4901
5203
  onChange = () => { };
4902
5204
  onTouched = () => { };
4903
5205
  // Computed
4904
5206
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
4905
5207
  effectiveType = computed(() => this.type() === 'password' && this.passwordVisible() ? 'text' : this.type(), ...(ngDevMode ? [{ debugName: "effectiveType" }] : /* istanbul ignore next */ []));
4906
- resolvedStatus = computed(() => this.errorMsg() ? 'error' : this.status(), ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
4907
- showError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
4908
- showHint = computed(() => !!this.hint() && !this.showError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
5208
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
5209
+ showError = this.hasError;
5210
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
4909
5211
  wrapperClasses = computed(() => ({
4910
5212
  [`ea-input-wrapper--${this.size()}`]: true,
4911
- [`ea-input-wrapper--${this.resolvedStatus()}`]: true,
4912
- 'ea-input-wrapper--focused': this.focused(),
5213
+ 'ea-input-wrapper--error': this.hasError(),
5214
+ 'ea-input-wrapper--focused': this.isFocused(),
4913
5215
  'ea-input-wrapper--disabled': this.isDisabled(),
4914
5216
  'ea-input-wrapper--readonly': this.readonly(),
4915
5217
  }), ...(ngDevMode ? [{ debugName: "wrapperClasses" }] : /* istanbul ignore next */ []));
@@ -4937,28 +5239,30 @@ class InputComponent {
4937
5239
  this.onChange(value);
4938
5240
  }
4939
5241
  handleFocus(event) {
4940
- this.focused.set(true);
4941
- this.inputFocused.emit(event);
5242
+ this.isFocused.set(true);
5243
+ this.focused.emit(event);
4942
5244
  }
4943
5245
  handleBlur(event) {
4944
- this.focused.set(false);
5246
+ this.isFocused.set(false);
4945
5247
  this.onTouched();
4946
- this.inputBlurred.emit(event);
5248
+ this.blurred.emit(event);
4947
5249
  }
5250
+ /** Toggles the password reveal state for `type="password"` inputs. */
4948
5251
  togglePasswordVisibility() {
4949
5252
  this.passwordVisible.update(value => !value);
4950
5253
  }
5254
+ /** Moves keyboard focus to the underlying native input element. */
4951
5255
  focus() {
4952
5256
  this.inputEl()?.nativeElement.focus();
4953
5257
  }
4954
5258
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: InputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4955
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: InputComponent, isStandalone: true, selector: "ea-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, showPasswordToggle: { classPropertyName: "showPasswordToggle", publicName: "showPasswordToggle", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", inputFocused: "inputFocused", inputBlurred: "inputBlurred" }, providers: [
5259
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: InputComponent, isStandalone: true, selector: "ea-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, showPasswordToggle: { classPropertyName: "showPasswordToggle", publicName: "showPasswordToggle", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", focused: "focused", blurred: "blurred" }, providers: [
4956
5260
  {
4957
5261
  provide: NG_VALUE_ACCESSOR,
4958
5262
  useExisting: forwardRef(() => InputComponent),
4959
5263
  multi: true,
4960
5264
  },
4961
- ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-input-field\">\n @if (label()) {\n <label\n class=\"ea-input-field__label\"\n [for]=\"id()\"\n [class.ea-input-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-input-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <!-- Prefix slot (icon or text) -->\n <span class=\"ea-input-wrapper__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-input\"\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\" />\n\n <!-- Suffix slot (icon, clear button, etc.) -->\n <span class=\"ea-input-wrapper__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n\n <!-- Built-in password visibility toggle -->\n @if (type() === 'password' && showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"ea-input-wrapper__password-toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Hide password' : 'Show password'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"togglePasswordVisibility()\"\n tabindex=\"-1\">\n @if (passwordVisible()) {\n <ea-icon-eye-off />\n } @else {\n <ea-icon-eye />\n }\n </button>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-input-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-input-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-input-field__message--hint{color:inherit}.ea-input-field__message--error{color:var(--color-error-default)}.ea-input-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-input-wrapper{display:flex;align-items:center;gap:var(--space-2);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);color:var(--color-text-secondary);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-input-wrapper--sm{padding:0 var(--space-2);min-height:2rem}.ea-input-wrapper--sm .ea-input{font-size:var(--font-size-sm);padding:var(--space-1-5) 0}.ea-input-wrapper--md{padding:0 var(--space-3);min-height:2.5rem}.ea-input-wrapper--md .ea-input{font-size:var(--font-size-md);padding:var(--space-2) 0}.ea-input-wrapper--lg{padding:0 var(--space-4);min-height:3rem}.ea-input-wrapper--lg .ea-input{font-size:var(--font-size-lg);padding:var(--space-2-5) 0}.ea-input-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-input-wrapper--error{border-color:var(--color-error-default)}.ea-input-wrapper--error.ea-input-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-input-wrapper--success{border-color:var(--color-success-default)}.ea-input-wrapper--success.ea-input-wrapper--focused{box-shadow:var(--shadow-focus-ring-success)}.ea-input-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-input-wrapper--disabled .ea-input{cursor:not-allowed}.ea-input-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-input-wrapper__prefix,.ea-input-wrapper__suffix{display:flex;align-items:center;flex-shrink:0;color:inherit}.ea-input-wrapper__prefix:empty,.ea-input-wrapper__suffix:empty{display:none}.ea-input-wrapper__password-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;cursor:pointer;color:var(--ea-input-toggle-color, inherit);border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-input-wrapper__password-toggle:hover{color:var(--color-text-primary)}.ea-input-wrapper__password-toggle ea-icon-eye,.ea-input-wrapper__password-toggle ea-icon-eye-off{width:1rem;height:1rem;pointer-events:none}.ea-input{flex:1;width:100%;min-width:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-input::placeholder{color:var(--color-text-tertiary)}.ea-input:-webkit-autofill,.ea-input:autofill{-webkit-text-fill-color:var(--color-text-primary);-webkit-box-shadow:0 0 0 1000px var(--color-bg-base) inset;transition:background-color 5000s ease-in-out 0s}.ea-input:disabled{cursor:not-allowed}.ea-input[type=number]::-webkit-inner-spin-button,.ea-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.ea-input[type=number]{-moz-appearance:textfield;appearance:textfield}.ea-input[type=search]::-webkit-search-decoration,.ea-input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: EyeIconComponent, selector: "ea-icon-eye" }, { kind: "component", type: EyeOffIconComponent, selector: "ea-icon-eye-off" }, { kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5265
+ ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-input-field\">\n @if (label()) {\n <label\n class=\"ea-input-field__label\"\n [for]=\"id()\"\n [class.ea-input-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-input-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <!-- Prefix slot (icon or text) -->\n <span class=\"ea-input-wrapper__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-input\"\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\" />\n\n <!-- Suffix slot (icon, clear button, etc.) -->\n <span class=\"ea-input-wrapper__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n\n <!-- Built-in password visibility toggle -->\n @if (type() === 'password' && showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"ea-input-wrapper__password-toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Hide password' : 'Show password'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"togglePasswordVisibility()\"\n tabindex=\"-1\">\n @if (passwordVisible()) {\n <ea-icon-eye-off />\n } @else {\n <ea-icon-eye />\n }\n </button>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-input-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-input-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-input-field__message--hint{color:inherit}.ea-input-field__message--error{color:var(--color-error-default)}.ea-input-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-input-wrapper{display:flex;align-items:center;gap:var(--space-2);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);color:var(--color-text-secondary);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-input-wrapper--sm{padding:0 var(--space-2);min-height:2rem}.ea-input-wrapper--sm .ea-input{font-size:var(--font-size-sm);padding:var(--space-1-5) 0}.ea-input-wrapper--md{padding:0 var(--space-3);min-height:2.5rem}.ea-input-wrapper--md .ea-input{font-size:var(--font-size-md);padding:var(--space-2) 0}.ea-input-wrapper--lg{padding:0 var(--space-4);min-height:3rem}.ea-input-wrapper--lg .ea-input{font-size:var(--font-size-lg);padding:var(--space-2-5) 0}.ea-input-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-input-wrapper--error{border-color:var(--color-error-default)}.ea-input-wrapper--error.ea-input-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-input-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-input-wrapper--disabled .ea-input{cursor:not-allowed}.ea-input-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-input-wrapper__prefix,.ea-input-wrapper__suffix{display:flex;align-items:center;flex-shrink:0;color:inherit}.ea-input-wrapper__prefix:empty,.ea-input-wrapper__suffix:empty{display:none}.ea-input-wrapper__password-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;cursor:pointer;color:var(--ea-input-toggle-color, inherit);border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-input-wrapper__password-toggle:hover{color:var(--color-text-primary)}.ea-input-wrapper__password-toggle ea-icon-eye,.ea-input-wrapper__password-toggle ea-icon-eye-off{width:1rem;height:1rem;pointer-events:none}.ea-input{flex:1;width:100%;min-width:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-input::placeholder{color:var(--color-text-tertiary)}.ea-input:-webkit-autofill,.ea-input:autofill{-webkit-text-fill-color:var(--color-text-primary);-webkit-box-shadow:0 0 0 1000px var(--color-bg-base) inset;transition:background-color 5000s ease-in-out 0s}.ea-input:disabled{cursor:not-allowed}.ea-input[type=number]::-webkit-inner-spin-button,.ea-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.ea-input[type=number]{-moz-appearance:textfield;appearance:textfield}.ea-input[type=search]::-webkit-search-decoration,.ea-input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: EyeIconComponent, selector: "ea-icon-eye" }, { kind: "component", type: EyeOffIconComponent, selector: "ea-icon-eye-off" }, { kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4962
5266
  }
4963
5267
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: InputComponent, decorators: [{
4964
5268
  type: Component,
@@ -4968,113 +5272,263 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
4968
5272
  useExisting: forwardRef(() => InputComponent),
4969
5273
  multi: true,
4970
5274
  },
4971
- ], template: "<div class=\"ea-input-field\">\n @if (label()) {\n <label\n class=\"ea-input-field__label\"\n [for]=\"id()\"\n [class.ea-input-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-input-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <!-- Prefix slot (icon or text) -->\n <span class=\"ea-input-wrapper__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-input\"\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\" />\n\n <!-- Suffix slot (icon, clear button, etc.) -->\n <span class=\"ea-input-wrapper__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n\n <!-- Built-in password visibility toggle -->\n @if (type() === 'password' && showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"ea-input-wrapper__password-toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Hide password' : 'Show password'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"togglePasswordVisibility()\"\n tabindex=\"-1\">\n @if (passwordVisible()) {\n <ea-icon-eye-off />\n } @else {\n <ea-icon-eye />\n }\n </button>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-input-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-input-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-input-field__message--hint{color:inherit}.ea-input-field__message--error{color:var(--color-error-default)}.ea-input-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-input-wrapper{display:flex;align-items:center;gap:var(--space-2);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);color:var(--color-text-secondary);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-input-wrapper--sm{padding:0 var(--space-2);min-height:2rem}.ea-input-wrapper--sm .ea-input{font-size:var(--font-size-sm);padding:var(--space-1-5) 0}.ea-input-wrapper--md{padding:0 var(--space-3);min-height:2.5rem}.ea-input-wrapper--md .ea-input{font-size:var(--font-size-md);padding:var(--space-2) 0}.ea-input-wrapper--lg{padding:0 var(--space-4);min-height:3rem}.ea-input-wrapper--lg .ea-input{font-size:var(--font-size-lg);padding:var(--space-2-5) 0}.ea-input-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-input-wrapper--error{border-color:var(--color-error-default)}.ea-input-wrapper--error.ea-input-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-input-wrapper--success{border-color:var(--color-success-default)}.ea-input-wrapper--success.ea-input-wrapper--focused{box-shadow:var(--shadow-focus-ring-success)}.ea-input-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-input-wrapper--disabled .ea-input{cursor:not-allowed}.ea-input-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-input-wrapper__prefix,.ea-input-wrapper__suffix{display:flex;align-items:center;flex-shrink:0;color:inherit}.ea-input-wrapper__prefix:empty,.ea-input-wrapper__suffix:empty{display:none}.ea-input-wrapper__password-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;cursor:pointer;color:var(--ea-input-toggle-color, inherit);border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-input-wrapper__password-toggle:hover{color:var(--color-text-primary)}.ea-input-wrapper__password-toggle ea-icon-eye,.ea-input-wrapper__password-toggle ea-icon-eye-off{width:1rem;height:1rem;pointer-events:none}.ea-input{flex:1;width:100%;min-width:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-input::placeholder{color:var(--color-text-tertiary)}.ea-input:-webkit-autofill,.ea-input:autofill{-webkit-text-fill-color:var(--color-text-primary);-webkit-box-shadow:0 0 0 1000px var(--color-bg-base) inset;transition:background-color 5000s ease-in-out 0s}.ea-input:disabled{cursor:not-allowed}.ea-input[type=number]::-webkit-inner-spin-button,.ea-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.ea-input[type=number]{-moz-appearance:textfield;appearance:textfield}.ea-input[type=search]::-webkit-search-decoration,.ea-input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}\n"] }]
4972
- }], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], showPasswordToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPasswordToggle", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], inputFocused: [{ type: i0.Output, args: ["inputFocused"] }], inputBlurred: [{ type: i0.Output, args: ["inputBlurred"] }] } });
5275
+ ], template: "<div class=\"ea-input-field\">\n @if (label()) {\n <label\n class=\"ea-input-field__label\"\n [for]=\"id()\"\n [class.ea-input-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-input-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <!-- Prefix slot (icon or text) -->\n <span class=\"ea-input-wrapper__prefix\">\n <ng-content select=\"[slot=prefix]\" />\n </span>\n\n <input\n #inputEl\n class=\"ea-input\"\n [id]=\"id()\"\n [type]=\"effectiveType()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [value]=\"value()\"\n [attr.autocomplete]=\"autocomplete() ?? null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\" />\n\n <!-- Suffix slot (icon, clear button, etc.) -->\n <span class=\"ea-input-wrapper__suffix\">\n <ng-content select=\"[slot=suffix]\" />\n </span>\n\n <!-- Built-in password visibility toggle -->\n @if (type() === 'password' && showPasswordToggle()) {\n <button\n type=\"button\"\n class=\"ea-input-wrapper__password-toggle\"\n [attr.aria-label]=\"passwordVisible() ? 'Hide password' : 'Show password'\"\n [attr.aria-pressed]=\"passwordVisible()\"\n (click)=\"togglePasswordVisibility()\"\n tabindex=\"-1\">\n @if (passwordVisible()) {\n <ea-icon-eye-off />\n } @else {\n <ea-icon-eye />\n }\n </button>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-input-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-input-field__message ea-input-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-input-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-input-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-input-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-input-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-input-field__message--hint{color:inherit}.ea-input-field__message--error{color:var(--color-error-default)}.ea-input-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-input-wrapper{display:flex;align-items:center;gap:var(--space-2);background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);color:var(--color-text-secondary);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-input-wrapper--sm{padding:0 var(--space-2);min-height:2rem}.ea-input-wrapper--sm .ea-input{font-size:var(--font-size-sm);padding:var(--space-1-5) 0}.ea-input-wrapper--md{padding:0 var(--space-3);min-height:2.5rem}.ea-input-wrapper--md .ea-input{font-size:var(--font-size-md);padding:var(--space-2) 0}.ea-input-wrapper--lg{padding:0 var(--space-4);min-height:3rem}.ea-input-wrapper--lg .ea-input{font-size:var(--font-size-lg);padding:var(--space-2-5) 0}.ea-input-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-input-wrapper--error{border-color:var(--color-error-default)}.ea-input-wrapper--error.ea-input-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-input-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-input-wrapper--disabled .ea-input{cursor:not-allowed}.ea-input-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-input-wrapper__prefix,.ea-input-wrapper__suffix{display:flex;align-items:center;flex-shrink:0;color:inherit}.ea-input-wrapper__prefix:empty,.ea-input-wrapper__suffix:empty{display:none}.ea-input-wrapper__password-toggle{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;width:1.25rem;height:1.25rem;background:none;border:none;cursor:pointer;color:var(--ea-input-toggle-color, inherit);border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-input-wrapper__password-toggle:hover{color:var(--color-text-primary)}.ea-input-wrapper__password-toggle ea-icon-eye,.ea-input-wrapper__password-toggle ea-icon-eye-off{width:1rem;height:1rem;pointer-events:none}.ea-input{flex:1;width:100%;min-width:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-input::placeholder{color:var(--color-text-tertiary)}.ea-input:-webkit-autofill,.ea-input:autofill{-webkit-text-fill-color:var(--color-text-primary);-webkit-box-shadow:0 0 0 1000px var(--color-bg-base) inset;transition:background-color 5000s ease-in-out 0s}.ea-input:disabled{cursor:not-allowed}.ea-input[type=number]::-webkit-inner-spin-button,.ea-input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.ea-input[type=number]{-moz-appearance:textfield;appearance:textfield}.ea-input[type=search]::-webkit-search-decoration,.ea-input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}\n"] }]
5276
+ }], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], showPasswordToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPasswordToggle", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], focused: [{ type: i0.Output, args: ["focused"] }], blurred: [{ type: i0.Output, args: ["blurred"] }] } });
4973
5277
 
5278
+ /**
5279
+ * Popup action menu attached to any focusable element via the
5280
+ * `[eaMenuTrigger]` directive. Supports keyboard navigation
5281
+ * (arrow keys, Home/End), closes on outside click or Escape, and restores
5282
+ * focus to the trigger on close.
5283
+ */
4974
5284
  class MenuComponent {
4975
- elRef = inject((ElementRef));
4976
- // Inputs
5285
+ injector = inject(Injector);
5286
+ listEl = viewChild('listEl', ...(ngDevMode ? [{ debugName: "listEl" }] : /* istanbul ignore next */ []));
4977
5287
  placement = input('bottom-start', ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
4978
5288
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
4979
5289
  ariaLabel = input('Menu', { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
4980
- // Two-way open binding
5290
+ id = input(`ea-menu-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
4981
5291
  open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
4982
- // Outputs
5292
+ /** Fires when the menu opens. */
4983
5293
  opened = output();
5294
+ /** Fires when the menu closes. */
4984
5295
  closed = output();
4985
- // Computed
4986
- menuId = signal(`ea-menu-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "menuId" }] : /* istanbul ignore next */ []));
4987
- menuClasses = computed(() => ({
5296
+ triggerEl = null;
5297
+ triggerRect = signal(null, ...(ngDevMode ? [{ debugName: "triggerRect" }] : /* istanbul ignore next */ []));
5298
+ listClasses = computed(() => ({
4988
5299
  [`ea-menu__list--${this.placement()}`]: true,
4989
- }), ...(ngDevMode ? [{ debugName: "menuClasses" }] : /* istanbul ignore next */ []));
4990
- toggle() {
5300
+ }), ...(ngDevMode ? [{ debugName: "listClasses" }] : /* istanbul ignore next */ []));
5301
+ listStyle = computed(() => {
5302
+ const rect = this.triggerRect();
5303
+ if (!rect)
5304
+ return {};
5305
+ const placement = this.placement();
5306
+ const gap = 4;
5307
+ const style = {};
5308
+ if (placement === 'bottom-start' || placement === 'bottom-end') {
5309
+ style['top'] = `${rect.bottom + gap}px`;
5310
+ }
5311
+ else {
5312
+ style['bottom'] = `${window.innerHeight - rect.top + gap}px`;
5313
+ }
5314
+ if (placement === 'bottom-start' || placement === 'top-start') {
5315
+ style['left'] = `${rect.left}px`;
5316
+ }
5317
+ else {
5318
+ style['right'] = `${window.innerWidth - rect.right}px`;
5319
+ }
5320
+ return style;
5321
+ }, ...(ngDevMode ? [{ debugName: "listStyle" }] : /* istanbul ignore next */ []));
5322
+ /** Toggles the menu open state, anchoring it to the given trigger element. */
5323
+ toggleAt(triggerEl) {
4991
5324
  if (this.disabled())
4992
5325
  return;
4993
- const next = !this.open();
4994
- this.open.set(next);
4995
- if (next) {
4996
- this.opened.emit();
5326
+ if (this.open()) {
5327
+ this.close();
4997
5328
  }
4998
5329
  else {
4999
- this.closed.emit();
5330
+ this.openAt(triggerEl);
5000
5331
  }
5001
5332
  }
5002
- close() {
5333
+ /** Opens the menu anchored to the given trigger element and focuses the first item. */
5334
+ openAt(triggerEl) {
5335
+ if (this.disabled())
5336
+ return;
5337
+ this.triggerEl = triggerEl;
5338
+ this.triggerRect.set(triggerEl.getBoundingClientRect());
5339
+ this.open.set(true);
5340
+ this.opened.emit();
5341
+ afterNextRender(() => this.focusFirstItem(), { injector: this.injector });
5342
+ }
5343
+ /**
5344
+ * Closes the menu if it is open. Pass `restoreFocus: true` to return focus
5345
+ * to the trigger element (used when closing via Escape or item activation;
5346
+ * not used on outside click, where the user has chosen a new focus target).
5347
+ */
5348
+ close(restoreFocus = false) {
5003
5349
  if (!this.open())
5004
5350
  return;
5005
5351
  this.open.set(false);
5006
5352
  this.closed.emit();
5353
+ if (restoreFocus)
5354
+ this.triggerEl?.focus();
5007
5355
  }
5008
- handleTriggerKeydown(event) {
5009
- if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
5010
- event.preventDefault();
5011
- if (!this.open())
5012
- this.toggle();
5013
- }
5014
- else if (event.key === 'Escape' && this.open()) {
5015
- event.preventDefault();
5016
- this.close();
5356
+ getEnabledItems() {
5357
+ const list = this.listEl()?.nativeElement;
5358
+ if (!list)
5359
+ return [];
5360
+ return Array.from(list.querySelectorAll('[role="menuitem"]:not([disabled])'));
5361
+ }
5362
+ focusFirstItem() {
5363
+ this.getEnabledItems()[0]?.focus();
5364
+ }
5365
+ onKeydown(event) {
5366
+ if (!this.open())
5367
+ return;
5368
+ const list = this.listEl()?.nativeElement;
5369
+ const active = document.activeElement;
5370
+ if (!list || !active || !list.contains(active))
5371
+ return;
5372
+ const items = this.getEnabledItems();
5373
+ if (items.length === 0)
5374
+ return;
5375
+ const current = items.indexOf(active);
5376
+ let next = -1;
5377
+ switch (event.key) {
5378
+ case 'ArrowDown':
5379
+ event.preventDefault();
5380
+ next = current < items.length - 1 ? current + 1 : 0;
5381
+ break;
5382
+ case 'ArrowUp':
5383
+ event.preventDefault();
5384
+ next = current > 0 ? current - 1 : items.length - 1;
5385
+ break;
5386
+ case 'Home':
5387
+ event.preventDefault();
5388
+ next = 0;
5389
+ break;
5390
+ case 'End':
5391
+ event.preventDefault();
5392
+ next = items.length - 1;
5393
+ break;
5017
5394
  }
5395
+ if (next >= 0)
5396
+ items[next].focus();
5018
5397
  }
5019
5398
  onDocumentClick(event) {
5020
5399
  if (!this.open())
5021
5400
  return;
5022
5401
  const target = event.target;
5023
- if (!this.elRef.nativeElement.contains(target)) {
5024
- this.close();
5025
- }
5402
+ if (this.triggerEl?.contains(target))
5403
+ return;
5404
+ if (this.listEl()?.nativeElement.contains(target))
5405
+ return;
5406
+ this.close();
5026
5407
  }
5027
5408
  onEscape() {
5028
- if (this.open())
5029
- this.close();
5409
+ if (!this.open())
5410
+ return;
5411
+ this.close(true);
5412
+ }
5413
+ onViewportChange() {
5414
+ if (!this.open() || !this.triggerEl)
5415
+ return;
5416
+ this.triggerRect.set(this.triggerEl.getBoundingClientRect());
5030
5417
  }
5031
5418
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5032
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MenuComponent, isStandalone: true, selector: "ea-menu", inputs: { placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: "<div class=\"ea-menu\">\n <div\n class=\"ea-menu__trigger\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"menuId()\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\">\n <ng-content select=\"[slot=trigger]\" />\n </div>\n\n @if (open()) {\n <div\n class=\"ea-menu__list\"\n role=\"menu\"\n [id]=\"menuId()\"\n [ngClass]=\"menuClasses()\"\n [attr.aria-label]=\"ariaLabel()\">\n <ng-content />\n </div>\n }\n</div>\n", styles: [".ea-menu{position:relative;display:inline-block}.ea-menu__trigger{display:inline-flex}.ea-menu__list{position:absolute;z-index:var(--z-index-dropdown);min-width:10rem;max-height:20rem;padding:var(--space-1) 0;overflow-y:auto;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}.ea-menu__list--bottom-start{top:calc(100% + var(--space-1));left:0}.ea-menu__list--bottom-end{top:calc(100% + var(--space-1));right:0}.ea-menu__list--top-start{bottom:calc(100% + var(--space-1));left:0}.ea-menu__list--top-end{bottom:calc(100% + var(--space-1));right:0}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5419
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: MenuComponent, isStandalone: true, selector: "ea-menu", inputs: { placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed" }, host: { listeners: { "document:keydown": "onKeydown($event)", "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()", "window:resize": "onViewportChange()", "window:scroll": "onViewportChange()" } }, viewQueries: [{ propertyName: "listEl", first: true, predicate: ["listEl"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (open()) {\n <div\n #listEl\n class=\"ea-menu__list\"\n role=\"menu\"\n [id]=\"id()\"\n [ngClass]=\"listClasses()\"\n [style]=\"listStyle()\"\n [attr.aria-label]=\"ariaLabel()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:contents}.ea-menu__list{position:fixed;z-index:var(--z-index-dropdown);min-width:10rem;max-height:20rem;padding:var(--space-1) 0;overflow-y:auto;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5033
5420
  }
5034
5421
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuComponent, decorators: [{
5035
5422
  type: Component,
5036
- args: [{ selector: 'ea-menu', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ea-menu\">\n <div\n class=\"ea-menu__trigger\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"menuId()\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\">\n <ng-content select=\"[slot=trigger]\" />\n </div>\n\n @if (open()) {\n <div\n class=\"ea-menu__list\"\n role=\"menu\"\n [id]=\"menuId()\"\n [ngClass]=\"menuClasses()\"\n [attr.aria-label]=\"ariaLabel()\">\n <ng-content />\n </div>\n }\n</div>\n", styles: [".ea-menu{position:relative;display:inline-block}.ea-menu__trigger{display:inline-flex}.ea-menu__list{position:absolute;z-index:var(--z-index-dropdown);min-width:10rem;max-height:20rem;padding:var(--space-1) 0;overflow-y:auto;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}.ea-menu__list--bottom-start{top:calc(100% + var(--space-1));left:0}.ea-menu__list--bottom-end{top:calc(100% + var(--space-1));right:0}.ea-menu__list--top-start{bottom:calc(100% + var(--space-1));left:0}.ea-menu__list--top-end{bottom:calc(100% + var(--space-1));right:0}\n"] }]
5037
- }], propDecorators: { placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], onDocumentClick: [{
5423
+ args: [{ selector: 'ea-menu', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (open()) {\n <div\n #listEl\n class=\"ea-menu__list\"\n role=\"menu\"\n [id]=\"id()\"\n [ngClass]=\"listClasses()\"\n [style]=\"listStyle()\"\n [attr.aria-label]=\"ariaLabel()\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:contents}.ea-menu__list{position:fixed;z-index:var(--z-index-dropdown);min-width:10rem;max-height:20rem;padding:var(--space-1) 0;overflow-y:auto;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);background-color:var(--color-bg-base)}\n"] }]
5424
+ }], propDecorators: { listEl: [{ type: i0.ViewChild, args: ['listEl', { isSignal: true }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], onKeydown: [{
5425
+ type: HostListener,
5426
+ args: ['document:keydown', ['$event']]
5427
+ }], onDocumentClick: [{
5038
5428
  type: HostListener,
5039
5429
  args: ['document:click', ['$event']]
5040
5430
  }], onEscape: [{
5041
5431
  type: HostListener,
5042
5432
  args: ['document:keydown.escape']
5433
+ }], onViewportChange: [{
5434
+ type: HostListener,
5435
+ args: ['window:resize']
5436
+ }, {
5437
+ type: HostListener,
5438
+ args: ['window:scroll']
5043
5439
  }] } });
5044
5440
 
5441
+ /**
5442
+ * Selectable row inside an `ea-menu`. Supports leading icons via the `icon`
5443
+ * content slot, a disabled state, and a `danger` variant for destructive
5444
+ * actions. Activating an item closes its parent menu.
5445
+ */
5045
5446
  class MenuItemComponent {
5046
5447
  menu = inject(MenuComponent, { optional: true });
5047
5448
  // Inputs
5048
5449
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
5049
5450
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
5050
5451
  // Outputs
5051
- itemClicked = output();
5452
+ /** Fires when the item is activated; the parent menu closes immediately afterwards. */
5453
+ clicked = output();
5052
5454
  handleClick(event) {
5053
5455
  if (this.disabled()) {
5054
5456
  event.preventDefault();
5055
5457
  event.stopPropagation();
5056
5458
  return;
5057
5459
  }
5058
- this.itemClicked.emit(event);
5059
- this.menu?.close();
5460
+ this.clicked.emit(event);
5461
+ this.menu?.close(true);
5060
5462
  }
5061
5463
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5062
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: MenuItemComponent, isStandalone: true, selector: "ea-menu-item", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClicked: "itemClicked" }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"ea-menu-item\"\n role=\"menuitem\"\n [class.ea-menu-item--disabled]=\"disabled()\"\n [class.ea-menu-item--danger]=\"variant() === 'danger'\"\n [disabled]=\"disabled()\"\n (click)=\"handleClick($event)\">\n <span class=\"ea-menu-item__icon\">\n <ng-content select=\"[slot=icon]\" />\n </span>\n <span class=\"ea-menu-item__label\">\n <ng-content />\n </span>\n</button>\n", styles: [".ea-menu-item{display:flex;align-items:center;gap:var(--space-2);width:100%;padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-family:var(--font-family-sans);text-align:left;border:none;background:transparent;color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-menu-item:hover:not(.ea-menu-item--disabled),.ea-menu-item:focus-visible:not(.ea-menu-item--disabled){background-color:var(--color-bg-muted)}.ea-menu-item:focus-visible{outline:none}.ea-menu-item--danger{color:var(--color-error-default)}.ea-menu-item--danger:hover:not(.ea-menu-item--disabled),.ea-menu-item--danger:focus-visible:not(.ea-menu-item--disabled){background-color:var(--color-error-subtle, var(--color-bg-muted))}.ea-menu-item--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-menu-item__icon{display:flex;flex-shrink:0;align-items:center;justify-content:center;width:1rem;height:1rem;color:inherit}.ea-menu-item__icon>*{width:1rem;height:1rem}.ea-menu-item__icon:empty{display:none}.ea-menu-item__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5464
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: MenuItemComponent, isStandalone: true, selector: "ea-menu-item", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, ngImport: i0, template: "<button\n type=\"button\"\n class=\"ea-menu-item\"\n role=\"menuitem\"\n [class.ea-menu-item--disabled]=\"disabled()\"\n [class.ea-menu-item--danger]=\"variant() === 'danger'\"\n [disabled]=\"disabled()\"\n (click)=\"handleClick($event)\">\n <span class=\"ea-menu-item__icon\">\n <ng-content select=\"[slot=icon]\" />\n </span>\n <span class=\"ea-menu-item__label\">\n <ng-content />\n </span>\n</button>\n", styles: [".ea-menu-item{display:flex;align-items:center;gap:var(--space-2);width:100%;padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-family:var(--font-family-sans);text-align:left;border:none;background:transparent;color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-menu-item:hover:not(.ea-menu-item--disabled),.ea-menu-item:focus-visible:not(.ea-menu-item--disabled){background-color:var(--color-bg-muted)}.ea-menu-item:focus-visible{outline:none}.ea-menu-item--danger{color:var(--color-error-default)}.ea-menu-item--danger:hover:not(.ea-menu-item--disabled),.ea-menu-item--danger:focus-visible:not(.ea-menu-item--disabled){background-color:var(--color-error-subtle, var(--color-bg-muted))}.ea-menu-item--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-menu-item__icon{display:flex;flex-shrink:0;align-items:center;justify-content:center;width:1rem;height:1rem;color:inherit}.ea-menu-item__icon>*{width:1rem;height:1rem}.ea-menu-item__icon:empty{display:none}.ea-menu-item__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5063
5465
  }
5064
5466
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuItemComponent, decorators: [{
5065
5467
  type: Component,
5066
5468
  args: [{ selector: 'ea-menu-item', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n type=\"button\"\n class=\"ea-menu-item\"\n role=\"menuitem\"\n [class.ea-menu-item--disabled]=\"disabled()\"\n [class.ea-menu-item--danger]=\"variant() === 'danger'\"\n [disabled]=\"disabled()\"\n (click)=\"handleClick($event)\">\n <span class=\"ea-menu-item__icon\">\n <ng-content select=\"[slot=icon]\" />\n </span>\n <span class=\"ea-menu-item__label\">\n <ng-content />\n </span>\n</button>\n", styles: [".ea-menu-item{display:flex;align-items:center;gap:var(--space-2);width:100%;padding:var(--space-2) var(--space-3);font-size:var(--font-size-sm);font-family:var(--font-family-sans);text-align:left;border:none;background:transparent;color:var(--color-text-primary);cursor:pointer;transition:var(--transition-colors)}.ea-menu-item:hover:not(.ea-menu-item--disabled),.ea-menu-item:focus-visible:not(.ea-menu-item--disabled){background-color:var(--color-bg-muted)}.ea-menu-item:focus-visible{outline:none}.ea-menu-item--danger{color:var(--color-error-default)}.ea-menu-item--danger:hover:not(.ea-menu-item--disabled),.ea-menu-item--danger:focus-visible:not(.ea-menu-item--disabled){background-color:var(--color-error-subtle, var(--color-bg-muted))}.ea-menu-item--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-menu-item__icon{display:flex;flex-shrink:0;align-items:center;justify-content:center;width:1rem;height:1rem;color:inherit}.ea-menu-item__icon>*{width:1rem;height:1rem}.ea-menu-item__icon:empty{display:none}.ea-menu-item__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"] }]
5067
- }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
5469
+ }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }] } });
5068
5470
 
5471
+ /**
5472
+ * Wires a focusable host element (typically a button) to an `ea-menu`,
5473
+ * handling click and keyboard activation (ArrowDown/Enter/Space to open,
5474
+ * Escape to close) and applying the appropriate ARIA attributes.
5475
+ */
5476
+ class MenuTriggerDirective {
5477
+ el = inject((ElementRef));
5478
+ menu = input.required({ ...(ngDevMode ? { debugName: "menu" } : /* istanbul ignore next */ {}), alias: 'eaMenuTrigger' });
5479
+ handleClick() {
5480
+ const m = this.menu();
5481
+ if (m.disabled())
5482
+ return;
5483
+ m.toggleAt(this.el.nativeElement);
5484
+ }
5485
+ handleKeydown(event) {
5486
+ const m = this.menu();
5487
+ if (m.disabled())
5488
+ return;
5489
+ if (event.key === 'ArrowDown' || event.key === 'Enter' || event.key === ' ') {
5490
+ event.preventDefault();
5491
+ if (!m.open())
5492
+ m.openAt(this.el.nativeElement);
5493
+ }
5494
+ else if (event.key === 'Escape' && m.open()) {
5495
+ event.preventDefault();
5496
+ m.close();
5497
+ }
5498
+ }
5499
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5500
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: MenuTriggerDirective, isStandalone: true, selector: "[eaMenuTrigger]", inputs: { menu: { classPropertyName: "menu", publicName: "eaMenuTrigger", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "click": "handleClick()", "keydown": "handleKeydown($event)" }, properties: { "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "menu()?.open() ?? false", "attr.aria-controls": "menu()?.id() ?? null" } }, ngImport: i0 });
5501
+ }
5502
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: MenuTriggerDirective, decorators: [{
5503
+ type: Directive,
5504
+ args: [{
5505
+ selector: '[eaMenuTrigger]',
5506
+ host: {
5507
+ '[attr.aria-haspopup]': '"menu"',
5508
+ '[attr.aria-expanded]': 'menu()?.open() ?? false',
5509
+ '[attr.aria-controls]': 'menu()?.id() ?? null',
5510
+ '(click)': 'handleClick()',
5511
+ '(keydown)': 'handleKeydown($event)',
5512
+ },
5513
+ }]
5514
+ }], propDecorators: { menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "eaMenuTrigger", required: true }] }] } });
5515
+
5516
+ /**
5517
+ * Page navigation control with previous/next buttons, numbered page jumps,
5518
+ * an optional page-size selector, and a range label. Exposes `page` and
5519
+ * `pageSize` as two-way `model()` bindings and emits a single `changed`
5520
+ * event whenever either changes.
5521
+ */
5069
5522
  class PaginatorComponent {
5070
5523
  totalItems = input.required(...(ngDevMode ? [{ debugName: "totalItems" }] : /* istanbul ignore next */ []));
5071
5524
  pageSizeOptions = input([10, 25, 50, 100], ...(ngDevMode ? [{ debugName: "pageSizeOptions" }] : /* istanbul ignore next */ []));
5072
5525
  showPageSizeSelector = input(true, ...(ngDevMode ? [{ debugName: "showPageSizeSelector" }] : /* istanbul ignore next */ []));
5073
5526
  showRangeLabel = input(true, ...(ngDevMode ? [{ debugName: "showRangeLabel" }] : /* istanbul ignore next */ []));
5074
- placement = input('right', ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
5527
+ align = input('right', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
5075
5528
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
5076
5529
  page = model(1, ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
5077
5530
  pageSize = model(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
5531
+ /** Fires when the user changes either the current page or the page size. */
5078
5532
  changed = output();
5079
5533
  totalPages = computed(() => Math.max(1, Math.ceil(this.totalItems() / this.pageSize())), ...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
5080
5534
  rangeStart = computed(() => this.totalItems() === 0 ? 0 : (this.page() - 1) * this.pageSize() + 1, ...(ngDevMode ? [{ debugName: "rangeStart" }] : /* istanbul ignore next */ []));
@@ -5105,6 +5559,7 @@ class PaginatorComponent {
5105
5559
  pages.push(total);
5106
5560
  return pages;
5107
5561
  }, ...(ngDevMode ? [{ debugName: "visiblePages" }] : /* istanbul ignore next */ []));
5562
+ /** Navigates to the given page, clamped into the valid range. */
5108
5563
  goToPage(page) {
5109
5564
  if (this.disabled())
5110
5565
  return;
@@ -5114,10 +5569,12 @@ class PaginatorComponent {
5114
5569
  this.page.set(clamped);
5115
5570
  this.changed.emit({ page: clamped, pageSize: this.pageSize() });
5116
5571
  }
5572
+ /** Navigates to the previous page if one exists. */
5117
5573
  prevPage() {
5118
5574
  if (this.canGoPrev())
5119
5575
  this.goToPage(this.page() - 1);
5120
5576
  }
5577
+ /** Navigates to the next page if one exists. */
5121
5578
  nextPage() {
5122
5579
  if (this.canGoNext())
5123
5580
  this.goToPage(this.page() + 1);
@@ -5131,19 +5588,24 @@ class PaginatorComponent {
5131
5588
  this.changed.emit({ page: 1, pageSize: newSize });
5132
5589
  }
5133
5590
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PaginatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5134
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PaginatorComponent, isStandalone: true, selector: "ea-paginator", inputs: { totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: true, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, showPageSizeSelector: { classPropertyName: "showPageSizeSelector", publicName: "showPageSizeSelector", isSignal: true, isRequired: false, transformFunction: null }, showRangeLabel: { classPropertyName: "showRangeLabel", publicName: "showRangeLabel", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "pageChange", pageSize: "pageSizeChange", changed: "changed" }, ngImport: i0, template: "<div\n class=\"ea-paginator\"\n [class.ea-paginator--left]=\"placement() === 'left'\"\n [class.ea-paginator--center]=\"placement() === 'center'\"\n [class.ea-paginator--disabled]=\"disabled()\"\n role=\"navigation\"\n aria-label=\"Pagination\">\n @if (showPageSizeSelector()) {\n <div class=\"ea-paginator__page-size\">\n <label\n class=\"ea-paginator__label\"\n for=\"ea-paginator-size\">\n Rows per page:\n </label>\n <select\n class=\"ea-paginator__select\"\n id=\"ea-paginator-size\"\n [disabled]=\"disabled()\"\n (change)=\"onPageSizeChange($event)\">\n @for (size of pageSizeOptions(); track size) {\n <option\n [value]=\"size\"\n [selected]=\"size === pageSize()\">\n {{ size }}\n </option>\n }\n </select>\n </div>\n }\n\n @if (showRangeLabel()) {\n <span class=\"ea-paginator__range\">\n {{ rangeStart() }}\u2013{{ rangeEnd() }} of {{ totalItems() }}\n </span>\n }\n\n <div class=\"ea-paginator__controls\">\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoPrev()\"\n aria-label=\"Previous page\"\n (clicked)=\"prevPage()\">\n <ea-icon-chevron-left />\n </ea-button>\n\n @for (p of visiblePages(); track $index) {\n @if (p === 'ellipsis') {\n <span class=\"ea-paginator__ellipsis\">\u2026</span>\n } @else {\n <ea-button\n class=\"ea-paginator__page-btn\"\n [class.ea-paginator__page-btn--active]=\"p === page()\"\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled()\"\n [aria-current]=\"p === page() ? 'page' : undefined\"\n (clicked)=\"goToPage(p)\">\n {{ p }}\n </ea-button>\n }\n }\n\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoNext()\"\n aria-label=\"Next page\"\n (clicked)=\"nextPage()\">\n <ea-icon-chevron-right />\n </ea-button>\n </div>\n</div>\n", styles: [".ea-paginator{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--space-4);padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-secondary);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-paginator--left{justify-content:flex-start}.ea-paginator--center{justify-content:center}.ea-paginator__page-size{display:flex;align-items:center;gap:var(--space-2)}.ea-paginator__label{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__select{padding:var(--space-1) calc(var(--space-2) + 1rem) var(--space-1) var(--space-2);font-size:var(--font-size-sm);font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 6px center;color:var(--color-text-primary);cursor:pointer;appearance:none;transition:var(--transition-colors),var(--transition-shadow)}.ea-paginator__select:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-paginator__select:disabled{opacity:.5;cursor:not-allowed}.ea-paginator__range{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__controls{display:flex;align-items:center;gap:var(--space-1)}.ea-paginator__controls ea-icon-chevron-left,.ea-paginator__controls ea-icon-chevron-right{width:1rem;height:1rem}.ea-paginator__page-btn--active .ea-button{font-weight:var(--font-weight-medium);border-color:var(--color-brand-default);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-paginator__page-btn--active .ea-button:hover:not(.ea-button--disabled){background-color:var(--color-brand-muted)}.ea-paginator__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--color-text-tertiary);pointer-events:none;-webkit-user-select:none;user-select:none}.ea-paginator--disabled{pointer-events:none}.ea-paginator--disabled .ea-paginator__range,.ea-paginator--disabled .ea-paginator__label{opacity:.5}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "ea-button", inputs: ["variant", "size", "type", "disabled", "loading", "fullWidth", "aria-label", "aria-current"], outputs: ["clicked"] }, { kind: "component", type: ChevronLeftIconComponent, selector: "ea-icon-chevron-left" }, { kind: "component", type: ChevronRightIconComponent, selector: "ea-icon-chevron-right" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5591
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: PaginatorComponent, isStandalone: true, selector: "ea-paginator", inputs: { totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: true, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, showPageSizeSelector: { classPropertyName: "showPageSizeSelector", publicName: "showPageSizeSelector", isSignal: true, isRequired: false, transformFunction: null }, showRangeLabel: { classPropertyName: "showRangeLabel", publicName: "showRangeLabel", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, page: { classPropertyName: "page", publicName: "page", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { page: "pageChange", pageSize: "pageSizeChange", changed: "changed" }, ngImport: i0, template: "<div\n class=\"ea-paginator\"\n [class.ea-paginator--left]=\"align() === 'left'\"\n [class.ea-paginator--center]=\"align() === 'center'\"\n [class.ea-paginator--disabled]=\"disabled()\"\n role=\"navigation\"\n aria-label=\"Pagination\">\n @if (showPageSizeSelector()) {\n <div class=\"ea-paginator__page-size\">\n <label\n class=\"ea-paginator__label\"\n for=\"ea-paginator-size\">\n Rows per page:\n </label>\n <select\n class=\"ea-paginator__select\"\n id=\"ea-paginator-size\"\n [disabled]=\"disabled()\"\n (change)=\"onPageSizeChange($event)\">\n @for (size of pageSizeOptions(); track size) {\n <option\n [value]=\"size\"\n [selected]=\"size === pageSize()\">\n {{ size }}\n </option>\n }\n </select>\n </div>\n }\n\n @if (showRangeLabel()) {\n <span class=\"ea-paginator__range\">\n {{ rangeStart() }}\u2013{{ rangeEnd() }} of {{ totalItems() }}\n </span>\n }\n\n <div class=\"ea-paginator__controls\">\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoPrev()\"\n aria-label=\"Previous page\"\n (clicked)=\"prevPage()\">\n <ea-icon-chevron-left />\n </ea-button>\n\n @for (p of visiblePages(); track $index) {\n @if (p === 'ellipsis') {\n <span class=\"ea-paginator__ellipsis\">\u2026</span>\n } @else {\n <ea-button\n class=\"ea-paginator__page-btn\"\n [class.ea-paginator__page-btn--active]=\"p === page()\"\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled()\"\n [aria-current]=\"p === page() ? 'page' : undefined\"\n (clicked)=\"goToPage(p)\">\n {{ p }}\n </ea-button>\n }\n }\n\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoNext()\"\n aria-label=\"Next page\"\n (clicked)=\"nextPage()\">\n <ea-icon-chevron-right />\n </ea-button>\n </div>\n</div>\n", styles: [".ea-paginator{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--space-4);padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-secondary);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-paginator--left{justify-content:flex-start}.ea-paginator--center{justify-content:center}.ea-paginator__page-size{display:flex;align-items:center;gap:var(--space-2)}.ea-paginator__label{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__select{padding:var(--space-1) calc(var(--space-2) + 1rem) var(--space-1) var(--space-2);font-size:var(--font-size-sm);font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 6px center;color:var(--color-text-primary);cursor:pointer;appearance:none;transition:var(--transition-colors),var(--transition-shadow)}.ea-paginator__select:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-paginator__select:disabled{opacity:.5;cursor:not-allowed}.ea-paginator__range{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__controls{display:flex;align-items:center;gap:var(--space-1)}.ea-paginator__controls ea-icon-chevron-left,.ea-paginator__controls ea-icon-chevron-right{width:1rem;height:1rem}.ea-paginator__page-btn--active .ea-button{font-weight:var(--font-weight-medium);border-color:var(--color-brand-default);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-paginator__page-btn--active .ea-button:hover:not(.ea-button--disabled){background-color:var(--color-brand-muted)}.ea-paginator__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--color-text-tertiary);pointer-events:none;-webkit-user-select:none;user-select:none}.ea-paginator--disabled{pointer-events:none}.ea-paginator--disabled .ea-paginator__range,.ea-paginator--disabled .ea-paginator__label{opacity:.5}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "ea-button", inputs: ["variant", "size", "type", "disabled", "loading", "fullWidth", "aria-label", "aria-current"], outputs: ["clicked"] }, { kind: "component", type: ChevronLeftIconComponent, selector: "ea-icon-chevron-left" }, { kind: "component", type: ChevronRightIconComponent, selector: "ea-icon-chevron-right" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5135
5592
  }
5136
5593
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PaginatorComponent, decorators: [{
5137
5594
  type: Component,
5138
- args: [{ selector: 'ea-paginator', imports: [ButtonComponent, ChevronLeftIconComponent, ChevronRightIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-paginator\"\n [class.ea-paginator--left]=\"placement() === 'left'\"\n [class.ea-paginator--center]=\"placement() === 'center'\"\n [class.ea-paginator--disabled]=\"disabled()\"\n role=\"navigation\"\n aria-label=\"Pagination\">\n @if (showPageSizeSelector()) {\n <div class=\"ea-paginator__page-size\">\n <label\n class=\"ea-paginator__label\"\n for=\"ea-paginator-size\">\n Rows per page:\n </label>\n <select\n class=\"ea-paginator__select\"\n id=\"ea-paginator-size\"\n [disabled]=\"disabled()\"\n (change)=\"onPageSizeChange($event)\">\n @for (size of pageSizeOptions(); track size) {\n <option\n [value]=\"size\"\n [selected]=\"size === pageSize()\">\n {{ size }}\n </option>\n }\n </select>\n </div>\n }\n\n @if (showRangeLabel()) {\n <span class=\"ea-paginator__range\">\n {{ rangeStart() }}\u2013{{ rangeEnd() }} of {{ totalItems() }}\n </span>\n }\n\n <div class=\"ea-paginator__controls\">\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoPrev()\"\n aria-label=\"Previous page\"\n (clicked)=\"prevPage()\">\n <ea-icon-chevron-left />\n </ea-button>\n\n @for (p of visiblePages(); track $index) {\n @if (p === 'ellipsis') {\n <span class=\"ea-paginator__ellipsis\">\u2026</span>\n } @else {\n <ea-button\n class=\"ea-paginator__page-btn\"\n [class.ea-paginator__page-btn--active]=\"p === page()\"\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled()\"\n [aria-current]=\"p === page() ? 'page' : undefined\"\n (clicked)=\"goToPage(p)\">\n {{ p }}\n </ea-button>\n }\n }\n\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoNext()\"\n aria-label=\"Next page\"\n (clicked)=\"nextPage()\">\n <ea-icon-chevron-right />\n </ea-button>\n </div>\n</div>\n", styles: [".ea-paginator{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--space-4);padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-secondary);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-paginator--left{justify-content:flex-start}.ea-paginator--center{justify-content:center}.ea-paginator__page-size{display:flex;align-items:center;gap:var(--space-2)}.ea-paginator__label{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__select{padding:var(--space-1) calc(var(--space-2) + 1rem) var(--space-1) var(--space-2);font-size:var(--font-size-sm);font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 6px center;color:var(--color-text-primary);cursor:pointer;appearance:none;transition:var(--transition-colors),var(--transition-shadow)}.ea-paginator__select:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-paginator__select:disabled{opacity:.5;cursor:not-allowed}.ea-paginator__range{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__controls{display:flex;align-items:center;gap:var(--space-1)}.ea-paginator__controls ea-icon-chevron-left,.ea-paginator__controls ea-icon-chevron-right{width:1rem;height:1rem}.ea-paginator__page-btn--active .ea-button{font-weight:var(--font-weight-medium);border-color:var(--color-brand-default);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-paginator__page-btn--active .ea-button:hover:not(.ea-button--disabled){background-color:var(--color-brand-muted)}.ea-paginator__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--color-text-tertiary);pointer-events:none;-webkit-user-select:none;user-select:none}.ea-paginator--disabled{pointer-events:none}.ea-paginator--disabled .ea-paginator__range,.ea-paginator--disabled .ea-paginator__label{opacity:.5}\n"] }]
5139
- }], propDecorators: { totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], showPageSizeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageSizeSelector", required: false }] }], showRangeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRangeLabel", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }, { type: i0.Output, args: ["pageChange"] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5595
+ args: [{ selector: 'ea-paginator', imports: [ButtonComponent, ChevronLeftIconComponent, ChevronRightIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-paginator\"\n [class.ea-paginator--left]=\"align() === 'left'\"\n [class.ea-paginator--center]=\"align() === 'center'\"\n [class.ea-paginator--disabled]=\"disabled()\"\n role=\"navigation\"\n aria-label=\"Pagination\">\n @if (showPageSizeSelector()) {\n <div class=\"ea-paginator__page-size\">\n <label\n class=\"ea-paginator__label\"\n for=\"ea-paginator-size\">\n Rows per page:\n </label>\n <select\n class=\"ea-paginator__select\"\n id=\"ea-paginator-size\"\n [disabled]=\"disabled()\"\n (change)=\"onPageSizeChange($event)\">\n @for (size of pageSizeOptions(); track size) {\n <option\n [value]=\"size\"\n [selected]=\"size === pageSize()\">\n {{ size }}\n </option>\n }\n </select>\n </div>\n }\n\n @if (showRangeLabel()) {\n <span class=\"ea-paginator__range\">\n {{ rangeStart() }}\u2013{{ rangeEnd() }} of {{ totalItems() }}\n </span>\n }\n\n <div class=\"ea-paginator__controls\">\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoPrev()\"\n aria-label=\"Previous page\"\n (clicked)=\"prevPage()\">\n <ea-icon-chevron-left />\n </ea-button>\n\n @for (p of visiblePages(); track $index) {\n @if (p === 'ellipsis') {\n <span class=\"ea-paginator__ellipsis\">\u2026</span>\n } @else {\n <ea-button\n class=\"ea-paginator__page-btn\"\n [class.ea-paginator__page-btn--active]=\"p === page()\"\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled()\"\n [aria-current]=\"p === page() ? 'page' : undefined\"\n (clicked)=\"goToPage(p)\">\n {{ p }}\n </ea-button>\n }\n }\n\n <ea-button\n variant=\"ghost\"\n size=\"sm\"\n [disabled]=\"disabled() || !canGoNext()\"\n aria-label=\"Next page\"\n (clicked)=\"nextPage()\">\n <ea-icon-chevron-right />\n </ea-button>\n </div>\n</div>\n", styles: [".ea-paginator{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--space-4);padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);color:var(--color-text-secondary);border-top:var(--border-width-thin) solid var(--color-border-default)}.ea-paginator--left{justify-content:flex-start}.ea-paginator--center{justify-content:center}.ea-paginator__page-size{display:flex;align-items:center;gap:var(--space-2)}.ea-paginator__label{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__select{padding:var(--space-1) calc(var(--space-2) + 1rem) var(--space-1) var(--space-2);font-size:var(--font-size-sm);font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);background-color:var(--color-bg-base);background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23666' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E\");background-repeat:no-repeat;background-position:right 6px center;color:var(--color-text-primary);cursor:pointer;appearance:none;transition:var(--transition-colors),var(--transition-shadow)}.ea-paginator__select:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-paginator__select:disabled{opacity:.5;cursor:not-allowed}.ea-paginator__range{white-space:nowrap;color:var(--color-text-secondary)}.ea-paginator__controls{display:flex;align-items:center;gap:var(--space-1)}.ea-paginator__controls ea-icon-chevron-left,.ea-paginator__controls ea-icon-chevron-right{width:1rem;height:1rem}.ea-paginator__page-btn--active .ea-button{font-weight:var(--font-weight-medium);border-color:var(--color-brand-default);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-paginator__page-btn--active .ea-button:hover:not(.ea-button--disabled){background-color:var(--color-brand-muted)}.ea-paginator__ellipsis{display:inline-flex;align-items:center;justify-content:center;min-width:2rem;height:2rem;color:var(--color-text-tertiary);pointer-events:none;-webkit-user-select:none;user-select:none}.ea-paginator--disabled{pointer-events:none}.ea-paginator--disabled .ea-paginator__range,.ea-paginator--disabled .ea-paginator__label{opacity:.5}\n"] }]
5596
+ }], propDecorators: { totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], showPageSizeSelector: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPageSizeSelector", required: false }] }], showRangeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRangeLabel", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }, { type: i0.Output, args: ["pageChange"] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5140
5597
 
5598
+ /**
5599
+ * Linear progress indicator supporting both determinate (driven by `value`
5600
+ * and `max`) and indeterminate modes. Optionally renders an inline label
5601
+ * and/or the current percentage.
5602
+ */
5141
5603
  class ProgressBarComponent {
5142
5604
  value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5143
5605
  max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
5144
5606
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
5145
5607
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5146
- label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5608
+ label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5147
5609
  showValue = input(false, ...(ngDevMode ? [{ debugName: "showValue" }] : /* istanbul ignore next */ []));
5148
5610
  indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
5149
5611
  percentage = computed(() => {
@@ -5159,28 +5621,42 @@ class ProgressBarComponent {
5159
5621
  'ea-progress-bar--indeterminate': this.indeterminate(),
5160
5622
  }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
5161
5623
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5162
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ProgressBarComponent, isStandalone: true, selector: "ea-progress-bar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-progress-bar\"\n [ngClass]=\"hostClasses()\">\n @if (label() || showValue()) {\n <div class=\"ea-progress-bar__header\">\n @if (label()) {\n <span class=\"ea-progress-bar__label\">{{ label() }}</span>\n }\n @if (showValue() && !indeterminate()) {\n <span class=\"ea-progress-bar__value\">{{ percentageRounded() }}%</span>\n }\n </div>\n }\n <div\n class=\"ea-progress-bar__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"indeterminate() ? null : percentageRounded()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-label]=\"label() || 'Progress'\">\n <div\n class=\"ea-progress-bar__fill\"\n [style.width]=\"indeterminate() ? null : percentage() + '%'\"></div>\n </div>\n</div>\n", styles: [".ea-progress-bar{display:flex;flex-direction:column;gap:var(--space-1-5);font-family:var(--font-family-sans)}.ea-progress-bar__header{display:flex;justify-content:space-between;align-items:baseline}.ea-progress-bar__label{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-primary)}.ea-progress-bar__value{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-secondary)}.ea-progress-bar__track{overflow:hidden;border-radius:var(--radius-full);background-color:var(--color-bg-muted)}.ea-progress-bar__fill{height:100%;border-radius:var(--radius-full);background-color:var(--color-brand-default);transition:width var(--duration-slow) var(--ease-out)}.ea-progress-bar--sm .ea-progress-bar__track{height:.25rem}.ea-progress-bar--md .ea-progress-bar__track{height:.375rem}.ea-progress-bar--lg .ea-progress-bar__track{height:.5rem}.ea-progress-bar--success .ea-progress-bar__fill{background-color:var(--color-success-default)}.ea-progress-bar--warning .ea-progress-bar__fill{background-color:var(--color-warning-default)}.ea-progress-bar--error .ea-progress-bar__fill{background-color:var(--color-error-default)}.ea-progress-bar--info .ea-progress-bar__fill{background-color:var(--color-info-default)}.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:40%;transition:none;animation:ea-progress-indeterminate 1.5s var(--ease-in-out) infinite}@keyframes ea-progress-indeterminate{0%{transform:translate(-110%)}to{transform:translate(260%)}}@media(prefers-reduced-motion:reduce){.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:100%;animation:none}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5624
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ProgressBarComponent, isStandalone: true, selector: "ea-progress-bar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-progress-bar\"\n [ngClass]=\"hostClasses()\">\n @if (label() || showValue()) {\n <div class=\"ea-progress-bar__header\">\n @if (label()) {\n <span class=\"ea-progress-bar__label\">{{ label() }}</span>\n }\n @if (showValue() && !indeterminate()) {\n <span class=\"ea-progress-bar__value\">{{ percentageRounded() }}%</span>\n }\n </div>\n }\n <div\n class=\"ea-progress-bar__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"indeterminate() ? null : percentageRounded()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-busy]=\"indeterminate() || null\"\n [attr.aria-label]=\"label() || 'Progress'\">\n <div\n class=\"ea-progress-bar__fill\"\n [style.width]=\"indeterminate() ? null : percentage() + '%'\"></div>\n </div>\n</div>\n", styles: [".ea-progress-bar{display:flex;flex-direction:column;gap:var(--space-1-5);font-family:var(--font-family-sans)}.ea-progress-bar__header{display:flex;justify-content:space-between;align-items:baseline}.ea-progress-bar__label{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-primary)}.ea-progress-bar__value{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-secondary)}.ea-progress-bar__track{overflow:hidden;border-radius:var(--radius-full);background-color:var(--color-bg-muted)}.ea-progress-bar__fill{height:100%;border-radius:var(--radius-full);background-color:var(--color-brand-default);transition:width var(--duration-slow) var(--ease-out)}.ea-progress-bar--sm .ea-progress-bar__track{height:.25rem}.ea-progress-bar--md .ea-progress-bar__track{height:.375rem}.ea-progress-bar--lg .ea-progress-bar__track{height:.5rem}.ea-progress-bar--success .ea-progress-bar__fill{background-color:var(--color-success-default)}.ea-progress-bar--warning .ea-progress-bar__fill{background-color:var(--color-warning-default)}.ea-progress-bar--error .ea-progress-bar__fill{background-color:var(--color-error-default)}.ea-progress-bar--info .ea-progress-bar__fill{background-color:var(--color-info-default)}.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:40%;transition:none;animation:ea-progress-indeterminate 1.5s var(--ease-in-out) infinite}@keyframes ea-progress-indeterminate{0%{transform:translate(-110%)}to{transform:translate(260%)}}@media(prefers-reduced-motion:reduce){.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:100%;animation:none}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5163
5625
  }
5164
5626
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ProgressBarComponent, decorators: [{
5165
5627
  type: Component,
5166
- args: [{ selector: 'ea-progress-bar', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-progress-bar\"\n [ngClass]=\"hostClasses()\">\n @if (label() || showValue()) {\n <div class=\"ea-progress-bar__header\">\n @if (label()) {\n <span class=\"ea-progress-bar__label\">{{ label() }}</span>\n }\n @if (showValue() && !indeterminate()) {\n <span class=\"ea-progress-bar__value\">{{ percentageRounded() }}%</span>\n }\n </div>\n }\n <div\n class=\"ea-progress-bar__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"indeterminate() ? null : percentageRounded()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-label]=\"label() || 'Progress'\">\n <div\n class=\"ea-progress-bar__fill\"\n [style.width]=\"indeterminate() ? null : percentage() + '%'\"></div>\n </div>\n</div>\n", styles: [".ea-progress-bar{display:flex;flex-direction:column;gap:var(--space-1-5);font-family:var(--font-family-sans)}.ea-progress-bar__header{display:flex;justify-content:space-between;align-items:baseline}.ea-progress-bar__label{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-primary)}.ea-progress-bar__value{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-secondary)}.ea-progress-bar__track{overflow:hidden;border-radius:var(--radius-full);background-color:var(--color-bg-muted)}.ea-progress-bar__fill{height:100%;border-radius:var(--radius-full);background-color:var(--color-brand-default);transition:width var(--duration-slow) var(--ease-out)}.ea-progress-bar--sm .ea-progress-bar__track{height:.25rem}.ea-progress-bar--md .ea-progress-bar__track{height:.375rem}.ea-progress-bar--lg .ea-progress-bar__track{height:.5rem}.ea-progress-bar--success .ea-progress-bar__fill{background-color:var(--color-success-default)}.ea-progress-bar--warning .ea-progress-bar__fill{background-color:var(--color-warning-default)}.ea-progress-bar--error .ea-progress-bar__fill{background-color:var(--color-error-default)}.ea-progress-bar--info .ea-progress-bar__fill{background-color:var(--color-info-default)}.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:40%;transition:none;animation:ea-progress-indeterminate 1.5s var(--ease-in-out) infinite}@keyframes ea-progress-indeterminate{0%{transform:translate(-110%)}to{transform:translate(260%)}}@media(prefers-reduced-motion:reduce){.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:100%;animation:none}}\n"] }]
5628
+ args: [{ selector: 'ea-progress-bar', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-progress-bar\"\n [ngClass]=\"hostClasses()\">\n @if (label() || showValue()) {\n <div class=\"ea-progress-bar__header\">\n @if (label()) {\n <span class=\"ea-progress-bar__label\">{{ label() }}</span>\n }\n @if (showValue() && !indeterminate()) {\n <span class=\"ea-progress-bar__value\">{{ percentageRounded() }}%</span>\n }\n </div>\n }\n <div\n class=\"ea-progress-bar__track\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"indeterminate() ? null : percentageRounded()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-busy]=\"indeterminate() || null\"\n [attr.aria-label]=\"label() || 'Progress'\">\n <div\n class=\"ea-progress-bar__fill\"\n [style.width]=\"indeterminate() ? null : percentage() + '%'\"></div>\n </div>\n</div>\n", styles: [".ea-progress-bar{display:flex;flex-direction:column;gap:var(--space-1-5);font-family:var(--font-family-sans)}.ea-progress-bar__header{display:flex;justify-content:space-between;align-items:baseline}.ea-progress-bar__label{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-primary)}.ea-progress-bar__value{font-size:var(--text-label-sm-size);font-weight:var(--text-label-sm-weight);line-height:var(--text-label-sm-lh);color:var(--color-text-secondary)}.ea-progress-bar__track{overflow:hidden;border-radius:var(--radius-full);background-color:var(--color-bg-muted)}.ea-progress-bar__fill{height:100%;border-radius:var(--radius-full);background-color:var(--color-brand-default);transition:width var(--duration-slow) var(--ease-out)}.ea-progress-bar--sm .ea-progress-bar__track{height:.25rem}.ea-progress-bar--md .ea-progress-bar__track{height:.375rem}.ea-progress-bar--lg .ea-progress-bar__track{height:.5rem}.ea-progress-bar--success .ea-progress-bar__fill{background-color:var(--color-success-default)}.ea-progress-bar--warning .ea-progress-bar__fill{background-color:var(--color-warning-default)}.ea-progress-bar--error .ea-progress-bar__fill{background-color:var(--color-error-default)}.ea-progress-bar--info .ea-progress-bar__fill{background-color:var(--color-info-default)}.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:40%;transition:none;animation:ea-progress-indeterminate 1.5s var(--ease-in-out) infinite}@keyframes ea-progress-indeterminate{0%{transform:translate(-110%)}to{transform:translate(260%)}}@media(prefers-reduced-motion:reduce){.ea-progress-bar--indeterminate .ea-progress-bar__fill{width:100%;animation:none}}\n"] }]
5167
5629
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }] } });
5168
5630
 
5631
+ /**
5632
+ * Composite single-select control made up of `ea-radio` children. Manages
5633
+ * shared state (name, size, disabled) for its options and integrates with
5634
+ * Angular forms via `ControlValueAccessor`.
5635
+ */
5169
5636
  class RadioGroupComponent {
5170
5637
  // Inputs
5638
+ id = input(`ea-radio-group-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
5171
5639
  name = input(`ea-radio-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
5172
5640
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5173
5641
  orientation = input('vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
5174
5642
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
5643
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
5644
+ label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5645
+ hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
5646
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
5175
5647
  ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
5176
5648
  // Two-way value binding
5177
5649
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5178
5650
  // Output
5651
+ /** Fires with the new value when an option is selected. */
5179
5652
  changed = output();
5180
5653
  // Internal state
5181
5654
  _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
5182
5655
  // Computed
5183
5656
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
5657
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
5658
+ showError = this.hasError;
5659
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
5184
5660
  // ControlValueAccessor callbacks
5185
5661
  onChange = () => { };
5186
5662
  onTouched = () => { };
@@ -5197,6 +5673,7 @@ class RadioGroupComponent {
5197
5673
  setDisabledState(isDisabled) {
5198
5674
  this._formDisabled.set(isDisabled);
5199
5675
  }
5676
+ /** Programmatically selects the option with the given value. */
5200
5677
  select(val) {
5201
5678
  if (this.isDisabled())
5202
5679
  return;
@@ -5206,13 +5683,13 @@ class RadioGroupComponent {
5206
5683
  this.changed.emit(val);
5207
5684
  }
5208
5685
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RadioGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5209
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: RadioGroupComponent, isStandalone: true, selector: "ea-radio-group", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, providers: [
5686
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: RadioGroupComponent, isStandalone: true, selector: "ea-radio-group", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, providers: [
5210
5687
  {
5211
5688
  provide: NG_VALUE_ACCESSOR,
5212
5689
  useExisting: forwardRef(() => RadioGroupComponent),
5213
5690
  multi: true,
5214
5691
  },
5215
- ], ngImport: i0, template: "<div\n class=\"ea-radio-group\"\n [class.ea-radio-group--horizontal]=\"orientation() === 'horizontal'\"\n [class.ea-radio-group--vertical]=\"orientation() === 'vertical'\"\n role=\"radiogroup\"\n [attr.aria-label]=\"ariaLabel()\">\n <ng-content />\n</div>\n", styles: [".ea-radio-group{display:flex}.ea-radio-group--vertical{flex-direction:column;gap:var(--space-2)}.ea-radio-group--horizontal{flex-direction:row;flex-wrap:wrap;gap:var(--space-4)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5692
+ ], ngImport: i0, template: "<div class=\"ea-radio-group-field\">\n @if (label()) {\n <span\n class=\"ea-radio-group-field__label\"\n [id]=\"id() + '-label'\"\n [class.ea-radio-group-field__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n\n <div\n class=\"ea-radio-group\"\n [class.ea-radio-group--horizontal]=\"orientation() === 'horizontal'\"\n [class.ea-radio-group--vertical]=\"orientation() === 'vertical'\"\n role=\"radiogroup\"\n [id]=\"id()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n <ng-content />\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-radio-group-field__message ea-radio-group-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-radio-group-field__message ea-radio-group-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-radio-group-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-radio-group-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-radio-group-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-radio-group-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-radio-group-field__message--hint{color:var(--color-text-secondary)}.ea-radio-group-field__message--error{color:var(--color-error-default)}.ea-radio-group{display:flex}.ea-radio-group--vertical{flex-direction:column;gap:var(--space-2)}.ea-radio-group--horizontal{flex-direction:row;flex-wrap:wrap;gap:var(--space-4)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5216
5693
  }
5217
5694
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RadioGroupComponent, decorators: [{
5218
5695
  type: Component,
@@ -5222,9 +5699,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
5222
5699
  useExisting: forwardRef(() => RadioGroupComponent),
5223
5700
  multi: true,
5224
5701
  },
5225
- ], template: "<div\n class=\"ea-radio-group\"\n [class.ea-radio-group--horizontal]=\"orientation() === 'horizontal'\"\n [class.ea-radio-group--vertical]=\"orientation() === 'vertical'\"\n role=\"radiogroup\"\n [attr.aria-label]=\"ariaLabel()\">\n <ng-content />\n</div>\n", styles: [".ea-radio-group{display:flex}.ea-radio-group--vertical{flex-direction:column;gap:var(--space-2)}.ea-radio-group--horizontal{flex-direction:row;flex-wrap:wrap;gap:var(--space-4)}\n"] }]
5226
- }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5702
+ ], template: "<div class=\"ea-radio-group-field\">\n @if (label()) {\n <span\n class=\"ea-radio-group-field__label\"\n [id]=\"id() + '-label'\"\n [class.ea-radio-group-field__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n\n <div\n class=\"ea-radio-group\"\n [class.ea-radio-group--horizontal]=\"orientation() === 'horizontal'\"\n [class.ea-radio-group--vertical]=\"orientation() === 'vertical'\"\n role=\"radiogroup\"\n [id]=\"id()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n <ng-content />\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-radio-group-field__message ea-radio-group-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-radio-group-field__message ea-radio-group-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-radio-group-field{display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-radio-group-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-radio-group-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-radio-group-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-radio-group-field__message--hint{color:var(--color-text-secondary)}.ea-radio-group-field__message--error{color:var(--color-error-default)}.ea-radio-group{display:flex}.ea-radio-group--vertical{flex-direction:column;gap:var(--space-2)}.ea-radio-group--horizontal{flex-direction:row;flex-wrap:wrap;gap:var(--space-4)}\n"] }]
5703
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5227
5704
 
5705
+ /**
5706
+ * Single radio option used inside an `ea-radio-group`. Inherits its size and
5707
+ * disabled state from the parent group and selecting it updates the group's
5708
+ * value.
5709
+ */
5228
5710
  class RadioComponent {
5229
5711
  group = inject(RadioGroupComponent);
5230
5712
  // Inputs
@@ -5255,6 +5737,307 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
5255
5737
  args: [{ selector: 'ea-radio', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass], template: "<label\n class=\"ea-radio\"\n [ngClass]=\"hostClasses()\"\n [for]=\"id()\">\n <input\n type=\"radio\"\n class=\"ea-radio__input\"\n [id]=\"id()\"\n [name]=\"name()\"\n [value]=\"value()\"\n [checked]=\"isChecked()\"\n [disabled]=\"isDisabled()\"\n (change)=\"handleChange()\" />\n\n <span\n class=\"ea-radio__circle\"\n aria-hidden=\"true\">\n </span>\n\n @if (label()) {\n <span class=\"ea-radio__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".ea-radio{display:inline-flex;align-items:flex-start;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-radio--sm .ea-radio__circle{width:1rem;height:1rem}.ea-radio--sm .ea-radio__label{font-size:var(--font-size-sm);line-height:1rem}.ea-radio--md .ea-radio__circle{width:1.25rem;height:1.25rem}.ea-radio--md .ea-radio__label{font-size:var(--font-size-sm);line-height:1.25rem}.ea-radio--lg .ea-radio__circle{width:1.5rem;height:1.5rem}.ea-radio--lg .ea-radio__label{font-size:var(--font-size-md);line-height:1.5rem}.ea-radio--disabled{opacity:.45;cursor:not-allowed}.ea-radio--checked .ea-radio__circle{border-color:var(--color-brand-default)}.ea-radio--checked .ea-radio__circle:after{transform:scale(1)}.ea-radio:hover:not(.ea-radio--disabled) .ea-radio__circle{border-color:var(--color-brand-default)}.ea-radio__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-radio__input:focus-visible+.ea-radio__circle{box-shadow:var(--shadow-focus-ring)}.ea-radio__circle{display:flex;align-items:center;justify-content:center;flex-shrink:0;border-radius:var(--radius-full);background-color:var(--color-bg-base);border:var(--border-width-medium) solid var(--color-border-strong);transition:var(--transition-colors),var(--transition-shadow)}.ea-radio__circle:after{content:\"\";display:block;width:45%;height:45%;border-radius:var(--radius-full);background-color:var(--color-brand-default);transform:scale(0);transition:var(--transition-transform)}.ea-radio__label{font-weight:var(--font-weight-regular)}\n"] }]
5256
5738
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
5257
5739
 
5740
+ /**
5741
+ * Compact toggle button group for picking one of a small set of options
5742
+ * (e.g. List/Grid/Kanban or Light/Dark). Implements `radiogroup` semantics
5743
+ * and `ControlValueAccessor`, with full keyboard support
5744
+ * (arrow keys, Home/End, Enter/Space).
5745
+ */
5746
+ class SegmentedComponent {
5747
+ buttonEls = viewChildren('optionEl', ...(ngDevMode ? [{ debugName: "buttonEls" }] : /* istanbul ignore next */ []));
5748
+ options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
5749
+ label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5750
+ hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
5751
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
5752
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5753
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
5754
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
5755
+ fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : /* istanbul ignore next */ []));
5756
+ ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
5757
+ id = input(`ea-segmented-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
5758
+ value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5759
+ /** Fires with the new value when the user selects a different option. */
5760
+ changed = output();
5761
+ _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
5762
+ onChange = () => { };
5763
+ onTouched = () => { };
5764
+ isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
5765
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
5766
+ showError = this.hasError;
5767
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
5768
+ enabledOptions = computed(() => this.options().filter(opt => !opt.disabled), ...(ngDevMode ? [{ debugName: "enabledOptions" }] : /* istanbul ignore next */ []));
5769
+ hostClasses = computed(() => ({
5770
+ [`ea-segmented--${this.size()}`]: true,
5771
+ 'ea-segmented--full-width': this.fullWidth(),
5772
+ 'ea-segmented--disabled': this.isDisabled(),
5773
+ 'ea-segmented--error': this.hasError(),
5774
+ }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
5775
+ writeValue(val) {
5776
+ this.value.set(val ?? '');
5777
+ }
5778
+ registerOnChange(fn) {
5779
+ this.onChange = fn;
5780
+ }
5781
+ registerOnTouched(fn) {
5782
+ this.onTouched = fn;
5783
+ }
5784
+ setDisabledState(isDisabled) {
5785
+ this._formDisabled.set(isDisabled);
5786
+ }
5787
+ isSelected(option) {
5788
+ return this.value() === option.value;
5789
+ }
5790
+ isOptionDisabled(option) {
5791
+ return this.isDisabled() || !!option.disabled;
5792
+ }
5793
+ /** Programmatically selects the given option. */
5794
+ select(option) {
5795
+ if (this.isOptionDisabled(option))
5796
+ return;
5797
+ if (this.value() === option.value) {
5798
+ this.onTouched();
5799
+ return;
5800
+ }
5801
+ this.value.set(option.value);
5802
+ this.onChange(option.value);
5803
+ this.onTouched();
5804
+ this.changed.emit(option.value);
5805
+ }
5806
+ handleKeydown(event, index) {
5807
+ if (this.isDisabled())
5808
+ return;
5809
+ const enabled = this.enabledOptions();
5810
+ if (enabled.length === 0)
5811
+ return;
5812
+ let targetValue = null;
5813
+ switch (event.key) {
5814
+ case 'ArrowRight':
5815
+ case 'ArrowDown': {
5816
+ const current = enabled.findIndex(o => o.value === this.value());
5817
+ const nextIndex = (current + 1 + enabled.length) % enabled.length;
5818
+ targetValue = enabled[nextIndex].value;
5819
+ break;
5820
+ }
5821
+ case 'ArrowLeft':
5822
+ case 'ArrowUp': {
5823
+ const current = enabled.findIndex(o => o.value === this.value());
5824
+ const prevIndex = (current - 1 + enabled.length) % enabled.length;
5825
+ targetValue = enabled[prevIndex].value;
5826
+ break;
5827
+ }
5828
+ case 'Home':
5829
+ targetValue = enabled[0].value;
5830
+ break;
5831
+ case 'End':
5832
+ targetValue = enabled[enabled.length - 1].value;
5833
+ break;
5834
+ case ' ':
5835
+ case 'Enter': {
5836
+ const opt = this.options()[index];
5837
+ if (opt)
5838
+ this.select(opt);
5839
+ event.preventDefault();
5840
+ return;
5841
+ }
5842
+ default:
5843
+ return;
5844
+ }
5845
+ if (targetValue !== null) {
5846
+ event.preventDefault();
5847
+ const opt = this.options().find(o => o.value === targetValue);
5848
+ if (opt) {
5849
+ this.select(opt);
5850
+ const targetIndex = this.options().findIndex(o => o.value === targetValue);
5851
+ queueMicrotask(() => this.buttonEls()[targetIndex]?.nativeElement.focus());
5852
+ }
5853
+ }
5854
+ }
5855
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SegmentedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5856
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SegmentedComponent, isStandalone: true, selector: "ea-segmented", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, providers: [
5857
+ {
5858
+ provide: NG_VALUE_ACCESSOR,
5859
+ useExisting: forwardRef(() => SegmentedComponent),
5860
+ multi: true,
5861
+ },
5862
+ ], viewQueries: [{ propertyName: "buttonEls", predicate: ["optionEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-segmented-field\">\n @if (label()) {\n <span\n class=\"ea-segmented-field__label\"\n [id]=\"id() + '-label'\"\n [class.ea-segmented-field__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n\n <div\n class=\"ea-segmented\"\n role=\"radiogroup\"\n [ngClass]=\"hostClasses()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n @for (option of options(); track option.value; let i = $index) {\n <button\n #optionEl\n type=\"button\"\n class=\"ea-segmented__option\"\n role=\"radio\"\n [class.ea-segmented__option--selected]=\"isSelected(option)\"\n [class.ea-segmented__option--disabled]=\"isOptionDisabled(option)\"\n [attr.aria-checked]=\"isSelected(option)\"\n [attr.aria-disabled]=\"isOptionDisabled(option) || null\"\n [disabled]=\"isOptionDisabled(option)\"\n [attr.tabindex]=\"isSelected(option) || (!value() && i === 0) ? 0 : -1\"\n (click)=\"select(option)\"\n (keydown)=\"handleKeydown($event, i)\">\n {{ option.label }}\n </button>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-segmented-field__message ea-segmented-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-segmented-field__message ea-segmented-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-segmented-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-segmented-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-segmented-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-segmented-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-segmented-field__message--hint{color:var(--color-text-secondary)}.ea-segmented-field__message--error{color:var(--color-error-default)}.ea-segmented{display:inline-flex;flex-direction:row;padding:var(--space-0-5);background-color:var(--color-bg-muted);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans)}.ea-segmented--full-width{display:flex;width:100%}.ea-segmented--full-width .ea-segmented__option{flex:1}.ea-segmented--disabled{opacity:.5;cursor:not-allowed}.ea-segmented--error{border-color:var(--color-error-default)}.ea-segmented--sm .ea-segmented__option{min-height:1.75rem;padding:var(--space-1) var(--space-2-5);font-size:var(--font-size-sm)}.ea-segmented--md .ea-segmented__option{min-height:2.25rem;padding:var(--space-1-5) var(--space-3);font-size:var(--font-size-md)}.ea-segmented--lg .ea-segmented__option{min-height:2.75rem;padding:var(--space-2) var(--space-4);font-size:var(--font-size-md)}.ea-segmented__option{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1-5);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight);background:transparent;border:var(--border-width-thin) solid transparent;border-radius:var(--radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow)}.ea-segmented__option:hover:not(.ea-segmented__option--selected):not(.ea-segmented__option--disabled){color:var(--color-text-primary);background-color:var(--color-bg-subtle)}.ea-segmented__option:focus-visible{box-shadow:var(--shadow-focus-ring);outline:none}.ea-segmented__option--selected{background-color:var(--color-bg-base);border-color:var(--color-border-default);color:var(--color-text-primary);box-shadow:var(--shadow-sm)}.ea-segmented__option--disabled{cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5863
+ }
5864
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SegmentedComponent, decorators: [{
5865
+ type: Component,
5866
+ args: [{ selector: 'ea-segmented', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass], providers: [
5867
+ {
5868
+ provide: NG_VALUE_ACCESSOR,
5869
+ useExisting: forwardRef(() => SegmentedComponent),
5870
+ multi: true,
5871
+ },
5872
+ ], template: "<div class=\"ea-segmented-field\">\n @if (label()) {\n <span\n class=\"ea-segmented-field__label\"\n [id]=\"id() + '-label'\"\n [class.ea-segmented-field__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n\n <div\n class=\"ea-segmented\"\n role=\"radiogroup\"\n [ngClass]=\"hostClasses()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \">\n @for (option of options(); track option.value; let i = $index) {\n <button\n #optionEl\n type=\"button\"\n class=\"ea-segmented__option\"\n role=\"radio\"\n [class.ea-segmented__option--selected]=\"isSelected(option)\"\n [class.ea-segmented__option--disabled]=\"isOptionDisabled(option)\"\n [attr.aria-checked]=\"isSelected(option)\"\n [attr.aria-disabled]=\"isOptionDisabled(option) || null\"\n [disabled]=\"isOptionDisabled(option)\"\n [attr.tabindex]=\"isSelected(option) || (!value() && i === 0) ? 0 : -1\"\n (click)=\"select(option)\"\n (keydown)=\"handleKeydown($event, i)\">\n {{ option.label }}\n </button>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-segmented-field__message ea-segmented-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-segmented-field__message ea-segmented-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-segmented-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-segmented-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-segmented-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-segmented-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-segmented-field__message--hint{color:var(--color-text-secondary)}.ea-segmented-field__message--error{color:var(--color-error-default)}.ea-segmented{display:inline-flex;flex-direction:row;padding:var(--space-0-5);background-color:var(--color-bg-muted);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans)}.ea-segmented--full-width{display:flex;width:100%}.ea-segmented--full-width .ea-segmented__option{flex:1}.ea-segmented--disabled{opacity:.5;cursor:not-allowed}.ea-segmented--error{border-color:var(--color-error-default)}.ea-segmented--sm .ea-segmented__option{min-height:1.75rem;padding:var(--space-1) var(--space-2-5);font-size:var(--font-size-sm)}.ea-segmented--md .ea-segmented__option{min-height:2.25rem;padding:var(--space-1-5) var(--space-3);font-size:var(--font-size-md)}.ea-segmented--lg .ea-segmented__option{min-height:2.75rem;padding:var(--space-2) var(--space-4);font-size:var(--font-size-md)}.ea-segmented__option{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-1-5);font-weight:var(--font-weight-medium);line-height:var(--line-height-tight);background:transparent;border:var(--border-width-thin) solid transparent;border-radius:var(--radius-sm);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow)}.ea-segmented__option:hover:not(.ea-segmented__option--selected):not(.ea-segmented__option--disabled){color:var(--color-text-primary);background-color:var(--color-bg-subtle)}.ea-segmented__option:focus-visible{box-shadow:var(--shadow-focus-ring);outline:none}.ea-segmented__option--selected{background-color:var(--color-bg-base);border-color:var(--color-border-default);color:var(--color-text-primary);box-shadow:var(--shadow-sm)}.ea-segmented__option--disabled{cursor:not-allowed}\n"] }]
5873
+ }], propDecorators: { buttonEls: [{ type: i0.ViewChildren, args: ['optionEl', { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5874
+
5875
+ /**
5876
+ * Single-value range input controlled with pointer drag or full keyboard
5877
+ * navigation (arrows, PageUp/PageDown, Home/End). Supports configurable
5878
+ * `min`, `max`, and `step`, optional value display, and integrates with
5879
+ * Angular forms via `ControlValueAccessor`.
5880
+ */
5881
+ class SliderComponent {
5882
+ trackEl = viewChild('trackEl', ...(ngDevMode ? [{ debugName: "trackEl" }] : /* istanbul ignore next */ []));
5883
+ label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5884
+ hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
5885
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
5886
+ min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
5887
+ max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
5888
+ step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
5889
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5890
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
5891
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
5892
+ showValue = input(false, ...(ngDevMode ? [{ debugName: "showValue" }] : /* istanbul ignore next */ []));
5893
+ showMinMaxLabels = input(false, ...(ngDevMode ? [{ debugName: "showMinMaxLabels" }] : /* istanbul ignore next */ []));
5894
+ formatValue = input(value => `${value}`, ...(ngDevMode ? [{ debugName: "formatValue" }] : /* istanbul ignore next */ []));
5895
+ ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
5896
+ id = input(`ea-slider-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
5897
+ value = model(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5898
+ /** Fires with the new (snapped, clamped) numeric value whenever the slider moves. */
5899
+ changed = output();
5900
+ _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
5901
+ dragging = signal(false, ...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
5902
+ onChange = () => { };
5903
+ onTouched = () => { };
5904
+ isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
5905
+ clampedValue = computed(() => {
5906
+ const v = this.value();
5907
+ return Math.min(this.max(), Math.max(this.min(), v));
5908
+ }, ...(ngDevMode ? [{ debugName: "clampedValue" }] : /* istanbul ignore next */ []));
5909
+ percent = computed(() => {
5910
+ const range = this.max() - this.min();
5911
+ if (range <= 0)
5912
+ return 0;
5913
+ return ((this.clampedValue() - this.min()) / range) * 100;
5914
+ }, ...(ngDevMode ? [{ debugName: "percent" }] : /* istanbul ignore next */ []));
5915
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
5916
+ showError = this.hasError;
5917
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
5918
+ hostClasses = computed(() => ({
5919
+ [`ea-slider--${this.size()}`]: true,
5920
+ 'ea-slider--error': this.hasError(),
5921
+ 'ea-slider--disabled': this.isDisabled(),
5922
+ 'ea-slider--dragging': this.dragging(),
5923
+ }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
5924
+ writeValue(val) {
5925
+ this.value.set(typeof val === 'number' && !isNaN(val) ? val : this.min());
5926
+ }
5927
+ registerOnChange(fn) {
5928
+ this.onChange = fn;
5929
+ }
5930
+ registerOnTouched(fn) {
5931
+ this.onTouched = fn;
5932
+ }
5933
+ setDisabledState(isDisabled) {
5934
+ this._formDisabled.set(isDisabled);
5935
+ }
5936
+ handleKeydown(event) {
5937
+ if (this.isDisabled())
5938
+ return;
5939
+ const step = this.step();
5940
+ const bigStep = Math.max(step * 10, (this.max() - this.min()) / 10);
5941
+ let next;
5942
+ switch (event.key) {
5943
+ case 'ArrowRight':
5944
+ case 'ArrowUp':
5945
+ next = this.clampedValue() + step;
5946
+ break;
5947
+ case 'ArrowLeft':
5948
+ case 'ArrowDown':
5949
+ next = this.clampedValue() - step;
5950
+ break;
5951
+ case 'PageUp':
5952
+ next = this.clampedValue() + bigStep;
5953
+ break;
5954
+ case 'PageDown':
5955
+ next = this.clampedValue() - bigStep;
5956
+ break;
5957
+ case 'Home':
5958
+ next = this.min();
5959
+ break;
5960
+ case 'End':
5961
+ next = this.max();
5962
+ break;
5963
+ default:
5964
+ return;
5965
+ }
5966
+ event.preventDefault();
5967
+ this.commitValue(next);
5968
+ }
5969
+ handlePointerDown(event) {
5970
+ if (this.isDisabled())
5971
+ return;
5972
+ const track = this.trackEl()?.nativeElement;
5973
+ if (!track)
5974
+ return;
5975
+ event.target.setPointerCapture?.(event.pointerId);
5976
+ this.dragging.set(true);
5977
+ this.updateFromPointer(event, track);
5978
+ }
5979
+ handlePointerMove(event) {
5980
+ if (!this.dragging() || this.isDisabled())
5981
+ return;
5982
+ const track = this.trackEl()?.nativeElement;
5983
+ if (!track)
5984
+ return;
5985
+ this.updateFromPointer(event, track);
5986
+ }
5987
+ handlePointerUp(event) {
5988
+ if (!this.dragging())
5989
+ return;
5990
+ event.target.releasePointerCapture?.(event.pointerId);
5991
+ this.dragging.set(false);
5992
+ this.onTouched();
5993
+ }
5994
+ handleBlur() {
5995
+ this.onTouched();
5996
+ }
5997
+ updateFromPointer(event, track) {
5998
+ const rect = track.getBoundingClientRect();
5999
+ const ratio = Math.min(1, Math.max(0, (event.clientX - rect.left) / rect.width));
6000
+ const range = this.max() - this.min();
6001
+ const raw = this.min() + ratio * range;
6002
+ this.commitValue(raw);
6003
+ }
6004
+ commitValue(raw) {
6005
+ const step = this.step();
6006
+ const min = this.min();
6007
+ const max = this.max();
6008
+ const snapped = Math.round((raw - min) / step) * step + min;
6009
+ const clamped = Math.min(max, Math.max(min, snapped));
6010
+ const rounded = Number(clamped.toFixed(10));
6011
+ if (rounded === this.value())
6012
+ return;
6013
+ this.value.set(rounded);
6014
+ this.onChange(rounded);
6015
+ this.changed.emit(rounded);
6016
+ }
6017
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SliderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6018
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SliderComponent, isStandalone: true, selector: "ea-slider", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, showMinMaxLabels: { classPropertyName: "showMinMaxLabels", publicName: "showMinMaxLabels", isSignal: true, isRequired: false, transformFunction: null }, formatValue: { classPropertyName: "formatValue", publicName: "formatValue", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, providers: [
6019
+ {
6020
+ provide: NG_VALUE_ACCESSOR,
6021
+ useExisting: forwardRef(() => SliderComponent),
6022
+ multi: true,
6023
+ },
6024
+ ], viewQueries: [{ propertyName: "trackEl", first: true, predicate: ["trackEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"ea-slider-field\"\n [ngClass]=\"hostClasses()\">\n @if (label()) {\n <span\n class=\"ea-slider-field__label\"\n [id]=\"id() + '-label'\"\n [class.ea-slider-field__label--required]=\"required()\">\n {{ label() }}\n @if (showValue()) {\n <span class=\"ea-slider-field__value\">{{ formatValue()(clampedValue()) }}</span>\n }\n </span>\n }\n\n <div class=\"ea-slider\">\n <div\n #trackEl\n class=\"ea-slider__track\"\n (pointerdown)=\"handlePointerDown($event)\"\n (pointermove)=\"handlePointerMove($event)\"\n (pointerup)=\"handlePointerUp($event)\"\n (pointercancel)=\"handlePointerUp($event)\">\n <div\n class=\"ea-slider__fill\"\n [style.width.%]=\"percent()\">\n </div>\n <div\n class=\"ea-slider__thumb\"\n role=\"slider\"\n tabindex=\"0\"\n [id]=\"id()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"clampedValue()\"\n [attr.aria-valuetext]=\"formatValue()(clampedValue())\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n [style.left.%]=\"percent()\"\n (keydown)=\"handleKeydown($event)\"\n (blur)=\"handleBlur()\">\n </div>\n </div>\n\n @if (showMinMaxLabels()) {\n <div class=\"ea-slider__minmax\">\n <span class=\"ea-slider__minmax-label\">{{ formatValue()(min()) }}</span>\n <span class=\"ea-slider__minmax-label\">{{ formatValue()(max()) }}</span>\n </div>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-slider-field__message ea-slider-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-slider-field__message ea-slider-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-slider-field{display:flex;flex-direction:column;gap:var(--space-2);font-family:var(--font-family-sans);color:var(--color-text-secondary)}.ea-slider-field__label{display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-2);font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-slider-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-slider-field__value{font-variant-numeric:tabular-nums;font-weight:var(--font-weight-medium);color:var(--color-text-secondary)}.ea-slider-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-slider-field__message--hint{color:inherit}.ea-slider-field__message--error{color:var(--color-error-default)}.ea-slider{display:flex;flex-direction:column;gap:var(--space-1);width:100%}.ea-slider--sm .ea-slider .ea-slider__track{height:.25rem}.ea-slider--sm .ea-slider .ea-slider__thumb{width:.875rem;height:.875rem}.ea-slider--md .ea-slider .ea-slider__track{height:.375rem}.ea-slider--md .ea-slider .ea-slider__thumb{width:1.125rem;height:1.125rem}.ea-slider--lg .ea-slider .ea-slider__track{height:.5rem}.ea-slider--lg .ea-slider .ea-slider__thumb{width:1.375rem;height:1.375rem}.ea-slider__track{position:relative;width:100%;background-color:var(--color-bg-muted);border-radius:var(--radius-full);cursor:pointer;touch-action:none}.ea-slider__fill{position:absolute;top:0;left:0;height:100%;background-color:var(--color-brand-default);border-radius:inherit;transition:var(--transition-colors)}.ea-slider__thumb{position:absolute;top:50%;background-color:var(--color-neutral-0);border:var(--border-width-medium) solid var(--color-brand-default);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);cursor:grab;transform:translate(-50%,-50%);transition:box-shadow var(--duration-fast) var(--ease-out),transform var(--duration-fast) var(--ease-out)}.ea-slider__thumb:focus-visible{box-shadow:var(--shadow-focus-ring);outline:none}.ea-slider__minmax{display:flex;justify-content:space-between;margin-top:var(--space-1)}.ea-slider__minmax-label{font-size:var(--font-size-xs);color:var(--color-text-tertiary);font-variant-numeric:tabular-nums}.ea-slider--dragging .ea-slider__thumb{cursor:grabbing;transform:translate(-50%,-50%) scale(1.1)}.ea-slider--disabled{opacity:.5;cursor:not-allowed}.ea-slider--disabled .ea-slider__track,.ea-slider--disabled .ea-slider__thumb{cursor:not-allowed}.ea-slider--error .ea-slider__fill{background-color:var(--color-error-default)}.ea-slider--error .ea-slider__thumb{border-color:var(--color-error-default)}.ea-slider--error .ea-slider__thumb:focus-visible{box-shadow:var(--shadow-focus-ring-error)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6025
+ }
6026
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SliderComponent, decorators: [{
6027
+ type: Component,
6028
+ args: [{ selector: 'ea-slider', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgClass], providers: [
6029
+ {
6030
+ provide: NG_VALUE_ACCESSOR,
6031
+ useExisting: forwardRef(() => SliderComponent),
6032
+ multi: true,
6033
+ },
6034
+ ], template: "<div\n class=\"ea-slider-field\"\n [ngClass]=\"hostClasses()\">\n @if (label()) {\n <span\n class=\"ea-slider-field__label\"\n [id]=\"id() + '-label'\"\n [class.ea-slider-field__label--required]=\"required()\">\n {{ label() }}\n @if (showValue()) {\n <span class=\"ea-slider-field__value\">{{ formatValue()(clampedValue()) }}</span>\n }\n </span>\n }\n\n <div class=\"ea-slider\">\n <div\n #trackEl\n class=\"ea-slider__track\"\n (pointerdown)=\"handlePointerDown($event)\"\n (pointermove)=\"handlePointerMove($event)\"\n (pointerup)=\"handlePointerUp($event)\"\n (pointercancel)=\"handlePointerUp($event)\">\n <div\n class=\"ea-slider__fill\"\n [style.width.%]=\"percent()\">\n </div>\n <div\n class=\"ea-slider__thumb\"\n role=\"slider\"\n tabindex=\"0\"\n [id]=\"id()\"\n [attr.aria-labelledby]=\"label() ? id() + '-label' : null\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-valuemin]=\"min()\"\n [attr.aria-valuemax]=\"max()\"\n [attr.aria-valuenow]=\"clampedValue()\"\n [attr.aria-valuetext]=\"formatValue()(clampedValue())\"\n [attr.aria-disabled]=\"isDisabled() || null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n [style.left.%]=\"percent()\"\n (keydown)=\"handleKeydown($event)\"\n (blur)=\"handleBlur()\">\n </div>\n </div>\n\n @if (showMinMaxLabels()) {\n <div class=\"ea-slider__minmax\">\n <span class=\"ea-slider__minmax-label\">{{ formatValue()(min()) }}</span>\n <span class=\"ea-slider__minmax-label\">{{ formatValue()(max()) }}</span>\n </div>\n }\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-slider-field__message ea-slider-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-slider-field__message ea-slider-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-slider-field{display:flex;flex-direction:column;gap:var(--space-2);font-family:var(--font-family-sans);color:var(--color-text-secondary)}.ea-slider-field__label{display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-2);font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-slider-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-slider-field__value{font-variant-numeric:tabular-nums;font-weight:var(--font-weight-medium);color:var(--color-text-secondary)}.ea-slider-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-slider-field__message--hint{color:inherit}.ea-slider-field__message--error{color:var(--color-error-default)}.ea-slider{display:flex;flex-direction:column;gap:var(--space-1);width:100%}.ea-slider--sm .ea-slider .ea-slider__track{height:.25rem}.ea-slider--sm .ea-slider .ea-slider__thumb{width:.875rem;height:.875rem}.ea-slider--md .ea-slider .ea-slider__track{height:.375rem}.ea-slider--md .ea-slider .ea-slider__thumb{width:1.125rem;height:1.125rem}.ea-slider--lg .ea-slider .ea-slider__track{height:.5rem}.ea-slider--lg .ea-slider .ea-slider__thumb{width:1.375rem;height:1.375rem}.ea-slider__track{position:relative;width:100%;background-color:var(--color-bg-muted);border-radius:var(--radius-full);cursor:pointer;touch-action:none}.ea-slider__fill{position:absolute;top:0;left:0;height:100%;background-color:var(--color-brand-default);border-radius:inherit;transition:var(--transition-colors)}.ea-slider__thumb{position:absolute;top:50%;background-color:var(--color-neutral-0);border:var(--border-width-medium) solid var(--color-brand-default);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);cursor:grab;transform:translate(-50%,-50%);transition:box-shadow var(--duration-fast) var(--ease-out),transform var(--duration-fast) var(--ease-out)}.ea-slider__thumb:focus-visible{box-shadow:var(--shadow-focus-ring);outline:none}.ea-slider__minmax{display:flex;justify-content:space-between;margin-top:var(--space-1)}.ea-slider__minmax-label{font-size:var(--font-size-xs);color:var(--color-text-tertiary);font-variant-numeric:tabular-nums}.ea-slider--dragging .ea-slider__thumb{cursor:grabbing;transform:translate(-50%,-50%) scale(1.1)}.ea-slider--disabled{opacity:.5;cursor:not-allowed}.ea-slider--disabled .ea-slider__track,.ea-slider--disabled .ea-slider__thumb{cursor:not-allowed}.ea-slider--error .ea-slider__fill{background-color:var(--color-error-default)}.ea-slider--error .ea-slider__thumb{border-color:var(--color-error-default)}.ea-slider--error .ea-slider__thumb:focus-visible{box-shadow:var(--shadow-focus-ring-error)}\n"] }]
6035
+ }], propDecorators: { trackEl: [{ type: i0.ViewChild, args: ['trackEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], showMinMaxLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMinMaxLabels", required: false }] }], formatValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatValue", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
6036
+
6037
+ /**
6038
+ * SVG loading indicator with an accessible `role="status"`. Uses the `label`
6039
+ * input as the accessible name announced to assistive technology.
6040
+ */
5258
6041
  class SpinnerComponent {
5259
6042
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5260
6043
  label = input('Loading', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
@@ -5262,28 +6045,42 @@ class SpinnerComponent {
5262
6045
  [`ea-spinner--${this.size()}`]: true,
5263
6046
  }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
5264
6047
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5265
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: SpinnerComponent, isStandalone: true, selector: "ea-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-spinner\"\n [ngClass]=\"hostClasses()\"\n role=\"status\">\n <svg\n class=\"ea-spinner__circle\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden=\"true\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n opacity=\"0.25\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\" />\n </svg>\n <span class=\"ea-spinner__label\">{{ label() }}</span>\n</div>\n", styles: [".ea-spinner{display:inline-flex;align-items:center;gap:var(--space-2);color:var(--color-brand-default)}.ea-spinner--sm .ea-spinner__circle{width:1rem;height:1rem}.ea-spinner--sm .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--md .ea-spinner__circle{width:1.5rem;height:1.5rem}.ea-spinner--md .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--lg .ea-spinner__circle{width:2rem;height:2rem}.ea-spinner--lg .ea-spinner__label{font-size:var(--font-size-md)}.ea-spinner__circle{animation:ea-spin .75s linear infinite}.ea-spinner__label{font-family:var(--font-family-sans);color:var(--color-text-secondary);line-height:var(--line-height-normal)}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6048
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: SpinnerComponent, isStandalone: true, selector: "ea-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"ea-spinner\"\n [ngClass]=\"hostClasses()\"\n role=\"status\">\n <svg\n class=\"ea-spinner__circle\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden=\"true\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n opacity=\"0.25\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\" />\n </svg>\n <span class=\"ea-spinner__label\">{{ label() }}</span>\n</div>\n", styles: [".ea-spinner{display:inline-flex;align-items:center;gap:var(--space-2);color:var(--color-brand-default)}.ea-spinner--sm .ea-spinner__circle{width:1rem;height:1rem}.ea-spinner--sm .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--md .ea-spinner__circle{width:1.5rem;height:1.5rem}.ea-spinner--md .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--lg .ea-spinner__circle{width:2rem;height:2rem}.ea-spinner--lg .ea-spinner__label{font-size:var(--font-size-md)}.ea-spinner__circle{animation:ea-spin .75s linear infinite}@media(prefers-reduced-motion:reduce){.ea-spinner__circle{animation-duration:2.5s}}.ea-spinner__label{font-family:var(--font-family-sans);color:var(--color-text-secondary);line-height:var(--line-height-normal)}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5266
6049
  }
5267
6050
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SpinnerComponent, decorators: [{
5268
6051
  type: Component,
5269
- args: [{ selector: 'ea-spinner', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-spinner\"\n [ngClass]=\"hostClasses()\"\n role=\"status\">\n <svg\n class=\"ea-spinner__circle\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden=\"true\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n opacity=\"0.25\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\" />\n </svg>\n <span class=\"ea-spinner__label\">{{ label() }}</span>\n</div>\n", styles: [".ea-spinner{display:inline-flex;align-items:center;gap:var(--space-2);color:var(--color-brand-default)}.ea-spinner--sm .ea-spinner__circle{width:1rem;height:1rem}.ea-spinner--sm .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--md .ea-spinner__circle{width:1.5rem;height:1.5rem}.ea-spinner--md .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--lg .ea-spinner__circle{width:2rem;height:2rem}.ea-spinner--lg .ea-spinner__label{font-size:var(--font-size-md)}.ea-spinner__circle{animation:ea-spin .75s linear infinite}.ea-spinner__label{font-family:var(--font-family-sans);color:var(--color-text-secondary);line-height:var(--line-height-normal)}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
6052
+ args: [{ selector: 'ea-spinner', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"ea-spinner\"\n [ngClass]=\"hostClasses()\"\n role=\"status\">\n <svg\n class=\"ea-spinner__circle\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n aria-hidden=\"true\">\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n opacity=\"0.25\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\" />\n </svg>\n <span class=\"ea-spinner__label\">{{ label() }}</span>\n</div>\n", styles: [".ea-spinner{display:inline-flex;align-items:center;gap:var(--space-2);color:var(--color-brand-default)}.ea-spinner--sm .ea-spinner__circle{width:1rem;height:1rem}.ea-spinner--sm .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--md .ea-spinner__circle{width:1.5rem;height:1.5rem}.ea-spinner--md .ea-spinner__label{font-size:var(--font-size-sm)}.ea-spinner--lg .ea-spinner__circle{width:2rem;height:2rem}.ea-spinner--lg .ea-spinner__label{font-size:var(--font-size-md)}.ea-spinner__circle{animation:ea-spin .75s linear infinite}@media(prefers-reduced-motion:reduce){.ea-spinner__circle{animation-duration:2.5s}}.ea-spinner__label{font-family:var(--font-family-sans);color:var(--color-text-secondary);line-height:var(--line-height-normal)}@keyframes ea-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
5270
6053
  }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
5271
6054
 
6055
+ /**
6056
+ * On/off toggle styled as a sliding switch. Backed by a visually hidden
6057
+ * native checkbox and integrates with Angular forms via
6058
+ * `ControlValueAccessor`.
6059
+ */
5272
6060
  class SwitchComponent {
5273
6061
  label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
6062
+ hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
6063
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
5274
6064
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5275
6065
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
6066
+ required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
6067
+ ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
5276
6068
  id = input(`ea-switch-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
5277
6069
  checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
6070
+ /** Fires with the new checked state whenever the user toggles the switch. */
5278
6071
  changed = output();
5279
6072
  _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
5280
6073
  onChange = () => { };
5281
6074
  onTouched = () => { };
5282
6075
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
6076
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
6077
+ showError = this.hasError;
6078
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
5283
6079
  hostClasses = computed(() => ({
5284
6080
  [`ea-switch--${this.size()}`]: true,
5285
6081
  'ea-switch--checked': this.checked(),
5286
6082
  'ea-switch--disabled': this.isDisabled(),
6083
+ 'ea-switch--error': this.hasError(),
5287
6084
  }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
5288
6085
  writeValue(val) {
5289
6086
  this.checked.set(!!val);
@@ -5307,13 +6104,13 @@ class SwitchComponent {
5307
6104
  this.changed.emit(newValue);
5308
6105
  }
5309
6106
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SwitchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5310
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SwitchComponent, isStandalone: true, selector: "ea-switch", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", changed: "changed" }, providers: [
6107
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SwitchComponent, isStandalone: true, selector: "ea-switch", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", changed: "changed" }, providers: [
5311
6108
  {
5312
6109
  provide: NG_VALUE_ACCESSOR,
5313
6110
  useExisting: forwardRef(() => SwitchComponent),
5314
6111
  multi: true,
5315
6112
  },
5316
- ], ngImport: i0, template: "<label\n class=\"ea-switch\"\n [ngClass]=\"hostClasses()\">\n <input\n class=\"ea-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-checked]=\"checked()\"\n (change)=\"handleChange()\" />\n <span class=\"ea-switch__track\">\n <span class=\"ea-switch__thumb\"></span>\n </span>\n @if (label()) {\n <span class=\"ea-switch__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".ea-switch{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans)}.ea-switch--sm .ea-switch__track{width:1.75rem;height:1rem}.ea-switch--sm .ea-switch__thumb{width:.75rem;height:.75rem}.ea-switch--sm .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--md .ea-switch__track{width:2.25rem;height:1.25rem}.ea-switch--md .ea-switch__thumb{width:1rem;height:1rem}.ea-switch--md .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--lg .ea-switch__track{width:2.75rem;height:1.5rem}.ea-switch--lg .ea-switch__thumb{width:1.25rem;height:1.25rem}.ea-switch--lg .ea-switch__label{font-size:var(--font-size-md)}.ea-switch--checked .ea-switch__track{background-color:var(--color-brand-default);border-color:var(--color-brand-default)}.ea-switch--checked .ea-switch__thumb{transform:translate(100%)}.ea-switch--disabled{opacity:.45;cursor:not-allowed}.ea-switch:hover:not(.ea-switch--disabled) .ea-switch__track{border-color:var(--color-brand-default)}.ea-switch__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-switch__input:focus-visible+.ea-switch__track{box-shadow:var(--shadow-focus-ring)}.ea-switch__track{position:relative;display:flex;align-items:center;flex-shrink:0;padding:.125rem;background-color:var(--color-bg-muted);border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-full);transition:var(--transition-colors)}.ea-switch__thumb{display:block;background-color:var(--color-neutral-0);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);transition:transform var(--duration-fast) var(--ease-out)}.ea-switch__label{font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6113
+ ], ngImport: i0, template: "<div class=\"ea-switch-field\">\n <label\n class=\"ea-switch\"\n [ngClass]=\"hostClasses()\">\n <input\n class=\"ea-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (change)=\"handleChange()\" />\n <span class=\"ea-switch__track\">\n <span class=\"ea-switch__thumb\"></span>\n </span>\n @if (label()) {\n <span\n class=\"ea-switch__label\"\n [class.ea-switch__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n </label>\n\n @if (showError()) {\n <p\n class=\"ea-switch-field__message ea-switch-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-switch-field__message ea-switch-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-switch-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-switch-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-switch-field__message--hint{color:var(--color-text-secondary)}.ea-switch-field__message--error{color:var(--color-error-default)}.ea-switch{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans)}.ea-switch--sm .ea-switch__track{width:1.75rem;height:1rem}.ea-switch--sm .ea-switch__thumb{width:.75rem;height:.75rem}.ea-switch--sm .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--md .ea-switch__track{width:2.25rem;height:1.25rem}.ea-switch--md .ea-switch__thumb{width:1rem;height:1rem}.ea-switch--md .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--lg .ea-switch__track{width:2.75rem;height:1.5rem}.ea-switch--lg .ea-switch__thumb{width:1.25rem;height:1.25rem}.ea-switch--lg .ea-switch__label{font-size:var(--font-size-md)}.ea-switch--checked .ea-switch__track{background-color:var(--color-brand-default);border-color:var(--color-brand-default)}.ea-switch--checked .ea-switch__thumb{transform:translate(100%)}.ea-switch--disabled{opacity:.45;cursor:not-allowed}.ea-switch:hover:not(.ea-switch--disabled) .ea-switch__track{border-color:var(--color-brand-default)}.ea-switch__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-switch__input:focus-visible+.ea-switch__track{box-shadow:var(--shadow-focus-ring)}.ea-switch__track{position:relative;display:flex;align-items:center;flex-shrink:0;padding:.125rem;background-color:var(--color-bg-muted);border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-full);transition:var(--transition-colors)}.ea-switch__thumb{display:block;background-color:var(--color-neutral-0);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);transition:transform var(--duration-fast) var(--ease-out)}.ea-switch__label{font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary)}.ea-switch__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-switch--error .ea-switch__track{border-color:var(--color-error-default)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5317
6114
  }
5318
6115
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SwitchComponent, decorators: [{
5319
6116
  type: Component,
@@ -5323,24 +6120,34 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
5323
6120
  useExisting: forwardRef(() => SwitchComponent),
5324
6121
  multi: true,
5325
6122
  },
5326
- ], template: "<label\n class=\"ea-switch\"\n [ngClass]=\"hostClasses()\">\n <input\n class=\"ea-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-checked]=\"checked()\"\n (change)=\"handleChange()\" />\n <span class=\"ea-switch__track\">\n <span class=\"ea-switch__thumb\"></span>\n </span>\n @if (label()) {\n <span class=\"ea-switch__label\">{{ label() }}</span>\n }\n</label>\n", styles: [".ea-switch{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans)}.ea-switch--sm .ea-switch__track{width:1.75rem;height:1rem}.ea-switch--sm .ea-switch__thumb{width:.75rem;height:.75rem}.ea-switch--sm .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--md .ea-switch__track{width:2.25rem;height:1.25rem}.ea-switch--md .ea-switch__thumb{width:1rem;height:1rem}.ea-switch--md .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--lg .ea-switch__track{width:2.75rem;height:1.5rem}.ea-switch--lg .ea-switch__thumb{width:1.25rem;height:1.25rem}.ea-switch--lg .ea-switch__label{font-size:var(--font-size-md)}.ea-switch--checked .ea-switch__track{background-color:var(--color-brand-default);border-color:var(--color-brand-default)}.ea-switch--checked .ea-switch__thumb{transform:translate(100%)}.ea-switch--disabled{opacity:.45;cursor:not-allowed}.ea-switch:hover:not(.ea-switch--disabled) .ea-switch__track{border-color:var(--color-brand-default)}.ea-switch__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-switch__input:focus-visible+.ea-switch__track{box-shadow:var(--shadow-focus-ring)}.ea-switch__track{position:relative;display:flex;align-items:center;flex-shrink:0;padding:.125rem;background-color:var(--color-bg-muted);border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-full);transition:var(--transition-colors)}.ea-switch__thumb{display:block;background-color:var(--color-neutral-0);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);transition:transform var(--duration-fast) var(--ease-out)}.ea-switch__label{font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary)}\n"] }]
5327
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
6123
+ ], template: "<div class=\"ea-switch-field\">\n <label\n class=\"ea-switch\"\n [ngClass]=\"hostClasses()\">\n <input\n class=\"ea-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [required]=\"required()\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"!label() ? (ariaLabel() ?? null) : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (change)=\"handleChange()\" />\n <span class=\"ea-switch__track\">\n <span class=\"ea-switch__thumb\"></span>\n </span>\n @if (label()) {\n <span\n class=\"ea-switch__label\"\n [class.ea-switch__label--required]=\"required()\">\n {{ label() }}\n </span>\n }\n </label>\n\n @if (showError()) {\n <p\n class=\"ea-switch-field__message ea-switch-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-switch-field__message ea-switch-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-switch-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-switch-field__message{font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-switch-field__message--hint{color:var(--color-text-secondary)}.ea-switch-field__message--error{color:var(--color-error-default)}.ea-switch{display:inline-flex;align-items:center;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans)}.ea-switch--sm .ea-switch__track{width:1.75rem;height:1rem}.ea-switch--sm .ea-switch__thumb{width:.75rem;height:.75rem}.ea-switch--sm .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--md .ea-switch__track{width:2.25rem;height:1.25rem}.ea-switch--md .ea-switch__thumb{width:1rem;height:1rem}.ea-switch--md .ea-switch__label{font-size:var(--font-size-sm)}.ea-switch--lg .ea-switch__track{width:2.75rem;height:1.5rem}.ea-switch--lg .ea-switch__thumb{width:1.25rem;height:1.25rem}.ea-switch--lg .ea-switch__label{font-size:var(--font-size-md)}.ea-switch--checked .ea-switch__track{background-color:var(--color-brand-default);border-color:var(--color-brand-default)}.ea-switch--checked .ea-switch__thumb{transform:translate(100%)}.ea-switch--disabled{opacity:.45;cursor:not-allowed}.ea-switch:hover:not(.ea-switch--disabled) .ea-switch__track{border-color:var(--color-brand-default)}.ea-switch__input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.ea-switch__input:focus-visible+.ea-switch__track{box-shadow:var(--shadow-focus-ring)}.ea-switch__track{position:relative;display:flex;align-items:center;flex-shrink:0;padding:.125rem;background-color:var(--color-bg-muted);border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-full);transition:var(--transition-colors)}.ea-switch__thumb{display:block;background-color:var(--color-neutral-0);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);transition:transform var(--duration-fast) var(--ease-out)}.ea-switch__label{font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary)}.ea-switch__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-switch--error .ea-switch__track{border-color:var(--color-error-default)}\n"] }]
6124
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5328
6125
 
6126
+ /**
6127
+ * Tab bar paired with content panels. Child `ea-tab` components register
6128
+ * themselves automatically and the active panel is shown based on the
6129
+ * `activeTab` two-way binding. Supports keyboard navigation
6130
+ * (arrow keys, Home/End).
6131
+ */
5329
6132
  class TabsComponent {
5330
6133
  registeredTabs = signal([], ...(ngDevMode ? [{ debugName: "registeredTabs" }] : /* istanbul ignore next */ []));
5331
6134
  variant = input('underline', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
5332
6135
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5333
6136
  activeTab = model('', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
5334
- tabChange = output();
6137
+ /** Fires with the value of the newly active tab. */
6138
+ changed = output();
6139
+ /** Registers a child tab so it appears in the tab bar; called automatically by `ea-tab`. */
5335
6140
  registerTab(tab) {
5336
6141
  this.registeredTabs.update(tabs => [...tabs, tab]);
5337
6142
  }
6143
+ /** Removes a previously registered child tab; called automatically by `ea-tab`. */
5338
6144
  unregisterTab(tab) {
5339
6145
  this.registeredTabs.update(tabs => tabs.filter(t => t !== tab));
5340
6146
  }
6147
+ /** Programmatically activates the tab with the given value. */
5341
6148
  selectTab(value) {
5342
6149
  this.activeTab.set(value);
5343
- this.tabChange.emit(value);
6150
+ this.changed.emit(value);
5344
6151
  }
5345
6152
  handleKeydown(event) {
5346
6153
  const tabList = this.registeredTabs().filter(t => !t.disabled());
@@ -5370,18 +6177,24 @@ class TabsComponent {
5370
6177
  }
5371
6178
  }
5372
6179
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5373
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TabsComponent, isStandalone: true, selector: "ea-tabs", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeTab: "activeTabChange", tabChange: "tabChange" }, ngImport: i0, template: "<div class=\"ea-tabs\">\n <div\n class=\"ea-tabs__list\"\n [class.ea-tabs__list--underline]=\"variant() === 'underline'\"\n [class.ea-tabs__list--filled]=\"variant() === 'filled'\"\n [class.ea-tabs__list--sm]=\"size() === 'sm'\"\n [class.ea-tabs__list--md]=\"size() === 'md'\"\n [class.ea-tabs__list--lg]=\"size() === 'lg'\"\n role=\"tablist\"\n (keydown)=\"handleKeydown($event)\">\n @for (tab of registeredTabs(); track tab.value()) {\n <button\n class=\"ea-tabs__trigger\"\n [class.ea-tabs__trigger--active]=\"tab.isActive()\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"tab.isActive()\"\n [disabled]=\"tab.disabled()\"\n [tabindex]=\"tab.isActive() ? 0 : -1\"\n (click)=\"selectTab(tab.value())\">\n {{ tab.label() }}\n </button>\n }\n </div>\n <ng-content />\n</div>\n", styles: [".ea-tabs{display:flex;flex-direction:column;gap:var(--space-4)}.ea-tabs__list{display:flex;gap:var(--space-1)}.ea-tabs__list--underline{border-bottom:var(--border-width-thin) solid var(--color-border-default);gap:0}.ea-tabs__list--underline .ea-tabs__trigger{border-radius:0;border-bottom:var(--border-width-medium) solid transparent;margin-bottom:calc(-1 * var(--border-width-thin))}.ea-tabs__list--underline .ea-tabs__trigger--active{border-bottom-color:var(--color-primary-600);color:var(--color-primary-600)}.ea-tabs__list--underline .ea-tabs__trigger:hover:not(:disabled):not(.ea-tabs__trigger--active){border-bottom-color:var(--color-border-strong)}.ea-tabs__list--filled{background-color:var(--color-bg-muted);border-radius:var(--radius-lg);padding:var(--space-1)}.ea-tabs__list--filled .ea-tabs__trigger{border-radius:var(--radius-md)}.ea-tabs__list--filled .ea-tabs__trigger--active{background-color:var(--color-bg-base);box-shadow:var(--shadow-sm);color:var(--color-text-primary)}.ea-tabs__list--sm .ea-tabs__trigger{padding:var(--space-1-5) var(--space-3);font-size:var(--font-size-xs)}.ea-tabs__list--md .ea-tabs__trigger{padding:var(--space-2) var(--space-4);font-size:var(--font-size-sm)}.ea-tabs__list--lg .ea-tabs__trigger{padding:var(--space-2-5) var(--space-5);font-size:var(--font-size-md)}.ea-tabs__trigger{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);white-space:nowrap;background:none;border:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-tabs__trigger:hover:not(:disabled){color:var(--color-text-primary)}.ea-tabs__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tabs__trigger:disabled{opacity:.5;cursor:not-allowed}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6180
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TabsComponent, isStandalone: true, selector: "ea-tabs", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeTab: "activeTabChange", changed: "changed" }, ngImport: i0, template: "<div class=\"ea-tabs\">\n <div\n class=\"ea-tabs__list\"\n [class.ea-tabs__list--underline]=\"variant() === 'underline'\"\n [class.ea-tabs__list--filled]=\"variant() === 'filled'\"\n [class.ea-tabs__list--sm]=\"size() === 'sm'\"\n [class.ea-tabs__list--md]=\"size() === 'md'\"\n [class.ea-tabs__list--lg]=\"size() === 'lg'\"\n role=\"tablist\"\n (keydown)=\"handleKeydown($event)\">\n @for (tab of registeredTabs(); track tab.value()) {\n <button\n class=\"ea-tabs__trigger\"\n [class.ea-tabs__trigger--active]=\"tab.isActive()\"\n type=\"button\"\n role=\"tab\"\n [id]=\"tab.id() + '-tab'\"\n [attr.aria-selected]=\"tab.isActive()\"\n [attr.aria-controls]=\"tab.id() + '-panel'\"\n [disabled]=\"tab.disabled()\"\n [tabindex]=\"tab.isActive() ? 0 : -1\"\n (click)=\"selectTab(tab.value())\">\n {{ tab.label() }}\n </button>\n }\n </div>\n <ng-content />\n</div>\n", styles: [".ea-tabs{display:flex;flex-direction:column;gap:var(--space-4)}.ea-tabs__list{display:flex;gap:var(--space-1)}.ea-tabs__list--underline{border-bottom:var(--border-width-thin) solid var(--color-border-default);gap:0}.ea-tabs__list--underline .ea-tabs__trigger{border-radius:0;border-bottom:var(--border-width-medium) solid transparent;margin-bottom:calc(-1 * var(--border-width-thin))}.ea-tabs__list--underline .ea-tabs__trigger--active{border-bottom-color:var(--color-primary-600);color:var(--color-primary-600)}.ea-tabs__list--underline .ea-tabs__trigger:hover:not(:disabled):not(.ea-tabs__trigger--active){border-bottom-color:var(--color-border-strong)}.ea-tabs__list--filled{background-color:var(--color-bg-muted);border-radius:var(--radius-lg);padding:var(--space-1)}.ea-tabs__list--filled .ea-tabs__trigger{border-radius:var(--radius-md)}.ea-tabs__list--filled .ea-tabs__trigger--active{background-color:var(--color-bg-base);box-shadow:var(--shadow-sm);color:var(--color-text-primary)}.ea-tabs__list--sm .ea-tabs__trigger{padding:var(--space-1-5) var(--space-3);font-size:var(--font-size-xs)}.ea-tabs__list--md .ea-tabs__trigger{padding:var(--space-2) var(--space-4);font-size:var(--font-size-sm)}.ea-tabs__list--lg .ea-tabs__trigger{padding:var(--space-2-5) var(--space-5);font-size:var(--font-size-md)}.ea-tabs__trigger{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);white-space:nowrap;background:none;border:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-tabs__trigger:hover:not(:disabled){color:var(--color-text-primary)}.ea-tabs__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tabs__trigger:disabled{opacity:.5;cursor:not-allowed}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5374
6181
  }
5375
6182
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TabsComponent, decorators: [{
5376
6183
  type: Component,
5377
- args: [{ selector: 'ea-tabs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ea-tabs\">\n <div\n class=\"ea-tabs__list\"\n [class.ea-tabs__list--underline]=\"variant() === 'underline'\"\n [class.ea-tabs__list--filled]=\"variant() === 'filled'\"\n [class.ea-tabs__list--sm]=\"size() === 'sm'\"\n [class.ea-tabs__list--md]=\"size() === 'md'\"\n [class.ea-tabs__list--lg]=\"size() === 'lg'\"\n role=\"tablist\"\n (keydown)=\"handleKeydown($event)\">\n @for (tab of registeredTabs(); track tab.value()) {\n <button\n class=\"ea-tabs__trigger\"\n [class.ea-tabs__trigger--active]=\"tab.isActive()\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"tab.isActive()\"\n [disabled]=\"tab.disabled()\"\n [tabindex]=\"tab.isActive() ? 0 : -1\"\n (click)=\"selectTab(tab.value())\">\n {{ tab.label() }}\n </button>\n }\n </div>\n <ng-content />\n</div>\n", styles: [".ea-tabs{display:flex;flex-direction:column;gap:var(--space-4)}.ea-tabs__list{display:flex;gap:var(--space-1)}.ea-tabs__list--underline{border-bottom:var(--border-width-thin) solid var(--color-border-default);gap:0}.ea-tabs__list--underline .ea-tabs__trigger{border-radius:0;border-bottom:var(--border-width-medium) solid transparent;margin-bottom:calc(-1 * var(--border-width-thin))}.ea-tabs__list--underline .ea-tabs__trigger--active{border-bottom-color:var(--color-primary-600);color:var(--color-primary-600)}.ea-tabs__list--underline .ea-tabs__trigger:hover:not(:disabled):not(.ea-tabs__trigger--active){border-bottom-color:var(--color-border-strong)}.ea-tabs__list--filled{background-color:var(--color-bg-muted);border-radius:var(--radius-lg);padding:var(--space-1)}.ea-tabs__list--filled .ea-tabs__trigger{border-radius:var(--radius-md)}.ea-tabs__list--filled .ea-tabs__trigger--active{background-color:var(--color-bg-base);box-shadow:var(--shadow-sm);color:var(--color-text-primary)}.ea-tabs__list--sm .ea-tabs__trigger{padding:var(--space-1-5) var(--space-3);font-size:var(--font-size-xs)}.ea-tabs__list--md .ea-tabs__trigger{padding:var(--space-2) var(--space-4);font-size:var(--font-size-sm)}.ea-tabs__list--lg .ea-tabs__trigger{padding:var(--space-2-5) var(--space-5);font-size:var(--font-size-md)}.ea-tabs__trigger{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);white-space:nowrap;background:none;border:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-tabs__trigger:hover:not(:disabled){color:var(--color-text-primary)}.ea-tabs__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tabs__trigger:disabled{opacity:.5;cursor:not-allowed}\n"] }]
5378
- }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }] } });
6184
+ args: [{ selector: 'ea-tabs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ea-tabs\">\n <div\n class=\"ea-tabs__list\"\n [class.ea-tabs__list--underline]=\"variant() === 'underline'\"\n [class.ea-tabs__list--filled]=\"variant() === 'filled'\"\n [class.ea-tabs__list--sm]=\"size() === 'sm'\"\n [class.ea-tabs__list--md]=\"size() === 'md'\"\n [class.ea-tabs__list--lg]=\"size() === 'lg'\"\n role=\"tablist\"\n (keydown)=\"handleKeydown($event)\">\n @for (tab of registeredTabs(); track tab.value()) {\n <button\n class=\"ea-tabs__trigger\"\n [class.ea-tabs__trigger--active]=\"tab.isActive()\"\n type=\"button\"\n role=\"tab\"\n [id]=\"tab.id() + '-tab'\"\n [attr.aria-selected]=\"tab.isActive()\"\n [attr.aria-controls]=\"tab.id() + '-panel'\"\n [disabled]=\"tab.disabled()\"\n [tabindex]=\"tab.isActive() ? 0 : -1\"\n (click)=\"selectTab(tab.value())\">\n {{ tab.label() }}\n </button>\n }\n </div>\n <ng-content />\n</div>\n", styles: [".ea-tabs{display:flex;flex-direction:column;gap:var(--space-4)}.ea-tabs__list{display:flex;gap:var(--space-1)}.ea-tabs__list--underline{border-bottom:var(--border-width-thin) solid var(--color-border-default);gap:0}.ea-tabs__list--underline .ea-tabs__trigger{border-radius:0;border-bottom:var(--border-width-medium) solid transparent;margin-bottom:calc(-1 * var(--border-width-thin))}.ea-tabs__list--underline .ea-tabs__trigger--active{border-bottom-color:var(--color-primary-600);color:var(--color-primary-600)}.ea-tabs__list--underline .ea-tabs__trigger:hover:not(:disabled):not(.ea-tabs__trigger--active){border-bottom-color:var(--color-border-strong)}.ea-tabs__list--filled{background-color:var(--color-bg-muted);border-radius:var(--radius-lg);padding:var(--space-1)}.ea-tabs__list--filled .ea-tabs__trigger{border-radius:var(--radius-md)}.ea-tabs__list--filled .ea-tabs__trigger--active{background-color:var(--color-bg-base);box-shadow:var(--shadow-sm);color:var(--color-text-primary)}.ea-tabs__list--sm .ea-tabs__trigger{padding:var(--space-1-5) var(--space-3);font-size:var(--font-size-xs)}.ea-tabs__list--md .ea-tabs__trigger{padding:var(--space-2) var(--space-4);font-size:var(--font-size-sm)}.ea-tabs__list--lg .ea-tabs__trigger{padding:var(--space-2-5) var(--space-5);font-size:var(--font-size-md)}.ea-tabs__trigger{display:flex;align-items:center;justify-content:center;padding:0;font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);line-height:var(--line-height-normal);white-space:nowrap;background:none;border:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-tabs__trigger:hover:not(:disabled){color:var(--color-text-primary)}.ea-tabs__trigger:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tabs__trigger:disabled{opacity:.5;cursor:not-allowed}\n"] }]
6185
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5379
6186
 
6187
+ /**
6188
+ * Single tab within an `ea-tabs` group. Registers itself with the parent on
6189
+ * init, exposes its `value` and `label`, and shows its projected content
6190
+ * when active.
6191
+ */
5380
6192
  class TabComponent {
5381
6193
  tabs = inject(TabsComponent);
5382
6194
  value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5383
6195
  label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5384
6196
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
6197
+ id = input(`ea-tab-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
5385
6198
  isActive = computed(() => this.tabs.activeTab() === this.value(), ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
5386
6199
  ngOnInit() {
5387
6200
  this.tabs.registerTab(this);
@@ -5390,11 +6203,14 @@ class TabComponent {
5390
6203
  this.tabs.unregisterTab(this);
5391
6204
  }
5392
6205
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5393
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TabComponent, isStandalone: true, selector: "ea-tab", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "isActive() ? null : \"none\"" } }, ngImport: i0, template: `
6206
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TabComponent, isStandalone: true, selector: "ea-tab", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "isActive() ? null : \"none\"" } }, ngImport: i0, template: `
5394
6207
  @if (isActive()) {
5395
6208
  <div
5396
6209
  class="ea-tab__panel"
5397
- role="tabpanel">
6210
+ role="tabpanel"
6211
+ [id]="id() + '-panel'"
6212
+ [attr.aria-labelledby]="id() + '-tab'"
6213
+ tabindex="0">
5398
6214
  <ng-content />
5399
6215
  </div>
5400
6216
  }
@@ -5409,20 +6225,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
5409
6225
  @if (isActive()) {
5410
6226
  <div
5411
6227
  class="ea-tab__panel"
5412
- role="tabpanel">
6228
+ role="tabpanel"
6229
+ [id]="id() + '-panel'"
6230
+ [attr.aria-labelledby]="id() + '-tab'"
6231
+ tabindex="0">
5413
6232
  <ng-content />
5414
6233
  </div>
5415
6234
  }
5416
6235
  `,
5417
6236
  changeDetection: ChangeDetectionStrategy.OnPush,
5418
6237
  }]
5419
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
6238
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
5420
6239
 
6240
+ /**
6241
+ * Inline label commonly used to represent filters, categories, or selected
6242
+ * items. When `removable`, renders a close button that emits `removed`; the
6243
+ * accessible name of that button is configurable via `removeLabel`.
6244
+ */
5421
6245
  class TagComponent {
5422
6246
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
5423
6247
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5424
6248
  removable = input(false, ...(ngDevMode ? [{ debugName: "removable" }] : /* istanbul ignore next */ []));
5425
6249
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
6250
+ removeLabel = input('Remove', ...(ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []));
6251
+ /** Fires when the user activates the remove button on a `removable` tag. */
5426
6252
  removed = output();
5427
6253
  hostClasses = computed(() => ({
5428
6254
  [`ea-tag--${this.variant()}`]: true,
@@ -5434,21 +6260,25 @@ class TagComponent {
5434
6260
  this.removed.emit();
5435
6261
  }
5436
6262
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5437
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TagComponent, isStandalone: true, selector: "ea-tag", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, ngImport: i0, template: "<span\n class=\"ea-tag\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n @if (removable()) {\n <button\n type=\"button\"\n class=\"ea-tag__remove\"\n [disabled]=\"disabled() || null\"\n (click)=\"onRemove($event)\"\n aria-label=\"Remove\">\n <ea-icon-x />\n </button>\n }\n</span>\n", styles: [".ea-tag{display:inline-flex;align-items:center;gap:var(--space-1);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);white-space:nowrap;font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-secondary)}.ea-tag--sm{padding:var(--space-0-5) var(--space-1-5);font-size:var(--font-size-xs)}.ea-tag--sm .ea-tag__remove ea-icon-x{width:.625rem;height:.625rem}.ea-tag--md{padding:var(--space-1) var(--space-2);font-size:var(--font-size-xs)}.ea-tag--md .ea-tag__remove ea-icon-x{width:.75rem;height:.75rem}.ea-tag--lg{padding:var(--space-1) var(--space-2-5);font-size:var(--font-size-sm)}.ea-tag--lg .ea-tag__remove ea-icon-x{width:.875rem;height:.875rem}.ea-tag--primary{border-color:var(--color-brand-muted);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-tag--success{border-color:var(--color-success-muted);background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-tag--warning{border-color:var(--color-warning-muted);background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-tag--error{border-color:var(--color-error-muted);background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-tag--info{border-color:var(--color-info-muted);background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-tag--disabled{opacity:.6;cursor:not-allowed}.ea-tag__remove{opacity:.7;display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;border-radius:var(--radius-xs);background:none;color:inherit;cursor:pointer;transition:var(--transition-colors)}.ea-tag__remove:hover{opacity:1}.ea-tag__remove:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tag__remove:disabled{cursor:not-allowed}.ea-tag__remove ea-icon-x{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6263
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TagComponent, isStandalone: true, selector: "ea-tag", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, ngImport: i0, template: "<span\n class=\"ea-tag\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n @if (removable()) {\n <button\n type=\"button\"\n class=\"ea-tag__remove\"\n [disabled]=\"disabled() || null\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"onRemove($event)\">\n <ea-icon-x />\n </button>\n }\n</span>\n", styles: [".ea-tag{display:inline-flex;align-items:center;gap:var(--space-1);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);white-space:nowrap;font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-secondary)}.ea-tag--sm{padding:var(--space-0-5) var(--space-1-5);font-size:var(--font-size-xs)}.ea-tag--sm .ea-tag__remove ea-icon-x{width:.625rem;height:.625rem}.ea-tag--md{padding:var(--space-1) var(--space-2);font-size:var(--font-size-xs)}.ea-tag--md .ea-tag__remove ea-icon-x{width:.75rem;height:.75rem}.ea-tag--lg{padding:var(--space-1) var(--space-2-5);font-size:var(--font-size-sm)}.ea-tag--lg .ea-tag__remove ea-icon-x{width:.875rem;height:.875rem}.ea-tag--success{border-color:var(--color-success-muted);background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-tag--warning{border-color:var(--color-warning-muted);background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-tag--error{border-color:var(--color-error-muted);background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-tag--info{border-color:var(--color-info-muted);background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-tag--disabled{opacity:.6;cursor:not-allowed}.ea-tag__remove{opacity:.7;display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;border-radius:var(--radius-xs);background:none;color:inherit;cursor:pointer;transition:var(--transition-colors)}.ea-tag__remove:hover{opacity:1}.ea-tag__remove:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tag__remove:disabled{cursor:not-allowed}.ea-tag__remove ea-icon-x{pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5438
6264
  }
5439
6265
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TagComponent, decorators: [{
5440
6266
  type: Component,
5441
- args: [{ selector: 'ea-tag', imports: [NgClass, XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<span\n class=\"ea-tag\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n @if (removable()) {\n <button\n type=\"button\"\n class=\"ea-tag__remove\"\n [disabled]=\"disabled() || null\"\n (click)=\"onRemove($event)\"\n aria-label=\"Remove\">\n <ea-icon-x />\n </button>\n }\n</span>\n", styles: [".ea-tag{display:inline-flex;align-items:center;gap:var(--space-1);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);white-space:nowrap;font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-secondary)}.ea-tag--sm{padding:var(--space-0-5) var(--space-1-5);font-size:var(--font-size-xs)}.ea-tag--sm .ea-tag__remove ea-icon-x{width:.625rem;height:.625rem}.ea-tag--md{padding:var(--space-1) var(--space-2);font-size:var(--font-size-xs)}.ea-tag--md .ea-tag__remove ea-icon-x{width:.75rem;height:.75rem}.ea-tag--lg{padding:var(--space-1) var(--space-2-5);font-size:var(--font-size-sm)}.ea-tag--lg .ea-tag__remove ea-icon-x{width:.875rem;height:.875rem}.ea-tag--primary{border-color:var(--color-brand-muted);background-color:var(--color-brand-subtle);color:var(--color-brand-default)}.ea-tag--success{border-color:var(--color-success-muted);background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-tag--warning{border-color:var(--color-warning-muted);background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-tag--error{border-color:var(--color-error-muted);background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-tag--info{border-color:var(--color-info-muted);background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-tag--disabled{opacity:.6;cursor:not-allowed}.ea-tag__remove{opacity:.7;display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;border-radius:var(--radius-xs);background:none;color:inherit;cursor:pointer;transition:var(--transition-colors)}.ea-tag__remove:hover{opacity:1}.ea-tag__remove:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tag__remove:disabled{cursor:not-allowed}.ea-tag__remove ea-icon-x{pointer-events:none}\n"] }]
5442
- }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }] } });
6267
+ args: [{ selector: 'ea-tag', imports: [NgClass, XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<span\n class=\"ea-tag\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n @if (removable()) {\n <button\n type=\"button\"\n class=\"ea-tag__remove\"\n [disabled]=\"disabled() || null\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"onRemove($event)\">\n <ea-icon-x />\n </button>\n }\n</span>\n", styles: [".ea-tag{display:inline-flex;align-items:center;gap:var(--space-1);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);white-space:nowrap;font-family:var(--font-family-sans);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);background-color:var(--color-bg-subtle);color:var(--color-text-secondary)}.ea-tag--sm{padding:var(--space-0-5) var(--space-1-5);font-size:var(--font-size-xs)}.ea-tag--sm .ea-tag__remove ea-icon-x{width:.625rem;height:.625rem}.ea-tag--md{padding:var(--space-1) var(--space-2);font-size:var(--font-size-xs)}.ea-tag--md .ea-tag__remove ea-icon-x{width:.75rem;height:.75rem}.ea-tag--lg{padding:var(--space-1) var(--space-2-5);font-size:var(--font-size-sm)}.ea-tag--lg .ea-tag__remove ea-icon-x{width:.875rem;height:.875rem}.ea-tag--success{border-color:var(--color-success-muted);background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-tag--warning{border-color:var(--color-warning-muted);background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-tag--error{border-color:var(--color-error-muted);background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-tag--info{border-color:var(--color-info-muted);background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-tag--disabled{opacity:.6;cursor:not-allowed}.ea-tag__remove{opacity:.7;display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;border:none;border-radius:var(--radius-xs);background:none;color:inherit;cursor:pointer;transition:var(--transition-colors)}.ea-tag__remove:hover{opacity:1}.ea-tag__remove:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-tag__remove:disabled{cursor:not-allowed}.ea-tag__remove ea-icon-x{pointer-events:none}\n"] }]
6268
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }] } });
5443
6269
 
6270
+ /**
6271
+ * Multiline text field that mirrors the `ea-input` API. Supports configurable
6272
+ * `rows`, `resize` direction, and `maxlength`, and integrates with Angular
6273
+ * forms via `ControlValueAccessor`.
6274
+ */
5444
6275
  class TextareaComponent {
5445
6276
  textareaEl = viewChild('textareaEl', ...(ngDevMode ? [{ debugName: "textareaEl" }] : /* istanbul ignore next */ []));
5446
6277
  label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
5447
6278
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
5448
6279
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
5449
- status = input('default', ...(ngDevMode ? [{ debugName: "status" }] : /* istanbul ignore next */ []));
5450
6280
  hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
5451
- errorMsg = input(undefined, { ...(ngDevMode ? { debugName: "errorMsg" } : /* istanbul ignore next */ {}), alias: 'error' });
6281
+ errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
5452
6282
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
5453
6283
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
5454
6284
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
@@ -5457,20 +6287,22 @@ class TextareaComponent {
5457
6287
  maxlength = input(undefined, ...(ngDevMode ? [{ debugName: "maxlength" }] : /* istanbul ignore next */ []));
5458
6288
  id = input(`ea-textarea-${Math.random().toString(36).slice(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
5459
6289
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5460
- focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
6290
+ isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
5461
6291
  _formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
5462
- textareaFocused = output();
5463
- textareaBlurred = output();
6292
+ /** Fires when the textarea receives focus. */
6293
+ focused = output();
6294
+ /** Fires when the textarea loses focus. */
6295
+ blurred = output();
5464
6296
  onChange = () => { };
5465
6297
  onTouched = () => { };
5466
6298
  isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
5467
- resolvedStatus = computed(() => this.errorMsg() ? 'error' : this.status(), ...(ngDevMode ? [{ debugName: "resolvedStatus" }] : /* istanbul ignore next */ []));
5468
- showError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "showError" }] : /* istanbul ignore next */ []));
5469
- showHint = computed(() => !!this.hint() && !this.showError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
6299
+ hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
6300
+ showError = this.hasError;
6301
+ showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
5470
6302
  wrapperClasses = computed(() => ({
5471
6303
  [`ea-textarea-wrapper--${this.size()}`]: true,
5472
- [`ea-textarea-wrapper--${this.resolvedStatus()}`]: true,
5473
- 'ea-textarea-wrapper--focused': this.focused(),
6304
+ 'ea-textarea-wrapper--error': this.hasError(),
6305
+ 'ea-textarea-wrapper--focused': this.isFocused(),
5474
6306
  'ea-textarea-wrapper--disabled': this.isDisabled(),
5475
6307
  'ea-textarea-wrapper--readonly': this.readonly(),
5476
6308
  }), ...(ngDevMode ? [{ debugName: "wrapperClasses" }] : /* istanbul ignore next */ []));
@@ -5492,25 +6324,26 @@ class TextareaComponent {
5492
6324
  this.onChange(value);
5493
6325
  }
5494
6326
  handleFocus(event) {
5495
- this.focused.set(true);
5496
- this.textareaFocused.emit(event);
6327
+ this.isFocused.set(true);
6328
+ this.focused.emit(event);
5497
6329
  }
5498
6330
  handleBlur(event) {
5499
- this.focused.set(false);
6331
+ this.isFocused.set(false);
5500
6332
  this.onTouched();
5501
- this.textareaBlurred.emit(event);
6333
+ this.blurred.emit(event);
5502
6334
  }
6335
+ /** Moves keyboard focus to the underlying native textarea element. */
5503
6336
  focus() {
5504
6337
  this.textareaEl()?.nativeElement.focus();
5505
6338
  }
5506
6339
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5507
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TextareaComponent, isStandalone: true, selector: "ea-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, status: { classPropertyName: "status", publicName: "status", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", textareaFocused: "textareaFocused", textareaBlurred: "textareaBlurred" }, providers: [
6340
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: TextareaComponent, isStandalone: true, selector: "ea-textarea", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, errorMsg: { classPropertyName: "errorMsg", publicName: "errorMsg", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, resize: { classPropertyName: "resize", publicName: "resize", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", focused: "focused", blurred: "blurred" }, providers: [
5508
6341
  {
5509
6342
  provide: NG_VALUE_ACCESSOR,
5510
6343
  useExisting: forwardRef(() => TextareaComponent),
5511
6344
  multi: true,
5512
6345
  },
5513
- ], viewQueries: [{ propertyName: "textareaEl", first: true, predicate: ["textareaEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-textarea-field\">\n @if (label()) {\n <label\n class=\"ea-textarea-field__label\"\n [for]=\"id()\"\n [class.ea-textarea-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-textarea-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <textarea\n #textareaEl\n class=\"ea-textarea\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [rows]=\"rows()\"\n [value]=\"value()\"\n [style.resize]=\"resize()\"\n [attr.maxlength]=\"maxlength() ?? null\"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"></textarea>\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-textarea-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-textarea-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-textarea-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-textarea-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-textarea-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-textarea-field__message--hint{color:inherit}.ea-textarea-field__message--error{color:var(--color-error-default)}.ea-textarea-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-textarea-wrapper{display:flex;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-textarea-wrapper--sm .ea-textarea{padding:var(--space-2);font-size:var(--font-size-sm)}.ea-textarea-wrapper--md .ea-textarea{padding:var(--space-3);font-size:var(--font-size-md)}.ea-textarea-wrapper--lg .ea-textarea{padding:var(--space-4);font-size:var(--font-size-lg)}.ea-textarea-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-textarea-wrapper--error{border-color:var(--color-error-default)}.ea-textarea-wrapper--error.ea-textarea-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-textarea-wrapper--success{border-color:var(--color-success-default)}.ea-textarea-wrapper--success.ea-textarea-wrapper--focused{box-shadow:var(--shadow-focus-ring-success)}.ea-textarea-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-textarea-wrapper--disabled .ea-textarea{cursor:not-allowed}.ea-textarea-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-textarea{flex:1;width:100%;min-width:0;min-height:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-textarea::placeholder{color:var(--color-text-tertiary)}.ea-textarea:disabled{cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6346
+ ], viewQueries: [{ propertyName: "textareaEl", first: true, predicate: ["textareaEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-textarea-field\">\n @if (label()) {\n <label\n class=\"ea-textarea-field__label\"\n [for]=\"id()\"\n [class.ea-textarea-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-textarea-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <textarea\n #textareaEl\n class=\"ea-textarea\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [rows]=\"rows()\"\n [value]=\"value()\"\n [style.resize]=\"resize()\"\n [attr.maxlength]=\"maxlength() ?? null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"></textarea>\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-textarea-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-textarea-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-textarea-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-textarea-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-textarea-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-textarea-field__message--hint{color:inherit}.ea-textarea-field__message--error{color:var(--color-error-default)}.ea-textarea-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-textarea-wrapper{display:flex;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-textarea-wrapper--sm .ea-textarea{padding:var(--space-2);font-size:var(--font-size-sm)}.ea-textarea-wrapper--md .ea-textarea{padding:var(--space-3);font-size:var(--font-size-md)}.ea-textarea-wrapper--lg .ea-textarea{padding:var(--space-4);font-size:var(--font-size-lg)}.ea-textarea-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-textarea-wrapper--error{border-color:var(--color-error-default)}.ea-textarea-wrapper--error.ea-textarea-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-textarea-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-textarea-wrapper--disabled .ea-textarea{cursor:not-allowed}.ea-textarea-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-textarea{flex:1;width:100%;min-width:0;min-height:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-textarea::placeholder{color:var(--color-text-tertiary)}.ea-textarea:disabled{cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AlertCircleIconComponent, selector: "ea-icon-alert-circle" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5514
6347
  }
5515
6348
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TextareaComponent, decorators: [{
5516
6349
  type: Component,
@@ -5520,12 +6353,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
5520
6353
  useExisting: forwardRef(() => TextareaComponent),
5521
6354
  multi: true,
5522
6355
  },
5523
- ], template: "<div class=\"ea-textarea-field\">\n @if (label()) {\n <label\n class=\"ea-textarea-field__label\"\n [for]=\"id()\"\n [class.ea-textarea-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-textarea-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <textarea\n #textareaEl\n class=\"ea-textarea\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [rows]=\"rows()\"\n [value]=\"value()\"\n [style.resize]=\"resize()\"\n [attr.maxlength]=\"maxlength() ?? null\"\n [attr.aria-invalid]=\"resolvedStatus() === 'error' || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"></textarea>\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-textarea-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-textarea-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-textarea-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-textarea-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-textarea-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-textarea-field__message--hint{color:inherit}.ea-textarea-field__message--error{color:var(--color-error-default)}.ea-textarea-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-textarea-wrapper{display:flex;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-textarea-wrapper--sm .ea-textarea{padding:var(--space-2);font-size:var(--font-size-sm)}.ea-textarea-wrapper--md .ea-textarea{padding:var(--space-3);font-size:var(--font-size-md)}.ea-textarea-wrapper--lg .ea-textarea{padding:var(--space-4);font-size:var(--font-size-lg)}.ea-textarea-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-textarea-wrapper--error{border-color:var(--color-error-default)}.ea-textarea-wrapper--error.ea-textarea-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-textarea-wrapper--success{border-color:var(--color-success-default)}.ea-textarea-wrapper--success.ea-textarea-wrapper--focused{box-shadow:var(--shadow-focus-ring-success)}.ea-textarea-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-textarea-wrapper--disabled .ea-textarea{cursor:not-allowed}.ea-textarea-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-textarea{flex:1;width:100%;min-width:0;min-height:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-textarea::placeholder{color:var(--color-text-tertiary)}.ea-textarea:disabled{cursor:not-allowed}\n"] }]
5524
- }], propDecorators: { textareaEl: [{ type: i0.ViewChild, args: ['textareaEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], status: [{ type: i0.Input, args: [{ isSignal: true, alias: "status", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], textareaFocused: [{ type: i0.Output, args: ["textareaFocused"] }], textareaBlurred: [{ type: i0.Output, args: ["textareaBlurred"] }] } });
6356
+ ], template: "<div class=\"ea-textarea-field\">\n @if (label()) {\n <label\n class=\"ea-textarea-field__label\"\n [for]=\"id()\"\n [class.ea-textarea-field__label--required]=\"required()\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ea-textarea-wrapper\"\n [ngClass]=\"wrapperClasses()\">\n <textarea\n #textareaEl\n class=\"ea-textarea\"\n [id]=\"id()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [required]=\"required()\"\n [rows]=\"rows()\"\n [value]=\"value()\"\n [style.resize]=\"resize()\"\n [attr.maxlength]=\"maxlength() ?? null\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"\n showError() ? id() + '-error' : showHint() ? id() + '-hint' : null\n \"\n (input)=\"handleInput($event)\"\n (focus)=\"handleFocus($event)\"\n (blur)=\"handleBlur($event)\"></textarea>\n </div>\n\n @if (showError()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-textarea-field__message-icon\" />\n {{ errorMsg() }}\n </p>\n }\n\n @if (showHint()) {\n <p\n class=\"ea-textarea-field__message ea-textarea-field__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n }\n</div>\n", styles: [".ea-textarea-field{display:flex;flex-direction:column;gap:var(--space-1-5);color:var(--color-text-secondary)}.ea-textarea-field__label{font-size:var(--text-label-md-size);font-weight:var(--text-label-md-weight);line-height:var(--text-label-md-lh);color:var(--color-text-primary)}.ea-textarea-field__label--required:after{content:\" *\";color:var(--color-error-default)}.ea-textarea-field__message{display:flex;align-items:center;gap:var(--space-1);font-size:var(--text-helper-size);font-weight:var(--text-helper-weight);line-height:var(--text-helper-lh)}.ea-textarea-field__message--hint{color:inherit}.ea-textarea-field__message--error{color:var(--color-error-default)}.ea-textarea-field__message-icon{flex-shrink:0;width:.875em;height:.875em}.ea-textarea-wrapper{display:flex;background-color:var(--color-bg-base);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-md);transition:var(--transition-colors),var(--transition-shadow);overflow:hidden}.ea-textarea-wrapper--sm .ea-textarea{padding:var(--space-2);font-size:var(--font-size-sm)}.ea-textarea-wrapper--md .ea-textarea{padding:var(--space-3);font-size:var(--font-size-md)}.ea-textarea-wrapper--lg .ea-textarea{padding:var(--space-4);font-size:var(--font-size-lg)}.ea-textarea-wrapper--focused{border-color:var(--color-border-focus);box-shadow:var(--shadow-focus-ring)}.ea-textarea-wrapper--error{border-color:var(--color-error-default)}.ea-textarea-wrapper--error.ea-textarea-wrapper--focused{box-shadow:var(--shadow-focus-ring-error)}.ea-textarea-wrapper--disabled{background-color:var(--color-bg-muted);border-color:var(--color-border-default);cursor:not-allowed;opacity:.6}.ea-textarea-wrapper--disabled .ea-textarea{cursor:not-allowed}.ea-textarea-wrapper--readonly{background-color:var(--color-bg-subtle)}.ea-textarea{flex:1;width:100%;min-width:0;min-height:0;background:transparent;border:none;outline:none;color:var(--color-text-primary);font-family:var(--font-family-sans);line-height:var(--line-height-normal)}.ea-textarea::placeholder{color:var(--color-text-tertiary)}.ea-textarea:disabled{cursor:not-allowed}\n"] }]
6357
+ }], propDecorators: { textareaEl: [{ type: i0.ViewChild, args: ['textareaEl', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], errorMsg: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMsg", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], resize: [{ type: i0.Input, args: [{ isSignal: true, alias: "resize", required: false }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], focused: [{ type: i0.Output, args: ["focused"] }], blurred: [{ type: i0.Output, args: ["blurred"] }] } });
5525
6358
 
6359
+ /**
6360
+ * Application-wide notification service. Use the convenience methods
6361
+ * (`success`, `error`, `warning`, `info`) to push a toast, or call
6362
+ * {@link show} for full control. A single `<ea-toast />` outlet must be
6363
+ * present in the app for toasts to appear.
6364
+ */
5526
6365
  class ToastService {
5527
6366
  nextId = 0;
5528
6367
  toasts = signal([], ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
6368
+ /** Shows a toast and returns its id; pass `duration: 0` to disable auto-dismiss. */
5529
6369
  show(message, options = {}) {
5530
6370
  const id = this.nextId++;
5531
6371
  const toast = {
@@ -5540,21 +6380,27 @@ class ToastService {
5540
6380
  }
5541
6381
  return id;
5542
6382
  }
6383
+ /** Shows a `success` toast and returns its id. */
5543
6384
  success(message, duration) {
5544
6385
  return this.show(message, { variant: 'success', duration });
5545
6386
  }
6387
+ /** Shows an `error` toast and returns its id. */
5546
6388
  error(message, duration) {
5547
6389
  return this.show(message, { variant: 'error', duration });
5548
6390
  }
6391
+ /** Shows a `warning` toast and returns its id. */
5549
6392
  warning(message, duration) {
5550
6393
  return this.show(message, { variant: 'warning', duration });
5551
6394
  }
6395
+ /** Shows an `info` toast and returns its id. */
5552
6396
  info(message, duration) {
5553
6397
  return this.show(message, { variant: 'info', duration });
5554
6398
  }
6399
+ /** Removes the toast with the given id, if it is still active. */
5555
6400
  dismiss(id) {
5556
6401
  this.toasts.update(list => list.filter(t => t.id !== id));
5557
6402
  }
6403
+ /** Removes all currently visible toasts. */
5558
6404
  clear() {
5559
6405
  this.toasts.set([]);
5560
6406
  }
@@ -5566,14 +6412,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
5566
6412
  args: [{ providedIn: 'root' }]
5567
6413
  }] });
5568
6414
 
6415
+ /**
6416
+ * Outlet that renders the stack of active toasts produced by
6417
+ * {@link ToastService}. Place a single `<ea-toast />` once in the root
6418
+ * template so toasts created from anywhere in the app are surfaced.
6419
+ */
5569
6420
  class ToastComponent {
5570
6421
  toastService = inject(ToastService);
6422
+ getRole(toast) {
6423
+ return toast.variant === 'error' || toast.variant === 'warning' ? 'alert' : 'status';
6424
+ }
5571
6425
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5572
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ToastComponent, isStandalone: true, selector: "ea-toast", ngImport: i0, template: "@if (toastService.toasts().length) {\n <div\n class=\"ea-toast-container\"\n aria-live=\"polite\"\n aria-atomic=\"false\">\n @for (toast of toastService.toasts(); track toast.id) {\n <div\n class=\"ea-toast ea-toast--{{ toast.variant }}\"\n role=\"status\">\n <span class=\"ea-toast__message\">{{ toast.message }}</span>\n <button\n class=\"ea-toast__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"toastService.dismiss(toast.id)\">\n <ea-icon-x />\n </button>\n </div>\n }\n </div>\n}\n", styles: [".ea-toast-container{position:fixed;bottom:var(--space-6);right:var(--space-6);left:var(--space-6);z-index:var(--z-index-toast);display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-2);pointer-events:none}@media(min-width:640px){.ea-toast-container{left:auto;max-width:24rem}}.ea-toast{display:flex;align-items:center;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);pointer-events:auto;animation:ea-toast-slide-in var(--duration-slow) var(--ease-out)}@media(min-width:640px){.ea-toast{width:auto}}.ea-toast--default{background-color:var(--color-neutral-800);color:var(--color-neutral-0)}.ea-toast--success{background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-toast--warning{background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-toast--error{background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-toast--info{background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-toast__message{flex:1;min-width:0}.ea-toast__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;color:inherit;opacity:.7;cursor:pointer;border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-toast__close:hover{opacity:1}.ea-toast__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@keyframes ea-toast-slide-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
6426
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ToastComponent, isStandalone: true, selector: "ea-toast", ngImport: i0, template: "@if (toastService.toasts().length) {\n <div\n class=\"ea-toast-container\"\n aria-live=\"polite\"\n aria-atomic=\"false\">\n @for (toast of toastService.toasts(); track toast.id) {\n <div\n class=\"ea-toast ea-toast--{{ toast.variant }}\"\n [attr.role]=\"getRole(toast)\"\n [attr.aria-live]=\"getRole(toast) === 'alert' ? 'assertive' : 'polite'\">\n <span class=\"ea-toast__message\">{{ toast.message }}</span>\n <button\n class=\"ea-toast__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"toastService.dismiss(toast.id)\">\n <ea-icon-x />\n </button>\n </div>\n }\n </div>\n}\n", styles: [".ea-toast-container{position:fixed;bottom:var(--space-6);right:var(--space-6);left:var(--space-6);z-index:var(--z-index-toast);display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-2);pointer-events:none}@media(min-width:640px){.ea-toast-container{left:auto;max-width:24rem}}.ea-toast{display:flex;align-items:center;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);pointer-events:auto;animation:ea-toast-slide-in var(--duration-slow) var(--ease-out)}@media(min-width:640px){.ea-toast{width:auto}}.ea-toast--default{background-color:var(--color-neutral-800);color:var(--color-neutral-0)}.ea-toast--success{background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-toast--warning{background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-toast--error{background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-toast--info{background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-toast__message{flex:1;min-width:0}.ea-toast__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;color:inherit;opacity:.7;cursor:pointer;border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-toast__close:hover{opacity:1}.ea-toast__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@keyframes ea-toast-slide-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
5573
6427
  }
5574
6428
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ToastComponent, decorators: [{
5575
6429
  type: Component,
5576
- args: [{ selector: 'ea-toast', imports: [XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (toastService.toasts().length) {\n <div\n class=\"ea-toast-container\"\n aria-live=\"polite\"\n aria-atomic=\"false\">\n @for (toast of toastService.toasts(); track toast.id) {\n <div\n class=\"ea-toast ea-toast--{{ toast.variant }}\"\n role=\"status\">\n <span class=\"ea-toast__message\">{{ toast.message }}</span>\n <button\n class=\"ea-toast__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"toastService.dismiss(toast.id)\">\n <ea-icon-x />\n </button>\n </div>\n }\n </div>\n}\n", styles: [".ea-toast-container{position:fixed;bottom:var(--space-6);right:var(--space-6);left:var(--space-6);z-index:var(--z-index-toast);display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-2);pointer-events:none}@media(min-width:640px){.ea-toast-container{left:auto;max-width:24rem}}.ea-toast{display:flex;align-items:center;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);pointer-events:auto;animation:ea-toast-slide-in var(--duration-slow) var(--ease-out)}@media(min-width:640px){.ea-toast{width:auto}}.ea-toast--default{background-color:var(--color-neutral-800);color:var(--color-neutral-0)}.ea-toast--success{background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-toast--warning{background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-toast--error{background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-toast--info{background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-toast__message{flex:1;min-width:0}.ea-toast__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;color:inherit;opacity:.7;cursor:pointer;border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-toast__close:hover{opacity:1}.ea-toast__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@keyframes ea-toast-slide-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}\n"] }]
6430
+ args: [{ selector: 'ea-toast', imports: [XIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if (toastService.toasts().length) {\n <div\n class=\"ea-toast-container\"\n aria-live=\"polite\"\n aria-atomic=\"false\">\n @for (toast of toastService.toasts(); track toast.id) {\n <div\n class=\"ea-toast ea-toast--{{ toast.variant }}\"\n [attr.role]=\"getRole(toast)\"\n [attr.aria-live]=\"getRole(toast) === 'alert' ? 'assertive' : 'polite'\">\n <span class=\"ea-toast__message\">{{ toast.message }}</span>\n <button\n class=\"ea-toast__close\"\n type=\"button\"\n aria-label=\"Dismiss\"\n (click)=\"toastService.dismiss(toast.id)\">\n <ea-icon-x />\n </button>\n </div>\n }\n </div>\n}\n", styles: [".ea-toast-container{position:fixed;bottom:var(--space-6);right:var(--space-6);left:var(--space-6);z-index:var(--z-index-toast);display:flex;flex-direction:column;align-items:flex-end;gap:var(--space-2);pointer-events:none}@media(min-width:640px){.ea-toast-container{left:auto;max-width:24rem}}.ea-toast{display:flex;align-items:center;gap:var(--space-3);width:100%;padding:var(--space-3) var(--space-4);font-family:var(--font-family-sans);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);pointer-events:auto;animation:ea-toast-slide-in var(--duration-slow) var(--ease-out)}@media(min-width:640px){.ea-toast{width:auto}}.ea-toast--default{background-color:var(--color-neutral-800);color:var(--color-neutral-0)}.ea-toast--success{background-color:var(--color-success-subtle);color:var(--color-success-700)}.ea-toast--warning{background-color:var(--color-warning-subtle);color:var(--color-warning-700)}.ea-toast--error{background-color:var(--color-error-subtle);color:var(--color-error-700)}.ea-toast--info{background-color:var(--color-info-subtle);color:var(--color-info-700)}.ea-toast__message{flex:1;min-width:0}.ea-toast__close{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:none;border:none;color:inherit;opacity:.7;cursor:pointer;border-radius:var(--radius-sm);transition:var(--transition-colors)}.ea-toast__close:hover{opacity:1}.ea-toast__close:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}@keyframes ea-toast-slide-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}\n"] }]
5577
6431
  }] });
5578
6432
 
5579
6433
  // =============================================================================
@@ -5585,5 +6439,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
5585
6439
  * Generated bundle index. Do not edit.
5586
6440
  */
5587
6441
 
5588
- export { AccordionComponent, AccordionItemComponent, AlertCircleIconComponent, AlertComponent, AlertTriangleIconComponent, AppleIconComponent, ArrowDownIconComponent, ArrowLeftIconComponent, ArrowRightIconComponent, ArrowUpIconComponent, AutocompleteComponent, AvatarComponent, AvatarEditorComponent, BadgeComponent, BellIconComponent, BreadcrumbsComponent, ButtonComponent, CalendarIconComponent, CameraIconComponent, CardComponent, CheckCircleIconComponent, CheckIconComponent, CheckboxComponent, ChevronDownIconComponent, ChevronLeftIconComponent, ChevronRightIconComponent, ChevronUpIconComponent, ChevronsUpDownIconComponent, ClockIconComponent, CodeInputComponent, CopyIconComponent, DataTableComponent, DatePickerComponent, DialogComponent, DividerComponent, DownloadIconComponent, DrawerComponent, DropdownComponent, EagamiIconComponent, EagamiWordmarkComponent, ExternalLinkIconComponent, EyeIconComponent, EyeOffIconComponent, FacebookIconComponent, FileIconComponent, FilterIconComponent, GithubIconComponent, GoogleIconComponent, HeartIconComponent, ImageIconComponent, InfoIconComponent, InputComponent, LinkIconComponent, LoaderIconComponent, LogOutIconComponent, MailIconComponent, MenuComponent, MenuIconComponent, MenuItemComponent, MicrosoftIconComponent, MinusIconComponent, MoreHorizontalIconComponent, PaginatorComponent, PencilIconComponent, PlusIconComponent, ProgressBarComponent, RadioComponent, RadioGroupComponent, RotateCcwIconComponent, SearchIconComponent, SettingsIconComponent, SkeletonComponent, SpinnerComponent, StarIconComponent, SwitchComponent, TabComponent, TabsComponent, TagComponent, TextareaComponent, ToastComponent, ToastService, TooltipDirective, TrashIconComponent, UploadIconComponent, UserIconComponent, XCircleIconComponent, XIconComponent, XTwitterIconComponent };
6442
+ export { AccordionComponent, AccordionItemComponent, AlertCircleIconComponent, AlertComponent, AlertTriangleIconComponent, AppleIconComponent, ArrowDownIconComponent, ArrowLeftIconComponent, ArrowRightIconComponent, ArrowUpIconComponent, AutocompleteComponent, AvatarComponent, AvatarEditorComponent, BadgeComponent, BellIconComponent, BreadcrumbsComponent, ButtonComponent, CalendarIconComponent, CameraIconComponent, CardComponent, CheckCircleIconComponent, CheckIconComponent, CheckboxComponent, ChevronDownIconComponent, ChevronLeftIconComponent, ChevronRightIconComponent, ChevronUpIconComponent, ChevronsUpDownIconComponent, ClockIconComponent, CodeInputComponent, CopyIconComponent, DataTableComponent, DatePickerComponent, DialogComponent, DividerComponent, DownloadIconComponent, DrawerComponent, DropdownComponent, EagamiIconComponent, EagamiWordmarkComponent, EmptyStateComponent, ExternalLinkIconComponent, EyeIconComponent, EyeOffIconComponent, FacebookIconComponent, FileIconComponent, FilterIconComponent, GithubIconComponent, GoogleIconComponent, HeartIconComponent, ImageIconComponent, InfoIconComponent, InputComponent, LinkIconComponent, LoaderIconComponent, LogOutIconComponent, MailIconComponent, MenuComponent, MenuIconComponent, MenuItemComponent, MenuTriggerDirective, MicrosoftIconComponent, MinusIconComponent, MoreHorizontalIconComponent, PaginatorComponent, PencilIconComponent, PlusIconComponent, ProgressBarComponent, RadioComponent, RadioGroupComponent, RotateCcwIconComponent, SearchIconComponent, SegmentedComponent, SettingsIconComponent, SkeletonComponent, SliderComponent, SpinnerComponent, StarIconComponent, SwitchComponent, TabComponent, TabsComponent, TagComponent, TextareaComponent, ToastComponent, ToastService, TooltipDirective, TrashIconComponent, UploadIconComponent, UserIconComponent, XCircleIconComponent, XIconComponent, XTwitterIconComponent };
5589
6443
  //# sourceMappingURL=eagami-ui.mjs.map