@eagami/ui 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/eagami-ui.mjs +1264 -1277
- package/fesm2022/eagami-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/eagami-ui.d.ts +0 -2
package/fesm2022/eagami-ui.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, signal, inject, effect, computed, Injectable, input, ChangeDetectionStrategy, Component, HostBinding, Directive, model, output, viewChild,
|
|
2
|
+
import { InjectionToken, makeEnvironmentProviders, provideEnvironmentInitializer, signal, inject, effect, computed, Injectable, input, ChangeDetectionStrategy, Component, HostBinding, Directive, model, output, DestroyRef, viewChild, ElementRef, HostListener, forwardRef, Renderer2, Injector, untracked, afterNextRender, ViewEncapsulation, contentChild, viewChildren } from '@angular/core';
|
|
3
3
|
import { NgClass, NgComponentOutlet, NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
5
5
|
|
|
@@ -1270,11 +1270,11 @@ class AccordionComponent {
|
|
|
1270
1270
|
return this.expandedItems().has(value);
|
|
1271
1271
|
}
|
|
1272
1272
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1273
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: AccordionComponent, isStandalone: true, selector: "ea-accordion", inputs: { multi: { classPropertyName: "multi", publicName: "multi", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: ` <div class="ea-accordion"><ng-content /></div> `, isInline: true, styles: [".ea-accordion{display:flex;flex-direction:column;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1273
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: AccordionComponent, isStandalone: true, selector: "ea-accordion", inputs: { multi: { classPropertyName: "multi", publicName: "multi", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: ` <div class="ea-accordion"><ng-content /></div> `, isInline: true, styles: [":host{display:block}.ea-accordion{display:flex;flex-direction:column;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);overflow:hidden}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1274
1274
|
}
|
|
1275
1275
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AccordionComponent, decorators: [{
|
|
1276
1276
|
type: Component,
|
|
1277
|
-
args: [{ selector: 'ea-accordion', template: ` <div class="ea-accordion"><ng-content /></div> `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ea-accordion{display:flex;flex-direction:column;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);overflow:hidden}\n"] }]
|
|
1277
|
+
args: [{ selector: 'ea-accordion', template: ` <div class="ea-accordion"><ng-content /></div> `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.ea-accordion{display:flex;flex-direction:column;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);overflow:hidden}\n"] }]
|
|
1278
1278
|
}], propDecorators: { multi: [{ type: i0.Input, args: [{ isSignal: true, alias: "multi", required: false }] }] } });
|
|
1279
1279
|
|
|
1280
1280
|
/**
|
|
@@ -1742,226 +1742,653 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
1742
1742
|
args: [{ selector: 'ea-field-messages', imports: [AlertCircleIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (error()) {\n <p\n class=\"ea-field-messages__message ea-field-messages__message--error\"\n [id]=\"id() + '-error'\"\n role=\"alert\">\n <ea-icon-alert-circle class=\"ea-field-messages__icon\" />\n {{ error() }}\n </p>\n} @else if (hint()) {\n <p\n class=\"ea-field-messages__message ea-field-messages__message--hint\"\n [id]=\"id() + '-hint'\">\n {{ hint() }}\n </p>\n}\n", styles: [":host{display:contents}.ea-field-messages__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-field-messages__message--hint{color:var(--color-text-secondary)}.ea-field-messages__message--error{color:var(--color-error-default)}.ea-field-messages__icon{flex-shrink:0;width:.875em;height:.875em}\n"] }]
|
|
1743
1743
|
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }] } });
|
|
1744
1744
|
|
|
1745
|
-
/**
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
1757
|
-
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
1758
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
1759
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
1760
|
-
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
1761
|
-
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
1762
|
-
hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
1763
|
-
errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
|
|
1764
|
-
minLength = input(0, ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
|
|
1765
|
-
maxResults = input(10, ...(ngDevMode ? [{ debugName: "maxResults" }] : /* istanbul ignore next */ []));
|
|
1766
|
-
emptyMessage = input(undefined, ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
1767
|
-
id = input(uniqueId('ea-autocomplete'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
1768
|
-
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
1769
|
-
/** Fires when the user picks an option from the suggestion list. */
|
|
1770
|
-
selected = output();
|
|
1771
|
-
/** Fires whenever the input text changes, including on free-text edits. */
|
|
1772
|
-
changed = output();
|
|
1773
|
-
/** Fires when the input receives focus. */
|
|
1774
|
-
focused = output();
|
|
1775
|
-
/** Fires when the input loses focus. */
|
|
1776
|
-
blurred = output();
|
|
1777
|
-
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
1778
|
-
isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
|
|
1779
|
-
focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
|
|
1780
|
-
_formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
|
|
1781
|
-
justSelected = false;
|
|
1782
|
-
onChange = () => { };
|
|
1783
|
-
onTouched = () => { };
|
|
1784
|
-
isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
1785
|
-
hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
1786
|
-
showError = this.hasError;
|
|
1787
|
-
showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
|
|
1788
|
-
filteredOptions = computed(() => {
|
|
1789
|
-
const query = this.value().trim().toLowerCase();
|
|
1790
|
-
const allOptions = this.options();
|
|
1791
|
-
const max = this.maxResults();
|
|
1792
|
-
if (query.length < this.minLength()) {
|
|
1793
|
-
return [];
|
|
1794
|
-
}
|
|
1795
|
-
const matched = query
|
|
1796
|
-
? allOptions.filter(o => o.label.toLowerCase().includes(query))
|
|
1797
|
-
: allOptions;
|
|
1798
|
-
return matched.slice(0, max);
|
|
1799
|
-
}, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
|
|
1800
|
-
showList = computed(() => this.isOpen() && this.value().length >= this.minLength(), ...(ngDevMode ? [{ debugName: "showList" }] : /* istanbul ignore next */ []));
|
|
1801
|
-
showEmpty = computed(() => this.showList() && this.filteredOptions().length === 0, ...(ngDevMode ? [{ debugName: "showEmpty" }] : /* istanbul ignore next */ []));
|
|
1802
|
-
/** Empty-list message, falling back to the active locale's translation. */
|
|
1803
|
-
resolvedEmptyMessage = computed(() => this.emptyMessage() ?? this.i18n.messages().autocomplete.empty, ...(ngDevMode ? [{ debugName: "resolvedEmptyMessage" }] : /* istanbul ignore next */ []));
|
|
1804
|
-
wrapperClasses = computed(() => ({
|
|
1805
|
-
[`ea-autocomplete__wrapper--${this.size()}`]: true,
|
|
1806
|
-
'ea-autocomplete__wrapper--error': this.hasError(),
|
|
1807
|
-
'ea-autocomplete__wrapper--focused': this.isFocused(),
|
|
1808
|
-
'ea-autocomplete__wrapper--disabled': this.isDisabled(),
|
|
1809
|
-
}), ...(ngDevMode ? [{ debugName: "wrapperClasses" }] : /* istanbul ignore next */ []));
|
|
1810
|
-
listboxClasses = computed(() => ({
|
|
1811
|
-
[`ea-autocomplete__listbox--${this.size()}`]: true,
|
|
1812
|
-
}), ...(ngDevMode ? [{ debugName: "listboxClasses" }] : /* istanbul ignore next */ []));
|
|
1813
|
-
writeValue(val) {
|
|
1814
|
-
this.value.set(val ?? '');
|
|
1745
|
+
/** True for cardinal placements that centre the popover on the perpendicular axis. */
|
|
1746
|
+
function isCardinal(placement) {
|
|
1747
|
+
return (placement === 'top' ||
|
|
1748
|
+
placement === 'bottom' ||
|
|
1749
|
+
placement === 'left' ||
|
|
1750
|
+
placement === 'right');
|
|
1751
|
+
}
|
|
1752
|
+
/** The dominant side of a placement (`top-start` and `top` both give `top`, etc.). */
|
|
1753
|
+
function side(placement) {
|
|
1754
|
+
if (placement.startsWith('top')) {
|
|
1755
|
+
return 'top';
|
|
1815
1756
|
}
|
|
1816
|
-
|
|
1817
|
-
|
|
1757
|
+
if (placement.startsWith('bottom')) {
|
|
1758
|
+
return 'bottom';
|
|
1818
1759
|
}
|
|
1819
|
-
|
|
1820
|
-
|
|
1760
|
+
if (placement === 'left') {
|
|
1761
|
+
return 'left';
|
|
1821
1762
|
}
|
|
1822
|
-
|
|
1823
|
-
|
|
1763
|
+
return 'right';
|
|
1764
|
+
}
|
|
1765
|
+
/** Maps `top` to `bottom`, `bottom-start` to `top-start`, etc. for flip logic. */
|
|
1766
|
+
function flipPlacement(placement) {
|
|
1767
|
+
if (placement === 'top') {
|
|
1768
|
+
return 'bottom';
|
|
1824
1769
|
}
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
this.value.set(next);
|
|
1828
|
-
this.onChange(next);
|
|
1829
|
-
this.changed.emit(next);
|
|
1830
|
-
this.isOpen.set(true);
|
|
1831
|
-
this.focusedIndex.set(-1);
|
|
1770
|
+
if (placement === 'bottom') {
|
|
1771
|
+
return 'top';
|
|
1832
1772
|
}
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
this.focused.emit(event);
|
|
1836
|
-
if (this.justSelected) {
|
|
1837
|
-
this.justSelected = false;
|
|
1838
|
-
return;
|
|
1839
|
-
}
|
|
1840
|
-
if (this.value().length >= this.minLength()) {
|
|
1841
|
-
this.isOpen.set(true);
|
|
1842
|
-
}
|
|
1773
|
+
if (placement === 'left') {
|
|
1774
|
+
return 'right';
|
|
1843
1775
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
this.onTouched();
|
|
1847
|
-
this.blurred.emit(event);
|
|
1776
|
+
if (placement === 'right') {
|
|
1777
|
+
return 'left';
|
|
1848
1778
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
return;
|
|
1852
|
-
}
|
|
1853
|
-
switch (event.key) {
|
|
1854
|
-
case 'ArrowDown':
|
|
1855
|
-
event.preventDefault();
|
|
1856
|
-
if (!this.isOpen()) {
|
|
1857
|
-
this.isOpen.set(true);
|
|
1858
|
-
}
|
|
1859
|
-
else {
|
|
1860
|
-
this.moveFocus(1);
|
|
1861
|
-
}
|
|
1862
|
-
break;
|
|
1863
|
-
case 'ArrowUp':
|
|
1864
|
-
event.preventDefault();
|
|
1865
|
-
if (this.isOpen()) {
|
|
1866
|
-
this.moveFocus(-1);
|
|
1867
|
-
}
|
|
1868
|
-
break;
|
|
1869
|
-
case 'Enter': {
|
|
1870
|
-
const opts = this.filteredOptions();
|
|
1871
|
-
const idx = this.focusedIndex();
|
|
1872
|
-
if (this.isOpen() && idx >= 0 && idx < opts.length && !opts[idx].disabled) {
|
|
1873
|
-
event.preventDefault();
|
|
1874
|
-
this.selectOption(opts[idx]);
|
|
1875
|
-
}
|
|
1876
|
-
break;
|
|
1877
|
-
}
|
|
1878
|
-
case 'Escape':
|
|
1879
|
-
if (this.isOpen()) {
|
|
1880
|
-
event.preventDefault();
|
|
1881
|
-
this.close();
|
|
1882
|
-
}
|
|
1883
|
-
break;
|
|
1884
|
-
}
|
|
1779
|
+
if (placement === 'top-start') {
|
|
1780
|
+
return 'bottom-start';
|
|
1885
1781
|
}
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
if (option.disabled || this.isDisabled()) {
|
|
1889
|
-
return;
|
|
1890
|
-
}
|
|
1891
|
-
this.value.set(option.label);
|
|
1892
|
-
this.onChange(option.label);
|
|
1893
|
-
this.changed.emit(option.label);
|
|
1894
|
-
this.selected.emit(option);
|
|
1895
|
-
this.justSelected = true;
|
|
1896
|
-
this.close();
|
|
1897
|
-
this.inputEl()?.nativeElement.focus();
|
|
1782
|
+
if (placement === 'top-end') {
|
|
1783
|
+
return 'bottom-end';
|
|
1898
1784
|
}
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
this.isOpen.set(false);
|
|
1902
|
-
this.focusedIndex.set(-1);
|
|
1785
|
+
if (placement === 'bottom-start') {
|
|
1786
|
+
return 'top-start';
|
|
1903
1787
|
}
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1788
|
+
return 'top-end';
|
|
1789
|
+
}
|
|
1790
|
+
/** Computes the top/left for a given placement without any flip or clamp logic. */
|
|
1791
|
+
function placeRaw(anchor, popover, placement, offset) {
|
|
1792
|
+
const s = side(placement);
|
|
1793
|
+
let top = 0;
|
|
1794
|
+
let left = 0;
|
|
1795
|
+
if (s === 'top') {
|
|
1796
|
+
top = anchor.top - popover.height - offset;
|
|
1907
1797
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1798
|
+
else if (s === 'bottom') {
|
|
1799
|
+
top = anchor.bottom + offset;
|
|
1800
|
+
}
|
|
1801
|
+
else if (s === 'left') {
|
|
1802
|
+
left = anchor.left - popover.width - offset;
|
|
1803
|
+
}
|
|
1804
|
+
else {
|
|
1805
|
+
left = anchor.right + offset;
|
|
1806
|
+
}
|
|
1807
|
+
if (s === 'top' || s === 'bottom') {
|
|
1808
|
+
if (isCardinal(placement)) {
|
|
1809
|
+
left = anchor.left + (anchor.width - popover.width) / 2;
|
|
1912
1810
|
}
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
idx += delta;
|
|
1811
|
+
else if (placement === 'top-start' || placement === 'bottom-start') {
|
|
1812
|
+
left = anchor.left;
|
|
1916
1813
|
}
|
|
1917
|
-
|
|
1918
|
-
|
|
1814
|
+
else {
|
|
1815
|
+
left = anchor.right - popover.width;
|
|
1919
1816
|
}
|
|
1920
|
-
this.focusedIndex.set(idx);
|
|
1921
1817
|
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
return;
|
|
1925
|
-
}
|
|
1926
|
-
const host = this.hostEl()?.nativeElement;
|
|
1927
|
-
if (host && !host.contains(event.target)) {
|
|
1928
|
-
this.close();
|
|
1929
|
-
}
|
|
1818
|
+
else {
|
|
1819
|
+
top = anchor.top + (anchor.height - popover.height) / 2;
|
|
1930
1820
|
}
|
|
1931
|
-
|
|
1932
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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: [
|
|
1933
|
-
{
|
|
1934
|
-
provide: NG_VALUE_ACCESSOR,
|
|
1935
|
-
useExisting: forwardRef(() => AutocompleteComponent),
|
|
1936
|
-
multi: true,
|
|
1937
|
-
},
|
|
1938
|
-
], 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(); as labelText) {\n <ea-field-label\n [text]=\"labelText\"\n [forId]=\"id()\"\n [required]=\"required()\" />\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 [ngClass]=\"listboxClasses()\"\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 {{ resolvedEmptyMessage() }}\n </li>\n }\n </ul>\n }\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"showError() ? errorMsg() : null\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [".ea-autocomplete{position:relative;display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-autocomplete__wrapper{display:flex;align-items:center;gap:.5em;width:100%;min-height:2.5em;padding:.5em .75em;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--xs{font-size:var(--font-size-xs)}.ea-autocomplete__wrapper--sm{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--md{font-size:var(--font-size-md)}.ea-autocomplete__wrapper--lg{font-size:var(--font-size-lg)}.ea-autocomplete__wrapper--xl{font-size:var(--font-size-xl)}.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-elevated)}.ea-autocomplete__listbox--xs{font-size:var(--font-size-xs)}.ea-autocomplete__listbox--sm{font-size:var(--font-size-sm)}.ea-autocomplete__listbox--md{font-size:var(--font-size-md)}.ea-autocomplete__listbox--lg{font-size:var(--font-size-lg)}.ea-autocomplete__listbox--xl{font-size:var(--font-size-xl)}.ea-autocomplete__option{padding:var(--space-2) var(--space-3);font-size:inherit;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-state-hover)}.ea-autocomplete__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-autocomplete__empty{padding:var(--space-2) var(--space-3);font-size:inherit;font-style:italic;color:var(--color-text-tertiary)}\n"], dependencies: [{ kind: "component", type: FieldLabelComponent, selector: "ea-field-label", inputs: ["text", "forId", "required", "labelId"] }, { kind: "component", type: FieldMessagesComponent, selector: "ea-field-messages", inputs: ["id", "error", "hint"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1821
|
+
return { top, left };
|
|
1939
1822
|
}
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
'
|
|
1964
|
-
|
|
1823
|
+
/**
|
|
1824
|
+
* Computes the viewport-space top/left for a popover anchored to `anchorRect`,
|
|
1825
|
+
* applying optional flip-on-overflow and edge-clamp logic. Pure function, no
|
|
1826
|
+
* DOM access. Both `<ea-popover>` and `[eaTooltip]` consume this.
|
|
1827
|
+
*
|
|
1828
|
+
* @param anchorRect The anchor element's `getBoundingClientRect()`.
|
|
1829
|
+
* @param popoverRect Width and height of the popover (post-render measurement).
|
|
1830
|
+
* @param viewport Viewport dimensions (`window.innerWidth/Height`).
|
|
1831
|
+
* @param options Placement and behavior flags.
|
|
1832
|
+
*/
|
|
1833
|
+
function computePopoverPosition(anchorRect, popoverRect, viewport, options) {
|
|
1834
|
+
const offset = options.offset ?? 4;
|
|
1835
|
+
const margin = options.margin ?? 8;
|
|
1836
|
+
const flip = options.flip ?? true;
|
|
1837
|
+
const clamp = options.clamp ?? true;
|
|
1838
|
+
let placement = options.placement;
|
|
1839
|
+
let pos = placeRaw(anchorRect, popoverRect, placement, offset);
|
|
1840
|
+
if (flip) {
|
|
1841
|
+
const overflowsTop = pos.top < margin;
|
|
1842
|
+
const overflowsBottom = pos.top + popoverRect.height > viewport.height - margin;
|
|
1843
|
+
const overflowsLeft = pos.left < margin;
|
|
1844
|
+
const overflowsRight = pos.left + popoverRect.width > viewport.width - margin;
|
|
1845
|
+
const s = side(placement);
|
|
1846
|
+
const shouldFlip = (s === 'top' && overflowsTop) ||
|
|
1847
|
+
(s === 'bottom' && overflowsBottom) ||
|
|
1848
|
+
(s === 'left' && overflowsLeft) ||
|
|
1849
|
+
(s === 'right' && overflowsRight);
|
|
1850
|
+
if (shouldFlip) {
|
|
1851
|
+
const flipped = flipPlacement(placement);
|
|
1852
|
+
const flippedPos = placeRaw(anchorRect, popoverRect, flipped, offset);
|
|
1853
|
+
const flippedFitsBetter = (s === 'top' &&
|
|
1854
|
+
flippedPos.top + popoverRect.height <= viewport.height - margin) ||
|
|
1855
|
+
(s === 'bottom' && flippedPos.top >= margin) ||
|
|
1856
|
+
(s === 'left' &&
|
|
1857
|
+
flippedPos.left + popoverRect.width <= viewport.width - margin) ||
|
|
1858
|
+
(s === 'right' && flippedPos.left >= margin);
|
|
1859
|
+
if (flippedFitsBetter) {
|
|
1860
|
+
placement = flipped;
|
|
1861
|
+
pos = flippedPos;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
if (clamp) {
|
|
1866
|
+
// Only clamp the cross-axis (perpendicular to the placement). For
|
|
1867
|
+
// bottom-side placements we clamp `left` so the popover doesn't slip off
|
|
1868
|
+
// the left/right of the viewport, but we leave `top` alone; clamping it
|
|
1869
|
+
// when the popover is taller than the available space below the anchor
|
|
1870
|
+
// would yank it up over the anchor itself (the common Storybook-docs-
|
|
1871
|
+
// iframe failure mode where viewports are short). Better to let it
|
|
1872
|
+
// overflow and scroll than to overlap its own trigger.
|
|
1873
|
+
const s = side(placement);
|
|
1874
|
+
const isVertical = s === 'top' || s === 'bottom';
|
|
1875
|
+
if (isVertical) {
|
|
1876
|
+
const maxLeft = viewport.width - popoverRect.width - margin;
|
|
1877
|
+
pos = {
|
|
1878
|
+
top: pos.top,
|
|
1879
|
+
left: Math.max(margin, Math.min(pos.left, Math.max(margin, maxLeft))),
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
else {
|
|
1883
|
+
const maxTop = viewport.height - popoverRect.height - margin;
|
|
1884
|
+
pos = {
|
|
1885
|
+
top: Math.max(margin, Math.min(pos.top, Math.max(margin, maxTop))),
|
|
1886
|
+
left: pos.left,
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
return {
|
|
1891
|
+
top: pos.top,
|
|
1892
|
+
left: pos.left,
|
|
1893
|
+
placement,
|
|
1894
|
+
...(options.matchAnchorWidth ? { width: anchorRect.width } : {}),
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
/**
|
|
1899
|
+
* Floating-element primitive. Renders projected content as `position: fixed`
|
|
1900
|
+
* anchored to an external element, with flip-on-overflow, viewport clamping,
|
|
1901
|
+
* outside-click and Escape dismissal, and SSR-safe scroll / resize handling.
|
|
1902
|
+
*
|
|
1903
|
+
* The primitive is intentionally low-level: a parent component drives the
|
|
1904
|
+
* `[open]` state and listens for `(closeRequested)` to mirror it back. Internal
|
|
1905
|
+
* library components (`<ea-menu>`, `<ea-dropdown>`, `<ea-color-picker>`,
|
|
1906
|
+
* `<ea-date-picker>`, `[eaTooltip]`) compose on top of it; downstream apps can
|
|
1907
|
+
* use it directly to build their own popover-based UI.
|
|
1908
|
+
*
|
|
1909
|
+
* @example
|
|
1910
|
+
* ```html
|
|
1911
|
+
* <button #trigger (click)="open.set(!open())">Open</button>
|
|
1912
|
+
* <ea-popover [anchor]="trigger" [open]="open()" (closeRequested)="open.set(false)">
|
|
1913
|
+
* <div>Popover content</div>
|
|
1914
|
+
* </ea-popover>
|
|
1915
|
+
* ```
|
|
1916
|
+
*/
|
|
1917
|
+
class PopoverComponent {
|
|
1918
|
+
destroyRef = inject(DestroyRef);
|
|
1919
|
+
surfaceEl = viewChild('surfaceEl', ...(ngDevMode ? [{ debugName: "surfaceEl" }] : /* istanbul ignore next */ []));
|
|
1920
|
+
/** Anchor element the popover positions itself against. */
|
|
1921
|
+
anchor = input.required(...(ngDevMode ? [{ debugName: "anchor" }] : /* istanbul ignore next */ []));
|
|
1922
|
+
/** Whether the popover is currently open. */
|
|
1923
|
+
open = input(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
1924
|
+
/** Where the popover attaches relative to the anchor. */
|
|
1925
|
+
placement = input('bottom-start', ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
|
|
1926
|
+
/** ARIA role applied to the popover surface. */
|
|
1927
|
+
role = input('dialog', ...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
|
|
1928
|
+
/** Accessible label. Falls back to nothing; consumers should provide one when no visible heading is in the popover. */
|
|
1929
|
+
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
1930
|
+
/** DOM id for the surface so trigger elements can reference it via aria-controls. */
|
|
1931
|
+
surfaceId = input(uniqueId('ea-popover'), ...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
|
|
1932
|
+
/**
|
|
1933
|
+
* Gap in px between the anchor and the popover. Defaults to 2 so an open panel
|
|
1934
|
+
* clears the anchor's active focus ring instead of sitting flush over it.
|
|
1935
|
+
*/
|
|
1936
|
+
offset = input(2, ...(ngDevMode ? [{ debugName: "offset" }] : /* istanbul ignore next */ []));
|
|
1937
|
+
/** Flip to the opposite side when the requested side overflows the viewport. */
|
|
1938
|
+
flip = input(true, ...(ngDevMode ? [{ debugName: "flip" }] : /* istanbul ignore next */ []));
|
|
1939
|
+
/** Clamp the popover inside the viewport when it would otherwise overflow. */
|
|
1940
|
+
clamp = input(true, ...(ngDevMode ? [{ debugName: "clamp" }] : /* istanbul ignore next */ []));
|
|
1941
|
+
/** Set the popover's `min-width` to match the anchor's width (dropdown pattern). */
|
|
1942
|
+
matchAnchorWidth = input(false, ...(ngDevMode ? [{ debugName: "matchAnchorWidth" }] : /* istanbul ignore next */ []));
|
|
1943
|
+
/** Close on click outside the popover and the anchor. */
|
|
1944
|
+
closeOnOutsideClick = input(true, ...(ngDevMode ? [{ debugName: "closeOnOutsideClick" }] : /* istanbul ignore next */ []));
|
|
1945
|
+
/** Close on Escape. */
|
|
1946
|
+
closeOnEscape = input(true, ...(ngDevMode ? [{ debugName: "closeOnEscape" }] : /* istanbul ignore next */ []));
|
|
1947
|
+
/** What to do on scroll / resize while open. */
|
|
1948
|
+
scrollBehavior = input('reposition', ...(ngDevMode ? [{ debugName: "scrollBehavior" }] : /* istanbul ignore next */ []));
|
|
1949
|
+
/** Requested close. The parent should mirror this into `[open]`. */
|
|
1950
|
+
closeRequested = output();
|
|
1951
|
+
position = signal(null, ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
1952
|
+
/** True placement after flip, for class-based styling (e.g. arrow direction). */
|
|
1953
|
+
effectivePlacement = computed(() => this.position()?.placement ?? this.placement(), ...(ngDevMode ? [{ debugName: "effectivePlacement" }] : /* istanbul ignore next */ []));
|
|
1954
|
+
/** Latches true once the post-rAF reposition has run, so the surface is
|
|
1955
|
+
* only revealed after its dimensions are guaranteed stable. Reset on close. */
|
|
1956
|
+
stable = signal(false, ...(ngDevMode ? [{ debugName: "stable" }] : /* istanbul ignore next */ []));
|
|
1957
|
+
/** True once the first `reposition()` has resolved a placement on a
|
|
1958
|
+
* laid-out surface. Drives the `--positioned` class. */
|
|
1959
|
+
isPositioned = computed(() => this.open() && this.position() !== null && this.stable(), ...(ngDevMode ? [{ debugName: "isPositioned" }] : /* istanbul ignore next */ []));
|
|
1960
|
+
/** Class list for the surface. Computed in TS so the placement key (with
|
|
1961
|
+
* its interpolated suffix) and the positioned modifier compose cleanly. */
|
|
1962
|
+
surfaceClass = computed(() => `ea-popover__surface ea-popover__surface--${this.effectivePlacement()}${this.isPositioned() ? ' ea-popover__surface--positioned' : ''}`, ...(ngDevMode ? [{ debugName: "surfaceClass" }] : /* istanbul ignore next */ []));
|
|
1963
|
+
/** Inline style applied to the surface element. */
|
|
1964
|
+
surfaceStyle = computed(() => {
|
|
1965
|
+
if (!this.open()) {
|
|
1966
|
+
return { display: 'none' };
|
|
1967
|
+
}
|
|
1968
|
+
const p = this.position();
|
|
1969
|
+
if (!p) {
|
|
1970
|
+
return {};
|
|
1971
|
+
}
|
|
1972
|
+
const style = {
|
|
1973
|
+
top: `${p.top}px`,
|
|
1974
|
+
left: `${p.left}px`,
|
|
1975
|
+
};
|
|
1976
|
+
if (p.width !== undefined) {
|
|
1977
|
+
style['min-width'] = `${p.width}px`;
|
|
1978
|
+
}
|
|
1979
|
+
return style;
|
|
1980
|
+
}, ...(ngDevMode ? [{ debugName: "surfaceStyle" }] : /* istanbul ignore next */ []));
|
|
1981
|
+
constructor() {
|
|
1982
|
+
// Re-measure and reposition whenever the anchor, placement, surface, or
|
|
1983
|
+
// open state changes. Reading `surfaceEl()` here makes it a tracked signal
|
|
1984
|
+
// dependency, so the effect re-runs once Angular has rendered the `@if`
|
|
1985
|
+
// block and the viewChild signal has updated; at that point both the
|
|
1986
|
+
// anchor and the surface have a `getBoundingClientRect`, and the position
|
|
1987
|
+
// can be computed. This is more reliable than `afterNextRender` because it
|
|
1988
|
+
// doesn't depend on a single render cycle landing in the expected order
|
|
1989
|
+
// (some host environments, Storybook docs mode for example, defer that
|
|
1990
|
+
// callback in a way that leaves the surface stuck at `visibility: hidden`).
|
|
1991
|
+
// Naturally SSR-safe: the surface never renders on the server, so the
|
|
1992
|
+
// effect always early-returns during prerender.
|
|
1993
|
+
// Teleport the surface to `document.body` as soon as it exists so
|
|
1994
|
+
// `position: fixed` is always relative to the actual viewport (escaping
|
|
1995
|
+
// any transformed/contained ancestor that would otherwise create a new
|
|
1996
|
+
// containing block). Doing the move on init, not on open, also means
|
|
1997
|
+
// the first `getBoundingClientRect` call inside `reposition()` reads a
|
|
1998
|
+
// surface that's already in its final DOM home, so the browser's layout
|
|
1999
|
+
// is settled and dimensions are accurate. Skipped in SSR (no `document`).
|
|
2000
|
+
effect(() => {
|
|
2001
|
+
const surface = this.surfaceEl()?.nativeElement;
|
|
2002
|
+
if (surface &&
|
|
2003
|
+
typeof document !== 'undefined' &&
|
|
2004
|
+
surface.parentNode !== document.body) {
|
|
2005
|
+
document.body.appendChild(surface);
|
|
2006
|
+
}
|
|
2007
|
+
});
|
|
2008
|
+
effect(() => {
|
|
2009
|
+
const surface = this.surfaceEl()?.nativeElement;
|
|
2010
|
+
const anchor = this.resolveAnchor();
|
|
2011
|
+
const isOpen = this.open();
|
|
2012
|
+
if (!surface || !anchor || !isOpen) {
|
|
2013
|
+
this.position.set(null);
|
|
2014
|
+
this.stable.set(false);
|
|
2015
|
+
return;
|
|
2016
|
+
}
|
|
2017
|
+
// Re-read inputs so signal subscriptions stay current after a re-open.
|
|
2018
|
+
this.placement();
|
|
2019
|
+
this.offset();
|
|
2020
|
+
this.flip();
|
|
2021
|
+
this.clamp();
|
|
2022
|
+
this.matchAnchorWidth();
|
|
2023
|
+
// First reposition runs synchronously off the open effect (fast), but
|
|
2024
|
+
// the surface is still transitioning out of `display: none` and the
|
|
2025
|
+
// first `getBoundingClientRect` can report the surface's natural width
|
|
2026
|
+
// even when that overflows the viewport. We deliberately keep the
|
|
2027
|
+
// surface hidden (`visibility: hidden` from CSS) until the next rAF
|
|
2028
|
+
// when the browser has finished laying it out at its real dimensions;
|
|
2029
|
+
// the second reposition then uses accurate measurements and the
|
|
2030
|
+
// `stable` latch flips, revealing the surface at the final position
|
|
2031
|
+
// with no visible jump. SSR / non-browser hosts fall back to flipping
|
|
2032
|
+
// `stable` synchronously.
|
|
2033
|
+
this.reposition();
|
|
2034
|
+
if (typeof requestAnimationFrame !== 'undefined') {
|
|
2035
|
+
requestAnimationFrame(() => {
|
|
2036
|
+
if (!this.open()) {
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
this.reposition();
|
|
2040
|
+
this.stable.set(true);
|
|
2041
|
+
});
|
|
2042
|
+
}
|
|
2043
|
+
else {
|
|
2044
|
+
this.stable.set(true);
|
|
2045
|
+
}
|
|
2046
|
+
});
|
|
2047
|
+
// Watch the surface's own size and reposition whenever it changes. The
|
|
2048
|
+
// first `reposition()` after open fires synchronously inside the open
|
|
2049
|
+
// effect, while the surface is still transitioning out of `display: none`;
|
|
2050
|
+
// in some browsers the layout pass hasn't completed, so the
|
|
2051
|
+
// `getBoundingClientRect` width can read as the surface's natural width
|
|
2052
|
+
// even when that overflows the viewport, so the clamp can't kick in. The
|
|
2053
|
+
// ResizeObserver fires once the surface has been laid out with its real
|
|
2054
|
+
// dimensions, giving us a second, accurate measurement to clamp against.
|
|
2055
|
+
// Also catches projected-content size changes while the popover is open
|
|
2056
|
+
// (e.g. virtualised lists adding rows).
|
|
2057
|
+
if (typeof ResizeObserver !== 'undefined') {
|
|
2058
|
+
const surfaceResizeObserver = new ResizeObserver(() => {
|
|
2059
|
+
if (this.open()) {
|
|
2060
|
+
this.reposition();
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2063
|
+
effect(() => {
|
|
2064
|
+
const surface = this.surfaceEl()?.nativeElement;
|
|
2065
|
+
surfaceResizeObserver.disconnect();
|
|
2066
|
+
if (surface) {
|
|
2067
|
+
surfaceResizeObserver.observe(surface);
|
|
2068
|
+
}
|
|
2069
|
+
});
|
|
2070
|
+
this.destroyRef.onDestroy(() => surfaceResizeObserver.disconnect());
|
|
2071
|
+
}
|
|
2072
|
+
// Listen for scroll / resize while open. The `scrollBehavior` input picks
|
|
2073
|
+
// the response. SSR guard is required because the website prerenders pages
|
|
2074
|
+
// that mount popovers.
|
|
2075
|
+
if (typeof window !== 'undefined') {
|
|
2076
|
+
const onViewportChange = (event) => {
|
|
2077
|
+
if (!this.open()) {
|
|
2078
|
+
return;
|
|
2079
|
+
}
|
|
2080
|
+
// Scrolling within the popover's own surface (e.g. a long dropdown list)
|
|
2081
|
+
// must not dismiss or re-track it; only outside/viewport scroll should.
|
|
2082
|
+
const target = event?.target;
|
|
2083
|
+
if (event?.type === 'scroll' &&
|
|
2084
|
+
target &&
|
|
2085
|
+
this.surfaceEl()?.nativeElement.contains(target)) {
|
|
2086
|
+
return;
|
|
2087
|
+
}
|
|
2088
|
+
const behavior = this.scrollBehavior();
|
|
2089
|
+
if (behavior === 'close') {
|
|
2090
|
+
this.closeRequested.emit();
|
|
2091
|
+
}
|
|
2092
|
+
else if (behavior === 'reposition') {
|
|
2093
|
+
this.reposition();
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
window.addEventListener('scroll', onViewportChange, {
|
|
2097
|
+
capture: true,
|
|
2098
|
+
passive: true,
|
|
2099
|
+
});
|
|
2100
|
+
window.addEventListener('resize', onViewportChange);
|
|
2101
|
+
this.destroyRef.onDestroy(() => {
|
|
2102
|
+
window.removeEventListener('scroll', onViewportChange, { capture: true });
|
|
2103
|
+
window.removeEventListener('resize', onViewportChange);
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
// Explicitly remove the portaled surface on destroy. Angular's view
|
|
2107
|
+
// destruction normally removes nodes the renderer created, but moving the
|
|
2108
|
+
// surface via raw `appendChild` (out of its original anchor slot) is
|
|
2109
|
+
// enough to break that tracking in some host environments: Storybook's
|
|
2110
|
+
// SPA navigation between docs pages, for one, leaves the surface stranded
|
|
2111
|
+
// in `document.body` after the parent component is gone. Removing it here
|
|
2112
|
+
// guarantees cleanup regardless of how Angular's view destruction handles
|
|
2113
|
+
// the relocated node.
|
|
2114
|
+
this.destroyRef.onDestroy(() => {
|
|
2115
|
+
const surface = this.surfaceEl()?.nativeElement;
|
|
2116
|
+
surface?.parentNode?.removeChild(surface);
|
|
2117
|
+
});
|
|
2118
|
+
}
|
|
2119
|
+
resolveAnchor() {
|
|
2120
|
+
const a = this.anchor();
|
|
2121
|
+
if (!a) {
|
|
2122
|
+
return null;
|
|
2123
|
+
}
|
|
2124
|
+
return a instanceof ElementRef ? a.nativeElement : a;
|
|
2125
|
+
}
|
|
2126
|
+
reposition() {
|
|
2127
|
+
if (typeof window === 'undefined') {
|
|
2128
|
+
return;
|
|
2129
|
+
}
|
|
2130
|
+
const anchor = this.resolveAnchor();
|
|
2131
|
+
const surface = this.surfaceEl()?.nativeElement;
|
|
2132
|
+
if (!anchor || !surface) {
|
|
2133
|
+
return;
|
|
2134
|
+
}
|
|
2135
|
+
const anchorRect = anchor.getBoundingClientRect();
|
|
2136
|
+
const surfaceRect = surface.getBoundingClientRect();
|
|
2137
|
+
this.position.set(computePopoverPosition(anchorRect, { width: surfaceRect.width, height: surfaceRect.height }, { width: window.innerWidth, height: window.innerHeight }, {
|
|
2138
|
+
placement: this.placement(),
|
|
2139
|
+
offset: this.offset(),
|
|
2140
|
+
flip: this.flip(),
|
|
2141
|
+
clamp: this.clamp(),
|
|
2142
|
+
matchAnchorWidth: this.matchAnchorWidth(),
|
|
2143
|
+
}));
|
|
2144
|
+
}
|
|
2145
|
+
onDocumentClick(event) {
|
|
2146
|
+
if (!this.open() || !this.closeOnOutsideClick()) {
|
|
2147
|
+
return;
|
|
2148
|
+
}
|
|
2149
|
+
const target = event.target;
|
|
2150
|
+
if (!target) {
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
const anchor = this.resolveAnchor();
|
|
2154
|
+
if (anchor?.contains(target)) {
|
|
2155
|
+
return;
|
|
2156
|
+
}
|
|
2157
|
+
if (this.surfaceEl()?.nativeElement.contains(target)) {
|
|
2158
|
+
return;
|
|
2159
|
+
}
|
|
2160
|
+
this.closeRequested.emit();
|
|
2161
|
+
}
|
|
2162
|
+
onEscape() {
|
|
2163
|
+
if (!this.open() || !this.closeOnEscape()) {
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
this.closeRequested.emit();
|
|
2167
|
+
}
|
|
2168
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: PopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2169
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.16", type: PopoverComponent, isStandalone: true, selector: "ea-popover", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: true, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, surfaceId: { classPropertyName: "surfaceId", publicName: "surfaceId", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, flip: { classPropertyName: "flip", publicName: "flip", isSignal: true, isRequired: false, transformFunction: null }, clamp: { classPropertyName: "clamp", publicName: "clamp", isSignal: true, isRequired: false, transformFunction: null }, matchAnchorWidth: { classPropertyName: "matchAnchorWidth", publicName: "matchAnchorWidth", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsideClick: { classPropertyName: "closeOnOutsideClick", publicName: "closeOnOutsideClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, scrollBehavior: { classPropertyName: "scrollBehavior", publicName: "scrollBehavior", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closeRequested: "closeRequested" }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" }, properties: { "attr.role": "null", "attr.aria-label": "null" } }, viewQueries: [{ propertyName: "surfaceEl", first: true, predicate: ["surfaceEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n The surface is rendered unconditionally so the `<ng-content/>` slot always\n exists. If we gated it on `@if (open())`, Angular would re-project the\n consumer's content at the popover host's position whenever the surface was\n absent, leaking menu items / picker controls into the document flow (made\n worse by `display: contents` on the host). Hiding via `display: none` keeps\n the projected DOM owned by the surface and out of the flow when closed.\n-->\n<div\n #surfaceEl\n [class]=\"surfaceClass()\"\n [id]=\"surfaceId()\"\n [attr.role]=\"open() ? role() : null\"\n [attr.aria-label]=\"open() ? ariaLabel() : null\"\n [attr.aria-hidden]=\"open() ? null : true\"\n [style]=\"surfaceStyle()\">\n <ng-content />\n</div>\n", styles: [":host{display:contents}.ea-popover__surface{z-index:var(--z-index-popover);position:fixed;visibility:hidden}.ea-popover__surface--positioned{visibility:visible}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2170
|
+
}
|
|
2171
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: PopoverComponent, decorators: [{
|
|
2172
|
+
type: Component,
|
|
2173
|
+
args: [{ selector: 'ea-popover', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2174
|
+
'[attr.role]': 'null',
|
|
2175
|
+
'[attr.aria-label]': 'null',
|
|
2176
|
+
}, template: "<!--\n The surface is rendered unconditionally so the `<ng-content/>` slot always\n exists. If we gated it on `@if (open())`, Angular would re-project the\n consumer's content at the popover host's position whenever the surface was\n absent, leaking menu items / picker controls into the document flow (made\n worse by `display: contents` on the host). Hiding via `display: none` keeps\n the projected DOM owned by the surface and out of the flow when closed.\n-->\n<div\n #surfaceEl\n [class]=\"surfaceClass()\"\n [id]=\"surfaceId()\"\n [attr.role]=\"open() ? role() : null\"\n [attr.aria-label]=\"open() ? ariaLabel() : null\"\n [attr.aria-hidden]=\"open() ? null : true\"\n [style]=\"surfaceStyle()\">\n <ng-content />\n</div>\n", styles: [":host{display:contents}.ea-popover__surface{z-index:var(--z-index-popover);position:fixed;visibility:hidden}.ea-popover__surface--positioned{visibility:visible}\n"] }]
|
|
2177
|
+
}], ctorParameters: () => [], propDecorators: { surfaceEl: [{ type: i0.ViewChild, args: ['surfaceEl', { isSignal: true }] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], surfaceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "surfaceId", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], flip: [{ type: i0.Input, args: [{ isSignal: true, alias: "flip", required: false }] }], clamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "clamp", required: false }] }], matchAnchorWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "matchAnchorWidth", required: false }] }], closeOnOutsideClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsideClick", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], scrollBehavior: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollBehavior", required: false }] }], closeRequested: [{ type: i0.Output, args: ["closeRequested"] }], onDocumentClick: [{
|
|
2178
|
+
type: HostListener,
|
|
2179
|
+
args: ['document:click', ['$event']]
|
|
2180
|
+
}], onEscape: [{
|
|
2181
|
+
type: HostListener,
|
|
2182
|
+
args: ['document:keydown.escape']
|
|
2183
|
+
}] } });
|
|
2184
|
+
|
|
2185
|
+
/**
|
|
2186
|
+
* Text input paired with a filtered suggestion list. Filters options by
|
|
2187
|
+
* case-insensitive substring match, supports arrow-key navigation, and
|
|
2188
|
+
* implements `ControlValueAccessor` for use with reactive and template-driven
|
|
2189
|
+
* forms.
|
|
2190
|
+
*/
|
|
2191
|
+
class AutocompleteComponent {
|
|
2192
|
+
inputEl = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputEl" }] : /* istanbul ignore next */ []));
|
|
2193
|
+
i18n = inject(EagamiI18nService);
|
|
2194
|
+
label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2195
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
2196
|
+
options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
2197
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2198
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
2199
|
+
readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
2200
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
2201
|
+
hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
2202
|
+
errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
|
|
2203
|
+
minLength = input(0, ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
|
|
2204
|
+
maxResults = input(10, ...(ngDevMode ? [{ debugName: "maxResults" }] : /* istanbul ignore next */ []));
|
|
2205
|
+
emptyMessage = input(undefined, ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
2206
|
+
id = input(uniqueId('ea-autocomplete'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
2207
|
+
value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
2208
|
+
/** Fires when the user picks an option from the suggestion list. */
|
|
2209
|
+
selected = output();
|
|
2210
|
+
/** Fires whenever the input text changes, including on free-text edits. */
|
|
2211
|
+
changed = output();
|
|
2212
|
+
/** Fires when the input receives focus. */
|
|
2213
|
+
focused = output();
|
|
2214
|
+
/** Fires when the input loses focus. */
|
|
2215
|
+
blurred = output();
|
|
2216
|
+
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
2217
|
+
isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
|
|
2218
|
+
focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : /* istanbul ignore next */ []));
|
|
2219
|
+
_formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
|
|
2220
|
+
justSelected = false;
|
|
2221
|
+
onChange = () => { };
|
|
2222
|
+
onTouched = () => { };
|
|
2223
|
+
isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
2224
|
+
hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
2225
|
+
showError = this.hasError;
|
|
2226
|
+
showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
|
|
2227
|
+
filteredOptions = computed(() => {
|
|
2228
|
+
const query = this.value().trim().toLowerCase();
|
|
2229
|
+
const allOptions = this.options();
|
|
2230
|
+
const max = this.maxResults();
|
|
2231
|
+
if (query.length < this.minLength()) {
|
|
2232
|
+
return [];
|
|
2233
|
+
}
|
|
2234
|
+
const matched = query
|
|
2235
|
+
? allOptions.filter(o => o.label.toLowerCase().includes(query))
|
|
2236
|
+
: allOptions;
|
|
2237
|
+
return matched.slice(0, max);
|
|
2238
|
+
}, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
|
|
2239
|
+
showList = computed(() => this.isOpen() && this.value().length >= this.minLength(), ...(ngDevMode ? [{ debugName: "showList" }] : /* istanbul ignore next */ []));
|
|
2240
|
+
showEmpty = computed(() => this.showList() && this.filteredOptions().length === 0, ...(ngDevMode ? [{ debugName: "showEmpty" }] : /* istanbul ignore next */ []));
|
|
2241
|
+
/** Empty-list message, falling back to the active locale's translation. */
|
|
2242
|
+
resolvedEmptyMessage = computed(() => this.emptyMessage() ?? this.i18n.messages().autocomplete.empty, ...(ngDevMode ? [{ debugName: "resolvedEmptyMessage" }] : /* istanbul ignore next */ []));
|
|
2243
|
+
wrapperClasses = computed(() => ({
|
|
2244
|
+
[`ea-autocomplete__wrapper--${this.size()}`]: true,
|
|
2245
|
+
'ea-autocomplete__wrapper--error': this.hasError(),
|
|
2246
|
+
'ea-autocomplete__wrapper--focused': this.isFocused(),
|
|
2247
|
+
'ea-autocomplete__wrapper--disabled': this.isDisabled(),
|
|
2248
|
+
}), ...(ngDevMode ? [{ debugName: "wrapperClasses" }] : /* istanbul ignore next */ []));
|
|
2249
|
+
listboxClasses = computed(() => ({
|
|
2250
|
+
[`ea-autocomplete__listbox--${this.size()}`]: true,
|
|
2251
|
+
}), ...(ngDevMode ? [{ debugName: "listboxClasses" }] : /* istanbul ignore next */ []));
|
|
2252
|
+
writeValue(val) {
|
|
2253
|
+
this.value.set(val ?? '');
|
|
2254
|
+
}
|
|
2255
|
+
registerOnChange(fn) {
|
|
2256
|
+
this.onChange = fn;
|
|
2257
|
+
}
|
|
2258
|
+
registerOnTouched(fn) {
|
|
2259
|
+
this.onTouched = fn;
|
|
2260
|
+
}
|
|
2261
|
+
setDisabledState(isDisabled) {
|
|
2262
|
+
this._formDisabled.set(isDisabled);
|
|
2263
|
+
}
|
|
2264
|
+
handleInput(event) {
|
|
2265
|
+
const next = event.target.value;
|
|
2266
|
+
this.value.set(next);
|
|
2267
|
+
this.onChange(next);
|
|
2268
|
+
this.changed.emit(next);
|
|
2269
|
+
this.isOpen.set(true);
|
|
2270
|
+
this.focusedIndex.set(-1);
|
|
2271
|
+
}
|
|
2272
|
+
handleFocus(event) {
|
|
2273
|
+
this.isFocused.set(true);
|
|
2274
|
+
this.focused.emit(event);
|
|
2275
|
+
if (this.justSelected) {
|
|
2276
|
+
this.justSelected = false;
|
|
2277
|
+
return;
|
|
2278
|
+
}
|
|
2279
|
+
if (this.value().length >= this.minLength()) {
|
|
2280
|
+
this.isOpen.set(true);
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
handleBlur(event) {
|
|
2284
|
+
this.isFocused.set(false);
|
|
2285
|
+
this.onTouched();
|
|
2286
|
+
this.blurred.emit(event);
|
|
2287
|
+
}
|
|
2288
|
+
handleKeydown(event) {
|
|
2289
|
+
if (this.isDisabled() || this.readonly()) {
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
switch (event.key) {
|
|
2293
|
+
case 'ArrowDown':
|
|
2294
|
+
event.preventDefault();
|
|
2295
|
+
if (!this.isOpen()) {
|
|
2296
|
+
this.isOpen.set(true);
|
|
2297
|
+
}
|
|
2298
|
+
else {
|
|
2299
|
+
this.moveFocus(1);
|
|
2300
|
+
}
|
|
2301
|
+
break;
|
|
2302
|
+
case 'ArrowUp':
|
|
2303
|
+
event.preventDefault();
|
|
2304
|
+
if (this.isOpen()) {
|
|
2305
|
+
this.moveFocus(-1);
|
|
2306
|
+
}
|
|
2307
|
+
break;
|
|
2308
|
+
case 'Enter': {
|
|
2309
|
+
const opts = this.filteredOptions();
|
|
2310
|
+
const idx = this.focusedIndex();
|
|
2311
|
+
if (this.isOpen() && idx >= 0 && idx < opts.length && !opts[idx].disabled) {
|
|
2312
|
+
event.preventDefault();
|
|
2313
|
+
this.selectOption(opts[idx]);
|
|
2314
|
+
}
|
|
2315
|
+
break;
|
|
2316
|
+
}
|
|
2317
|
+
case 'Escape':
|
|
2318
|
+
if (this.isOpen()) {
|
|
2319
|
+
event.preventDefault();
|
|
2320
|
+
this.close();
|
|
2321
|
+
}
|
|
2322
|
+
break;
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
/** Programmatically selects the given option, updating the value and closing the list. */
|
|
2326
|
+
selectOption(option) {
|
|
2327
|
+
if (option.disabled || this.isDisabled()) {
|
|
2328
|
+
return;
|
|
2329
|
+
}
|
|
2330
|
+
this.value.set(option.label);
|
|
2331
|
+
this.onChange(option.label);
|
|
2332
|
+
this.changed.emit(option.label);
|
|
2333
|
+
this.selected.emit(option);
|
|
2334
|
+
this.justSelected = true;
|
|
2335
|
+
this.close();
|
|
2336
|
+
this.inputEl()?.nativeElement.focus();
|
|
2337
|
+
}
|
|
2338
|
+
/** Closes the suggestion list without changing the current value. */
|
|
2339
|
+
close() {
|
|
2340
|
+
this.isOpen.set(false);
|
|
2341
|
+
this.focusedIndex.set(-1);
|
|
2342
|
+
}
|
|
2343
|
+
/** Moves keyboard focus to the underlying text input. */
|
|
2344
|
+
focus() {
|
|
2345
|
+
this.inputEl()?.nativeElement.focus();
|
|
2346
|
+
}
|
|
2347
|
+
moveFocus(delta) {
|
|
2348
|
+
const opts = this.filteredOptions();
|
|
2349
|
+
if (opts.length === 0) {
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
let idx = this.focusedIndex() + delta;
|
|
2353
|
+
while (idx >= 0 && idx < opts.length && opts[idx].disabled) {
|
|
2354
|
+
idx += delta;
|
|
2355
|
+
}
|
|
2356
|
+
if (idx < 0 || idx >= opts.length) {
|
|
2357
|
+
return;
|
|
2358
|
+
}
|
|
2359
|
+
this.focusedIndex.set(idx);
|
|
2360
|
+
}
|
|
2361
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2362
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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" }, providers: [
|
|
2363
|
+
{
|
|
2364
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2365
|
+
useExisting: forwardRef(() => AutocompleteComponent),
|
|
2366
|
+
multi: true,
|
|
2367
|
+
},
|
|
2368
|
+
], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"ea-autocomplete\">\n @if (label(); as labelText) {\n <ea-field-label\n [text]=\"labelText\"\n [forId]=\"id()\"\n [required]=\"required()\" />\n }\n\n <div\n #anchorEl\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 <ea-popover\n [anchor]=\"anchorEl\"\n [open]=\"showList()\"\n placement=\"bottom-start\"\n role=\"listbox\"\n [surfaceId]=\"id() + '-listbox'\"\n [matchAnchorWidth]=\"true\"\n [closeOnEscape]=\"false\"\n scrollBehavior=\"close\"\n (closeRequested)=\"close()\">\n <div\n class=\"ea-autocomplete__listbox\"\n [ngClass]=\"listboxClasses()\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <div\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 </div>\n }\n @if (showEmpty()) {\n <div\n class=\"ea-autocomplete__empty\"\n role=\"presentation\">\n {{ resolvedEmptyMessage() }}\n </div>\n }\n </div>\n </ea-popover>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"showError() ? errorMsg() : null\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [".ea-autocomplete{position:relative;display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-autocomplete__wrapper{display:flex;align-items:center;gap:.5em;width:100%;min-height:2.5em;padding:.5em .75em;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--xs{font-size:var(--font-size-xs)}.ea-autocomplete__wrapper--sm{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--md{font-size:var(--font-size-md)}.ea-autocomplete__wrapper--lg{font-size:var(--font-size-lg)}.ea-autocomplete__wrapper--xl{font-size:var(--font-size-xl)}.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{overflow-y:auto;max-height:15rem;padding:var(--space-1) 0;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-elevated)}.ea-autocomplete__listbox--xs{font-size:var(--font-size-xs)}.ea-autocomplete__listbox--sm{font-size:var(--font-size-sm)}.ea-autocomplete__listbox--md{font-size:var(--font-size-md)}.ea-autocomplete__listbox--lg{font-size:var(--font-size-lg)}.ea-autocomplete__listbox--xl{font-size:var(--font-size-xl)}.ea-autocomplete__option{padding:var(--space-2) var(--space-3);font-size:inherit;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-state-hover)}.ea-autocomplete__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-autocomplete__empty{padding:var(--space-2) var(--space-3);font-size:inherit;font-style:italic;color:var(--color-text-tertiary)}\n"], dependencies: [{ kind: "component", type: FieldLabelComponent, selector: "ea-field-label", inputs: ["text", "forId", "required", "labelId"] }, { kind: "component", type: FieldMessagesComponent, selector: "ea-field-messages", inputs: ["id", "error", "hint"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: PopoverComponent, selector: "ea-popover", inputs: ["anchor", "open", "placement", "role", "aria-label", "surfaceId", "offset", "flip", "clamp", "matchAnchorWidth", "closeOnOutsideClick", "closeOnEscape", "scrollBehavior"], outputs: ["closeRequested"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2369
|
+
}
|
|
2370
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AutocompleteComponent, decorators: [{
|
|
2371
|
+
type: Component,
|
|
2372
|
+
args: [{ selector: 'ea-autocomplete', imports: [FieldLabelComponent, FieldMessagesComponent, NgClass, PopoverComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2373
|
+
{
|
|
2374
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2375
|
+
useExisting: forwardRef(() => AutocompleteComponent),
|
|
2376
|
+
multi: true,
|
|
2377
|
+
},
|
|
2378
|
+
], template: "<div class=\"ea-autocomplete\">\n @if (label(); as labelText) {\n <ea-field-label\n [text]=\"labelText\"\n [forId]=\"id()\"\n [required]=\"required()\" />\n }\n\n <div\n #anchorEl\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 <ea-popover\n [anchor]=\"anchorEl\"\n [open]=\"showList()\"\n placement=\"bottom-start\"\n role=\"listbox\"\n [surfaceId]=\"id() + '-listbox'\"\n [matchAnchorWidth]=\"true\"\n [closeOnEscape]=\"false\"\n scrollBehavior=\"close\"\n (closeRequested)=\"close()\">\n <div\n class=\"ea-autocomplete__listbox\"\n [ngClass]=\"listboxClasses()\">\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <div\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 </div>\n }\n @if (showEmpty()) {\n <div\n class=\"ea-autocomplete__empty\"\n role=\"presentation\">\n {{ resolvedEmptyMessage() }}\n </div>\n }\n </div>\n </ea-popover>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"showError() ? errorMsg() : null\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [".ea-autocomplete{position:relative;display:flex;flex-direction:column;gap:var(--space-1-5)}.ea-autocomplete__wrapper{display:flex;align-items:center;gap:.5em;width:100%;min-height:2.5em;padding:.5em .75em;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--xs{font-size:var(--font-size-xs)}.ea-autocomplete__wrapper--sm{font-size:var(--font-size-sm)}.ea-autocomplete__wrapper--md{font-size:var(--font-size-md)}.ea-autocomplete__wrapper--lg{font-size:var(--font-size-lg)}.ea-autocomplete__wrapper--xl{font-size:var(--font-size-xl)}.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{overflow-y:auto;max-height:15rem;padding:var(--space-1) 0;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-elevated)}.ea-autocomplete__listbox--xs{font-size:var(--font-size-xs)}.ea-autocomplete__listbox--sm{font-size:var(--font-size-sm)}.ea-autocomplete__listbox--md{font-size:var(--font-size-md)}.ea-autocomplete__listbox--lg{font-size:var(--font-size-lg)}.ea-autocomplete__listbox--xl{font-size:var(--font-size-xl)}.ea-autocomplete__option{padding:var(--space-2) var(--space-3);font-size:inherit;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-state-hover)}.ea-autocomplete__option--disabled{color:var(--color-text-disabled);cursor:not-allowed}.ea-autocomplete__empty{padding:var(--space-2) var(--space-3);font-size:inherit;font-style:italic;color:var(--color-text-tertiary)}\n"] }]
|
|
2379
|
+
}], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { 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"] }] } });
|
|
2380
|
+
|
|
2381
|
+
class CameraIconComponent extends IconComponentBase {
|
|
2382
|
+
static slug = 'camera';
|
|
2383
|
+
static category = 'feather';
|
|
2384
|
+
static defaultStrokeWidth = 1.5;
|
|
2385
|
+
static tags = [
|
|
2386
|
+
'camera',
|
|
2387
|
+
'photo',
|
|
2388
|
+
'photography',
|
|
2389
|
+
'picture',
|
|
2390
|
+
'snapshot',
|
|
2391
|
+
'appareil photo',
|
|
1965
2392
|
'cámara',
|
|
1966
2393
|
'foto',
|
|
1967
2394
|
'κάμερα',
|
|
@@ -2358,171 +2785,18 @@ class SkeletonComponent {
|
|
|
2358
2785
|
styles['height'] = this.height();
|
|
2359
2786
|
}
|
|
2360
2787
|
return styles;
|
|
2361
|
-
}, ...(ngDevMode ? [{ debugName: "hostStyles" }] : /* istanbul ignore next */ []));
|
|
2362
|
-
hostClasses = computed(() => ({
|
|
2363
|
-
[`ea-skeleton--${this.variant()}`]: true,
|
|
2364
|
-
'ea-skeleton--animated': this.animated(),
|
|
2365
|
-
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2366
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2367
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: SkeletonComponent, isStandalone: true, selector: "ea-skeleton", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, animated: { classPropertyName: "animated", publicName: "animated", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, 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"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2368
|
-
}
|
|
2369
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SkeletonComponent, decorators: [{
|
|
2370
|
-
type: Component,
|
|
2371
|
-
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"] }]
|
|
2372
|
-
}], 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 }] }] } });
|
|
2373
|
-
|
|
2374
|
-
/** True for cardinal placements that centre the popover on the perpendicular axis. */
|
|
2375
|
-
function isCardinal(placement) {
|
|
2376
|
-
return (placement === 'top' ||
|
|
2377
|
-
placement === 'bottom' ||
|
|
2378
|
-
placement === 'left' ||
|
|
2379
|
-
placement === 'right');
|
|
2380
|
-
}
|
|
2381
|
-
/** The dominant side of a placement (`top-start` and `top` both give `top`, etc.). */
|
|
2382
|
-
function side(placement) {
|
|
2383
|
-
if (placement.startsWith('top')) {
|
|
2384
|
-
return 'top';
|
|
2385
|
-
}
|
|
2386
|
-
if (placement.startsWith('bottom')) {
|
|
2387
|
-
return 'bottom';
|
|
2388
|
-
}
|
|
2389
|
-
if (placement === 'left') {
|
|
2390
|
-
return 'left';
|
|
2391
|
-
}
|
|
2392
|
-
return 'right';
|
|
2393
|
-
}
|
|
2394
|
-
/** Maps `top` to `bottom`, `bottom-start` to `top-start`, etc. for flip logic. */
|
|
2395
|
-
function flipPlacement(placement) {
|
|
2396
|
-
if (placement === 'top') {
|
|
2397
|
-
return 'bottom';
|
|
2398
|
-
}
|
|
2399
|
-
if (placement === 'bottom') {
|
|
2400
|
-
return 'top';
|
|
2401
|
-
}
|
|
2402
|
-
if (placement === 'left') {
|
|
2403
|
-
return 'right';
|
|
2404
|
-
}
|
|
2405
|
-
if (placement === 'right') {
|
|
2406
|
-
return 'left';
|
|
2407
|
-
}
|
|
2408
|
-
if (placement === 'top-start') {
|
|
2409
|
-
return 'bottom-start';
|
|
2410
|
-
}
|
|
2411
|
-
if (placement === 'top-end') {
|
|
2412
|
-
return 'bottom-end';
|
|
2413
|
-
}
|
|
2414
|
-
if (placement === 'bottom-start') {
|
|
2415
|
-
return 'top-start';
|
|
2416
|
-
}
|
|
2417
|
-
return 'top-end';
|
|
2418
|
-
}
|
|
2419
|
-
/** Computes the top/left for a given placement without any flip or clamp logic. */
|
|
2420
|
-
function placeRaw(anchor, popover, placement, offset) {
|
|
2421
|
-
const s = side(placement);
|
|
2422
|
-
let top = 0;
|
|
2423
|
-
let left = 0;
|
|
2424
|
-
if (s === 'top') {
|
|
2425
|
-
top = anchor.top - popover.height - offset;
|
|
2426
|
-
}
|
|
2427
|
-
else if (s === 'bottom') {
|
|
2428
|
-
top = anchor.bottom + offset;
|
|
2429
|
-
}
|
|
2430
|
-
else if (s === 'left') {
|
|
2431
|
-
left = anchor.left - popover.width - offset;
|
|
2432
|
-
}
|
|
2433
|
-
else {
|
|
2434
|
-
left = anchor.right + offset;
|
|
2435
|
-
}
|
|
2436
|
-
if (s === 'top' || s === 'bottom') {
|
|
2437
|
-
if (isCardinal(placement)) {
|
|
2438
|
-
left = anchor.left + (anchor.width - popover.width) / 2;
|
|
2439
|
-
}
|
|
2440
|
-
else if (placement === 'top-start' || placement === 'bottom-start') {
|
|
2441
|
-
left = anchor.left;
|
|
2442
|
-
}
|
|
2443
|
-
else {
|
|
2444
|
-
left = anchor.right - popover.width;
|
|
2445
|
-
}
|
|
2446
|
-
}
|
|
2447
|
-
else {
|
|
2448
|
-
top = anchor.top + (anchor.height - popover.height) / 2;
|
|
2449
|
-
}
|
|
2450
|
-
return { top, left };
|
|
2451
|
-
}
|
|
2452
|
-
/**
|
|
2453
|
-
* Computes the viewport-space top/left for a popover anchored to `anchorRect`,
|
|
2454
|
-
* applying optional flip-on-overflow and edge-clamp logic. Pure function, no
|
|
2455
|
-
* DOM access. Both `<ea-popover>` and `[eaTooltip]` consume this.
|
|
2456
|
-
*
|
|
2457
|
-
* @param anchorRect The anchor element's `getBoundingClientRect()`.
|
|
2458
|
-
* @param popoverRect Width and height of the popover (post-render measurement).
|
|
2459
|
-
* @param viewport Viewport dimensions (`window.innerWidth/Height`).
|
|
2460
|
-
* @param options Placement and behavior flags.
|
|
2461
|
-
*/
|
|
2462
|
-
function computePopoverPosition(anchorRect, popoverRect, viewport, options) {
|
|
2463
|
-
const offset = options.offset ?? 4;
|
|
2464
|
-
const margin = options.margin ?? 8;
|
|
2465
|
-
const flip = options.flip ?? true;
|
|
2466
|
-
const clamp = options.clamp ?? true;
|
|
2467
|
-
let placement = options.placement;
|
|
2468
|
-
let pos = placeRaw(anchorRect, popoverRect, placement, offset);
|
|
2469
|
-
if (flip) {
|
|
2470
|
-
const overflowsTop = pos.top < margin;
|
|
2471
|
-
const overflowsBottom = pos.top + popoverRect.height > viewport.height - margin;
|
|
2472
|
-
const overflowsLeft = pos.left < margin;
|
|
2473
|
-
const overflowsRight = pos.left + popoverRect.width > viewport.width - margin;
|
|
2474
|
-
const s = side(placement);
|
|
2475
|
-
const shouldFlip = (s === 'top' && overflowsTop) ||
|
|
2476
|
-
(s === 'bottom' && overflowsBottom) ||
|
|
2477
|
-
(s === 'left' && overflowsLeft) ||
|
|
2478
|
-
(s === 'right' && overflowsRight);
|
|
2479
|
-
if (shouldFlip) {
|
|
2480
|
-
const flipped = flipPlacement(placement);
|
|
2481
|
-
const flippedPos = placeRaw(anchorRect, popoverRect, flipped, offset);
|
|
2482
|
-
const flippedFitsBetter = (s === 'top' &&
|
|
2483
|
-
flippedPos.top + popoverRect.height <= viewport.height - margin) ||
|
|
2484
|
-
(s === 'bottom' && flippedPos.top >= margin) ||
|
|
2485
|
-
(s === 'left' &&
|
|
2486
|
-
flippedPos.left + popoverRect.width <= viewport.width - margin) ||
|
|
2487
|
-
(s === 'right' && flippedPos.left >= margin);
|
|
2488
|
-
if (flippedFitsBetter) {
|
|
2489
|
-
placement = flipped;
|
|
2490
|
-
pos = flippedPos;
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
if (clamp) {
|
|
2495
|
-
// Only clamp the cross-axis (perpendicular to the placement). For
|
|
2496
|
-
// bottom-side placements we clamp `left` so the popover doesn't slip off
|
|
2497
|
-
// the left/right of the viewport, but we leave `top` alone; clamping it
|
|
2498
|
-
// when the popover is taller than the available space below the anchor
|
|
2499
|
-
// would yank it up over the anchor itself (the common Storybook-docs-
|
|
2500
|
-
// iframe failure mode where viewports are short). Better to let it
|
|
2501
|
-
// overflow and scroll than to overlap its own trigger.
|
|
2502
|
-
const s = side(placement);
|
|
2503
|
-
const isVertical = s === 'top' || s === 'bottom';
|
|
2504
|
-
if (isVertical) {
|
|
2505
|
-
const maxLeft = viewport.width - popoverRect.width - margin;
|
|
2506
|
-
pos = {
|
|
2507
|
-
top: pos.top,
|
|
2508
|
-
left: Math.max(margin, Math.min(pos.left, Math.max(margin, maxLeft))),
|
|
2509
|
-
};
|
|
2510
|
-
}
|
|
2511
|
-
else {
|
|
2512
|
-
const maxTop = viewport.height - popoverRect.height - margin;
|
|
2513
|
-
pos = {
|
|
2514
|
-
top: Math.max(margin, Math.min(pos.top, Math.max(margin, maxTop))),
|
|
2515
|
-
left: pos.left,
|
|
2516
|
-
};
|
|
2517
|
-
}
|
|
2518
|
-
}
|
|
2519
|
-
return {
|
|
2520
|
-
top: pos.top,
|
|
2521
|
-
left: pos.left,
|
|
2522
|
-
placement,
|
|
2523
|
-
...(options.matchAnchorWidth ? { width: anchorRect.width } : {}),
|
|
2524
|
-
};
|
|
2788
|
+
}, ...(ngDevMode ? [{ debugName: "hostStyles" }] : /* istanbul ignore next */ []));
|
|
2789
|
+
hostClasses = computed(() => ({
|
|
2790
|
+
[`ea-skeleton--${this.variant()}`]: true,
|
|
2791
|
+
'ea-skeleton--animated': this.animated(),
|
|
2792
|
+
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
2793
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2794
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: SkeletonComponent, isStandalone: true, selector: "ea-skeleton", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, animated: { classPropertyName: "animated", publicName: "animated", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, 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"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2525
2795
|
}
|
|
2796
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SkeletonComponent, decorators: [{
|
|
2797
|
+
type: Component,
|
|
2798
|
+
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"] }]
|
|
2799
|
+
}], 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 }] }] } });
|
|
2526
2800
|
|
|
2527
2801
|
/**
|
|
2528
2802
|
* Attaches a positioned tooltip to its host element. Shows on hover and
|
|
@@ -3341,401 +3615,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
3341
3615
|
SkeletonComponent,
|
|
3342
3616
|
TooltipDirective,
|
|
3343
3617
|
TrashIconComponent,
|
|
3344
|
-
UploadIconComponent,
|
|
3345
|
-
], 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 [attr.aria-label]=\"i18n.messages().avatarEditor.upload\"\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\">\n {{ i18n.messages().avatarEditor.dropzone }}\n </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 [attr.aria-label]=\"i18n.messages().avatarEditor.canvas\"\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\n class=\"ea-avatar-editor__canvas-overlay\"\n [class.ea-avatar-editor__canvas-overlay--on-light]=\"!isImageDark()\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>{{ i18n.messages().avatarEditor.change }}</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]=\"i18n.messages().avatarEditor.revert\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.revert\"\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]=\"i18n.messages().avatarEditor.zoomOut\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomOut\"\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 [attr.aria-label]=\"i18n.messages().avatarEditor.zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.zoomIn\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomIn\"\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]=\"i18n.messages().avatarEditor.remove\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.remove\"\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-state-hover);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--compact .ea-avatar-editor__dropzone{gap:var(--space-1-5);padding:var(--space-3);font-size:.75rem;line-height:1.35}.ea-avatar-editor--compact .ea-avatar-editor__upload-icon{width:24px;height:24px}.ea-avatar-editor--ultra-compact .ea-avatar-editor__dropzone{gap:var(--space-1);padding:var(--space-2);font-size:.625rem;line-height:1.2}.ea-avatar-editor--ultra-compact .ea-avatar-editor__upload-icon{width:16px;height:16px}.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);color:var(--color-neutral-0);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default),color var(--duration-fast) var(--easing-default)}.ea-avatar-editor__canvas-overlay--on-light{color:var(--color-neutral-950)}.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"] }]
|
|
3346
|
-
}], 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"] }] } });
|
|
3347
|
-
|
|
3348
|
-
class UserIconComponent extends IconComponentBase {
|
|
3349
|
-
static slug = 'user';
|
|
3350
|
-
static category = 'feather';
|
|
3351
|
-
static tags = [
|
|
3352
|
-
'user',
|
|
3353
|
-
'person',
|
|
3354
|
-
'profile',
|
|
3355
|
-
'account',
|
|
3356
|
-
'avatar',
|
|
3357
|
-
'utilisateur',
|
|
3358
|
-
'personne',
|
|
3359
|
-
'usuario',
|
|
3360
|
-
'persona',
|
|
3361
|
-
'χρήστης',
|
|
3362
|
-
'άτομο',
|
|
3363
|
-
'użytkownik',
|
|
3364
|
-
'osoba',
|
|
3365
|
-
];
|
|
3366
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UserIconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3367
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: UserIconComponent, isStandalone: true, selector: "ea-icon-user", usesInheritance: true, ngImport: i0, template: `
|
|
3368
|
-
<svg
|
|
3369
|
-
viewBox="0 0 24 24"
|
|
3370
|
-
fill="none"
|
|
3371
|
-
stroke="currentColor"
|
|
3372
|
-
[attr.stroke-width]="strokeWidth()"
|
|
3373
|
-
stroke-linecap="round"
|
|
3374
|
-
stroke-linejoin="round"
|
|
3375
|
-
aria-hidden="true"
|
|
3376
|
-
width="100%"
|
|
3377
|
-
height="100%">
|
|
3378
|
-
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
3379
|
-
<circle
|
|
3380
|
-
cx="12"
|
|
3381
|
-
cy="7"
|
|
3382
|
-
r="4" />
|
|
3383
|
-
</svg>
|
|
3384
|
-
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3385
|
-
}
|
|
3386
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UserIconComponent, decorators: [{
|
|
3387
|
-
type: Component,
|
|
3388
|
-
args: [{
|
|
3389
|
-
selector: 'ea-icon-user',
|
|
3390
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3391
|
-
template: `
|
|
3392
|
-
<svg
|
|
3393
|
-
viewBox="0 0 24 24"
|
|
3394
|
-
fill="none"
|
|
3395
|
-
stroke="currentColor"
|
|
3396
|
-
[attr.stroke-width]="strokeWidth()"
|
|
3397
|
-
stroke-linecap="round"
|
|
3398
|
-
stroke-linejoin="round"
|
|
3399
|
-
aria-hidden="true"
|
|
3400
|
-
width="100%"
|
|
3401
|
-
height="100%">
|
|
3402
|
-
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
3403
|
-
<circle
|
|
3404
|
-
cx="12"
|
|
3405
|
-
cy="7"
|
|
3406
|
-
r="4" />
|
|
3407
|
-
</svg>
|
|
3408
|
-
`,
|
|
3409
|
-
}]
|
|
3410
|
-
}] });
|
|
3411
|
-
|
|
3412
|
-
/**
|
|
3413
|
-
* Compact image used to represent a user or entity. Falls back to initials
|
|
3414
|
-
* when no `src` is provided, then to a generic user icon when neither image
|
|
3415
|
-
* nor initials are available.
|
|
3416
|
-
*/
|
|
3417
|
-
class AvatarComponent {
|
|
3418
|
-
src = input(undefined, ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
3419
|
-
alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
|
|
3420
|
-
initials = input(undefined, ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
|
|
3421
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3422
|
-
shape = input('circle', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
3423
|
-
hostClasses = computed(() => ({
|
|
3424
|
-
[`ea-avatar--${this.size()}`]: true,
|
|
3425
|
-
[`ea-avatar--${this.shape()}`]: true,
|
|
3426
|
-
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3427
|
-
showImage = computed(() => !!this.src(), ...(ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []));
|
|
3428
|
-
showInitials = computed(() => !this.src() && !!this.initials(), ...(ngDevMode ? [{ debugName: "showInitials" }] : /* istanbul ignore next */ []));
|
|
3429
|
-
showFallback = computed(() => !this.src() && !this.initials(), ...(ngDevMode ? [{ debugName: "showFallback" }] : /* istanbul ignore next */ []));
|
|
3430
|
-
handleImageError(event) {
|
|
3431
|
-
event.target.style.display = 'none';
|
|
3432
|
-
}
|
|
3433
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3434
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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;width:var(--ea-avatar-size, 2.5rem);height:var(--ea-avatar-size, 2.5rem);background-color:var(--color-bg-emphasis);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{--ea-avatar-size: 1.5rem}.ea-avatar--sm{--ea-avatar-size: 2rem}.ea-avatar--md{--ea-avatar-size: 2.5rem}.ea-avatar--lg{--ea-avatar-size: 3rem}.ea-avatar--xl{--ea-avatar-size: 4rem}.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{font-size:calc(var(--ea-avatar-size, 2.5rem) * .4);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{font-size:calc(var(--ea-avatar-size, 2.5rem) * .6)}\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 });
|
|
3435
|
-
}
|
|
3436
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AvatarComponent, decorators: [{
|
|
3437
|
-
type: Component,
|
|
3438
|
-
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;width:var(--ea-avatar-size, 2.5rem);height:var(--ea-avatar-size, 2.5rem);background-color:var(--color-bg-emphasis);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{--ea-avatar-size: 1.5rem}.ea-avatar--sm{--ea-avatar-size: 2rem}.ea-avatar--md{--ea-avatar-size: 2.5rem}.ea-avatar--lg{--ea-avatar-size: 3rem}.ea-avatar--xl{--ea-avatar-size: 4rem}.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{font-size:calc(var(--ea-avatar-size, 2.5rem) * .4);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{font-size:calc(var(--ea-avatar-size, 2.5rem) * .6)}\n"] }]
|
|
3439
|
-
}], 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 }] }] } });
|
|
3440
|
-
|
|
3441
|
-
/**
|
|
3442
|
-
* Compact indicator used to communicate status, counts, or labels inline with
|
|
3443
|
-
* surrounding content.
|
|
3444
|
-
*/
|
|
3445
|
-
class BadgeComponent {
|
|
3446
|
-
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3447
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3448
|
-
shape = input('pill', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
3449
|
-
hostClasses = computed(() => ({
|
|
3450
|
-
[`ea-badge--${this.variant()}`]: true,
|
|
3451
|
-
[`ea-badge--${this.size()}`]: true,
|
|
3452
|
-
[`ea-badge--${this.shape()}`]: true,
|
|
3453
|
-
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3454
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3455
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: BadgeComponent, isStandalone: true, selector: "ea-badge", inputs: { variant: { classPropertyName: "variant", publicName: "variant", 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 } }, ngImport: i0, template: "<span\n class=\"ea-badge\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n</span>\n", styles: [".ea-badge{display:inline-flex;align-items:center;gap:.25em;padding:.25em .625em;white-space:nowrap;font-family:var(--font-family-sans);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);border-style:solid;border-width:var(--ea-badge-border-width, 0);border-color:var(--ea-badge-border-color, transparent);border-radius:var(--radius-full)}.ea-badge--xs{font-size:var(--ea-badge-font-size, var(--font-size-2xs))}.ea-badge--sm{font-size:var(--ea-badge-font-size, var(--font-size-xs))}.ea-badge--md{font-size:var(--ea-badge-font-size, var(--font-size-sm))}.ea-badge--lg{font-size:var(--ea-badge-font-size, var(--font-size-md))}.ea-badge--xl{font-size:var(--ea-badge-font-size, var(--font-size-lg))}.ea-badge--default{background-color:var(--ea-badge-background-color, var(--color-bg-muted));color:var(--ea-badge-color, var(--color-text-secondary))}.ea-badge--success{background-color:var(--ea-badge-background-color, var(--color-success-subtle));color:var(--ea-badge-color, var(--color-success-text))}.ea-badge--warning{background-color:var(--ea-badge-background-color, var(--color-warning-subtle));color:var(--ea-badge-color, var(--color-warning-text))}.ea-badge--error{background-color:var(--ea-badge-background-color, var(--color-error-subtle));color:var(--ea-badge-color, var(--color-error-text))}.ea-badge--info{background-color:var(--ea-badge-background-color, var(--color-info-subtle));color:var(--ea-badge-color, var(--color-info-text))}.ea-badge--pin{justify-content:center;box-sizing:border-box;min-width:var(--ea-badge-size, 1.8em);height:var(--ea-badge-size, 1.8em);padding:0 var(--space-1);font-variant-numeric:tabular-nums}.ea-badge--pin.ea-badge--sm{font-size:var(--ea-badge-font-size, 9px)}.ea-badge--pin.ea-badge--md{font-size:var(--ea-badge-font-size, 10px)}.ea-badge--pin.ea-badge--lg{font-size:var(--ea-badge-font-size, 12px)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3456
|
-
}
|
|
3457
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BadgeComponent, decorators: [{
|
|
3458
|
-
type: Component,
|
|
3459
|
-
args: [{ selector: 'ea-badge', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<span\n class=\"ea-badge\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n</span>\n", styles: [".ea-badge{display:inline-flex;align-items:center;gap:.25em;padding:.25em .625em;white-space:nowrap;font-family:var(--font-family-sans);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);border-style:solid;border-width:var(--ea-badge-border-width, 0);border-color:var(--ea-badge-border-color, transparent);border-radius:var(--radius-full)}.ea-badge--xs{font-size:var(--ea-badge-font-size, var(--font-size-2xs))}.ea-badge--sm{font-size:var(--ea-badge-font-size, var(--font-size-xs))}.ea-badge--md{font-size:var(--ea-badge-font-size, var(--font-size-sm))}.ea-badge--lg{font-size:var(--ea-badge-font-size, var(--font-size-md))}.ea-badge--xl{font-size:var(--ea-badge-font-size, var(--font-size-lg))}.ea-badge--default{background-color:var(--ea-badge-background-color, var(--color-bg-muted));color:var(--ea-badge-color, var(--color-text-secondary))}.ea-badge--success{background-color:var(--ea-badge-background-color, var(--color-success-subtle));color:var(--ea-badge-color, var(--color-success-text))}.ea-badge--warning{background-color:var(--ea-badge-background-color, var(--color-warning-subtle));color:var(--ea-badge-color, var(--color-warning-text))}.ea-badge--error{background-color:var(--ea-badge-background-color, var(--color-error-subtle));color:var(--ea-badge-color, var(--color-error-text))}.ea-badge--info{background-color:var(--ea-badge-background-color, var(--color-info-subtle));color:var(--ea-badge-color, var(--color-info-text))}.ea-badge--pin{justify-content:center;box-sizing:border-box;min-width:var(--ea-badge-size, 1.8em);height:var(--ea-badge-size, 1.8em);padding:0 var(--space-1);font-variant-numeric:tabular-nums}.ea-badge--pin.ea-badge--sm{font-size:var(--ea-badge-font-size, 9px)}.ea-badge--pin.ea-badge--md{font-size:var(--ea-badge-font-size, 10px)}.ea-badge--pin.ea-badge--lg{font-size:var(--ea-badge-font-size, 12px)}\n"] }]
|
|
3460
|
-
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }] } });
|
|
3461
|
-
|
|
3462
|
-
class ChevronRightIconComponent extends IconComponentBase {
|
|
3463
|
-
static slug = 'chevron-right';
|
|
3464
|
-
static category = 'feather';
|
|
3465
|
-
static tags = [
|
|
3466
|
-
'chevron-right',
|
|
3467
|
-
'chevron',
|
|
3468
|
-
'right',
|
|
3469
|
-
'arrow',
|
|
3470
|
-
'forward',
|
|
3471
|
-
'next',
|
|
3472
|
-
'droite',
|
|
3473
|
-
'derecha',
|
|
3474
|
-
'δεξιά',
|
|
3475
|
-
'prawo',
|
|
3476
|
-
];
|
|
3477
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChevronRightIconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3478
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: ChevronRightIconComponent, isStandalone: true, selector: "ea-icon-chevron-right", usesInheritance: true, ngImport: i0, template: `
|
|
3479
|
-
<svg
|
|
3480
|
-
viewBox="0 0 24 24"
|
|
3481
|
-
fill="none"
|
|
3482
|
-
stroke="currentColor"
|
|
3483
|
-
[attr.stroke-width]="strokeWidth()"
|
|
3484
|
-
stroke-linecap="round"
|
|
3485
|
-
stroke-linejoin="round"
|
|
3486
|
-
aria-hidden="true"
|
|
3487
|
-
width="100%"
|
|
3488
|
-
height="100%">
|
|
3489
|
-
<polyline points="9 18 15 12 9 6" />
|
|
3490
|
-
</svg>
|
|
3491
|
-
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3492
|
-
}
|
|
3493
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChevronRightIconComponent, decorators: [{
|
|
3494
|
-
type: Component,
|
|
3495
|
-
args: [{
|
|
3496
|
-
selector: 'ea-icon-chevron-right',
|
|
3497
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3498
|
-
template: `
|
|
3499
|
-
<svg
|
|
3500
|
-
viewBox="0 0 24 24"
|
|
3501
|
-
fill="none"
|
|
3502
|
-
stroke="currentColor"
|
|
3503
|
-
[attr.stroke-width]="strokeWidth()"
|
|
3504
|
-
stroke-linecap="round"
|
|
3505
|
-
stroke-linejoin="round"
|
|
3506
|
-
aria-hidden="true"
|
|
3507
|
-
width="100%"
|
|
3508
|
-
height="100%">
|
|
3509
|
-
<polyline points="9 18 15 12 9 6" />
|
|
3510
|
-
</svg>
|
|
3511
|
-
`,
|
|
3512
|
-
}]
|
|
3513
|
-
}] });
|
|
3514
|
-
|
|
3515
|
-
/**
|
|
3516
|
-
* Navigation trail that shows the user's location within a hierarchy. Items
|
|
3517
|
-
* with an `href` render as links, others render as buttons; the final item is
|
|
3518
|
-
* always treated as the current page and is non-interactive.
|
|
3519
|
-
*/
|
|
3520
|
-
class BreadcrumbsComponent {
|
|
3521
|
-
i18n = inject(EagamiI18nService);
|
|
3522
|
-
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
3523
|
-
separator = input('chevron', ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
|
|
3524
|
-
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
3525
|
-
/** Fires when a non-disabled, non-final breadcrumb is activated. */
|
|
3526
|
-
clicked = output();
|
|
3527
|
-
/** Accessible label for the breadcrumb nav, falling back to the active locale. */
|
|
3528
|
-
resolvedAriaLabel = computed(() => this.ariaLabel() ?? this.i18n.messages().breadcrumbs.label, ...(ngDevMode ? [{ debugName: "resolvedAriaLabel" }] : /* istanbul ignore next */ []));
|
|
3529
|
-
isLast(index) {
|
|
3530
|
-
return index === this.items().length - 1;
|
|
3531
|
-
}
|
|
3532
|
-
handleClick(item, index, event) {
|
|
3533
|
-
if (item.disabled || this.isLast(index)) {
|
|
3534
|
-
event.preventDefault();
|
|
3535
|
-
return;
|
|
3536
|
-
}
|
|
3537
|
-
this.clicked.emit({ item, index, event });
|
|
3538
|
-
}
|
|
3539
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BreadcrumbsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3540
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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]=\"resolvedAriaLabel()\">\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 });
|
|
3541
|
-
}
|
|
3542
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BreadcrumbsComponent, decorators: [{
|
|
3543
|
-
type: Component,
|
|
3544
|
-
args: [{ selector: 'ea-breadcrumbs', imports: [ChevronRightIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<nav\n class=\"ea-breadcrumbs\"\n [attr.aria-label]=\"resolvedAriaLabel()\">\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"] }]
|
|
3545
|
-
}], 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"] }] } });
|
|
3546
|
-
|
|
3547
|
-
/**
|
|
3548
|
-
* Standard action button supporting primary, secondary, ghost, and danger
|
|
3549
|
-
* variants. Includes a loading state that swaps the label for a spinner while
|
|
3550
|
-
* preserving the rendered width.
|
|
3551
|
-
*/
|
|
3552
|
-
class ButtonComponent {
|
|
3553
|
-
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3554
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3555
|
-
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
3556
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3557
|
-
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
3558
|
-
fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : /* istanbul ignore next */ []));
|
|
3559
|
-
/** Optional icon component rendered to the left of the label. */
|
|
3560
|
-
icon = input(undefined, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
3561
|
-
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
3562
|
-
ariaCurrent = input(undefined, { ...(ngDevMode ? { debugName: "ariaCurrent" } : /* istanbul ignore next */ {}), alias: 'aria-current' });
|
|
3563
|
-
/** Fires when the button is activated; suppressed while disabled or loading. */
|
|
3564
|
-
clicked = output();
|
|
3565
|
-
isDisabled = computed(() => this.disabled() || this.loading(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
3566
|
-
hostClasses = computed(() => ({
|
|
3567
|
-
[`ea-button--${this.variant()}`]: true,
|
|
3568
|
-
[`ea-button--${this.size()}`]: true,
|
|
3569
|
-
'ea-button--full-width': this.fullWidth(),
|
|
3570
|
-
'ea-button--loading': this.loading(),
|
|
3571
|
-
'ea-button--disabled': this.isDisabled(),
|
|
3572
|
-
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3573
|
-
handleClick(event) {
|
|
3574
|
-
if (this.isDisabled()) {
|
|
3575
|
-
event.preventDefault();
|
|
3576
|
-
return;
|
|
3577
|
-
}
|
|
3578
|
-
this.clicked.emit(event);
|
|
3579
|
-
}
|
|
3580
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3581
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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 }, icon: { classPropertyName: "icon", publicName: "icon", 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 @if (icon(); as iconComponent) {\n <span\n class=\"ea-button__icon\"\n aria-hidden=\"true\">\n <ng-container *ngComponentOutlet=\"iconComponent\" />\n </span>\n }\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [":host{display:inline-flex}.ea-button{display:inline-flex;align-items:center;justify-content:center;gap:.5em;position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;padding:.5em 1em;min-height:2.5em;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--xs{font-size:var(--ea-button-font-size, var(--font-size-xs))}.ea-button--sm{font-size:var(--ea-button-font-size, var(--font-size-sm))}.ea-button--md{font-size:var(--ea-button-font-size, var(--font-size-md))}.ea-button--lg{font-size:var(--ea-button-font-size, var(--font-size-lg))}.ea-button--xl{font-size:var(--ea-button-font-size, var(--font-size-xl))}.ea-button--primary{background-color:var(--ea-button-background-color, var(--color-brand-default));border-color:var(--ea-button-border-color, var(--color-brand-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-brand-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-brand-hover)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-brand-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-brand-active)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--secondary{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, var(--color-border-strong));color:var(--ea-button-color, var(--color-text-primary))}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, transparent);color:var(--ea-button-color, var(--color-text-primary))}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, transparent));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, transparent));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--danger{background-color:var(--ea-button-background-color, var(--color-error-default));border-color:var(--ea-button-border-color, var(--color-error-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)));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:.5em}.ea-button__content--hidden{visibility:hidden}.ea-button__icon{display:inline-flex;align-items:center;flex-shrink:0;font-size:var(--icon-inline-size)}.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"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3582
|
-
}
|
|
3583
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ButtonComponent, decorators: [{
|
|
3584
|
-
type: Component,
|
|
3585
|
-
args: [{ selector: 'ea-button', imports: [NgClass, NgComponentOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
3586
|
-
'[class.ea-button--full-width]': 'fullWidth()',
|
|
3587
|
-
}, 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 @if (icon(); as iconComponent) {\n <span\n class=\"ea-button__icon\"\n aria-hidden=\"true\">\n <ng-container *ngComponentOutlet=\"iconComponent\" />\n </span>\n }\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [":host{display:inline-flex}.ea-button{display:inline-flex;align-items:center;justify-content:center;gap:.5em;position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;padding:.5em 1em;min-height:2.5em;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--xs{font-size:var(--ea-button-font-size, var(--font-size-xs))}.ea-button--sm{font-size:var(--ea-button-font-size, var(--font-size-sm))}.ea-button--md{font-size:var(--ea-button-font-size, var(--font-size-md))}.ea-button--lg{font-size:var(--ea-button-font-size, var(--font-size-lg))}.ea-button--xl{font-size:var(--ea-button-font-size, var(--font-size-xl))}.ea-button--primary{background-color:var(--ea-button-background-color, var(--color-brand-default));border-color:var(--ea-button-border-color, var(--color-brand-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-brand-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-brand-hover)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-brand-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-brand-active)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--secondary{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, var(--color-border-strong));color:var(--ea-button-color, var(--color-text-primary))}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, transparent);color:var(--ea-button-color, var(--color-text-primary))}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, transparent));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, transparent));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--danger{background-color:var(--ea-button-background-color, var(--color-error-default));border-color:var(--ea-button-border-color, var(--color-error-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)));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:.5em}.ea-button__content--hidden{visibility:hidden}.ea-button__icon{display:inline-flex;align-items:center;flex-shrink:0;font-size:var(--icon-inline-size)}.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"] }]
|
|
3588
|
-
}], 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 }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", 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"] }] } });
|
|
3618
|
+
UploadIconComponent,
|
|
3619
|
+
], 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 [attr.aria-label]=\"i18n.messages().avatarEditor.upload\"\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\">\n {{ i18n.messages().avatarEditor.dropzone }}\n </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 [attr.aria-label]=\"i18n.messages().avatarEditor.canvas\"\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\n class=\"ea-avatar-editor__canvas-overlay\"\n [class.ea-avatar-editor__canvas-overlay--on-light]=\"!isImageDark()\">\n <ea-icon-camera class=\"ea-avatar-editor__overlay-icon\" />\n <span>{{ i18n.messages().avatarEditor.change }}</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]=\"i18n.messages().avatarEditor.revert\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.revert\"\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]=\"i18n.messages().avatarEditor.zoomOut\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomOut\"\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 [attr.aria-label]=\"i18n.messages().avatarEditor.zoom\"\n (input)=\"onZoomInput($event)\" />\n\n <button\n type=\"button\"\n class=\"ea-avatar-editor__icon-btn\"\n [eaTooltip]=\"i18n.messages().avatarEditor.zoomIn\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.zoomIn\"\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]=\"i18n.messages().avatarEditor.remove\"\n [attr.aria-label]=\"i18n.messages().avatarEditor.remove\"\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-state-hover);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--compact .ea-avatar-editor__dropzone{gap:var(--space-1-5);padding:var(--space-3);font-size:.75rem;line-height:1.35}.ea-avatar-editor--compact .ea-avatar-editor__upload-icon{width:24px;height:24px}.ea-avatar-editor--ultra-compact .ea-avatar-editor__dropzone{gap:var(--space-1);padding:var(--space-2);font-size:.625rem;line-height:1.2}.ea-avatar-editor--ultra-compact .ea-avatar-editor__upload-icon{width:16px;height:16px}.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);color:var(--color-neutral-0);opacity:0;pointer-events:none;transition:opacity var(--duration-fast) var(--easing-default),color var(--duration-fast) var(--easing-default)}.ea-avatar-editor__canvas-overlay--on-light{color:var(--color-neutral-950)}.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"] }]
|
|
3620
|
+
}], 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"] }] } });
|
|
3589
3621
|
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
'
|
|
3602
|
-
'
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3622
|
+
class UserIconComponent extends IconComponentBase {
|
|
3623
|
+
static slug = 'user';
|
|
3624
|
+
static category = 'feather';
|
|
3625
|
+
static tags = [
|
|
3626
|
+
'user',
|
|
3627
|
+
'person',
|
|
3628
|
+
'profile',
|
|
3629
|
+
'account',
|
|
3630
|
+
'avatar',
|
|
3631
|
+
'utilisateur',
|
|
3632
|
+
'personne',
|
|
3633
|
+
'usuario',
|
|
3634
|
+
'persona',
|
|
3635
|
+
'χρήστης',
|
|
3636
|
+
'άτομο',
|
|
3637
|
+
'użytkownik',
|
|
3638
|
+
'osoba',
|
|
3639
|
+
];
|
|
3640
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UserIconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3641
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: UserIconComponent, isStandalone: true, selector: "ea-icon-user", usesInheritance: true, ngImport: i0, template: `
|
|
3642
|
+
<svg
|
|
3643
|
+
viewBox="0 0 24 24"
|
|
3644
|
+
fill="none"
|
|
3645
|
+
stroke="currentColor"
|
|
3646
|
+
[attr.stroke-width]="strokeWidth()"
|
|
3647
|
+
stroke-linecap="round"
|
|
3648
|
+
stroke-linejoin="round"
|
|
3649
|
+
aria-hidden="true"
|
|
3650
|
+
width="100%"
|
|
3651
|
+
height="100%">
|
|
3652
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
3653
|
+
<circle
|
|
3654
|
+
cx="12"
|
|
3655
|
+
cy="7"
|
|
3656
|
+
r="4" />
|
|
3657
|
+
</svg>
|
|
3658
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3606
3659
|
}
|
|
3607
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
3660
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: UserIconComponent, decorators: [{
|
|
3608
3661
|
type: Component,
|
|
3609
|
-
args: [{
|
|
3610
|
-
|
|
3662
|
+
args: [{
|
|
3663
|
+
selector: 'ea-icon-user',
|
|
3664
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3665
|
+
template: `
|
|
3666
|
+
<svg
|
|
3667
|
+
viewBox="0 0 24 24"
|
|
3668
|
+
fill="none"
|
|
3669
|
+
stroke="currentColor"
|
|
3670
|
+
[attr.stroke-width]="strokeWidth()"
|
|
3671
|
+
stroke-linecap="round"
|
|
3672
|
+
stroke-linejoin="round"
|
|
3673
|
+
aria-hidden="true"
|
|
3674
|
+
width="100%"
|
|
3675
|
+
height="100%">
|
|
3676
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
3677
|
+
<circle
|
|
3678
|
+
cx="12"
|
|
3679
|
+
cy="7"
|
|
3680
|
+
r="4" />
|
|
3681
|
+
</svg>
|
|
3682
|
+
`,
|
|
3683
|
+
}]
|
|
3684
|
+
}] });
|
|
3611
3685
|
|
|
3612
3686
|
/**
|
|
3613
|
-
*
|
|
3614
|
-
* `
|
|
3615
|
-
*
|
|
3616
|
-
* `--ea-card-shadow` CSS custom property.
|
|
3687
|
+
* Compact image used to represent a user or entity. Falls back to initials
|
|
3688
|
+
* when no `src` is provided, then to a generic user icon when neither image
|
|
3689
|
+
* nor initials are available.
|
|
3617
3690
|
*/
|
|
3618
|
-
class
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3691
|
+
class AvatarComponent {
|
|
3692
|
+
src = input(undefined, ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
3693
|
+
alt = input('', ...(ngDevMode ? [{ debugName: "alt" }] : /* istanbul ignore next */ []));
|
|
3694
|
+
initials = input(undefined, ...(ngDevMode ? [{ debugName: "initials" }] : /* istanbul ignore next */ []));
|
|
3695
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3696
|
+
shape = input('circle', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
3624
3697
|
hostClasses = computed(() => ({
|
|
3625
|
-
[`ea-
|
|
3626
|
-
[`ea-
|
|
3627
|
-
'ea-card--full-width': this.fullWidth(),
|
|
3698
|
+
[`ea-avatar--${this.size()}`]: true,
|
|
3699
|
+
[`ea-avatar--${this.shape()}`]: true,
|
|
3628
3700
|
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3629
|
-
|
|
3630
|
-
|
|
3701
|
+
showImage = computed(() => !!this.src(), ...(ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []));
|
|
3702
|
+
showInitials = computed(() => !this.src() && !!this.initials(), ...(ngDevMode ? [{ debugName: "showInitials" }] : /* istanbul ignore next */ []));
|
|
3703
|
+
showFallback = computed(() => !this.src() && !this.initials(), ...(ngDevMode ? [{ debugName: "showFallback" }] : /* istanbul ignore next */ []));
|
|
3704
|
+
handleImageError(event) {
|
|
3705
|
+
event.target.style.display = 'none';
|
|
3706
|
+
}
|
|
3707
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3708
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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;width:var(--ea-avatar-size, 2.5rem);height:var(--ea-avatar-size, 2.5rem);background-color:var(--color-bg-emphasis);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{--ea-avatar-size: 1.5rem}.ea-avatar--sm{--ea-avatar-size: 2rem}.ea-avatar--md{--ea-avatar-size: 2.5rem}.ea-avatar--lg{--ea-avatar-size: 3rem}.ea-avatar--xl{--ea-avatar-size: 4rem}.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{font-size:calc(var(--ea-avatar-size, 2.5rem) * .4);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{font-size:calc(var(--ea-avatar-size, 2.5rem) * .6)}\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 });
|
|
3631
3709
|
}
|
|
3632
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
3710
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: AvatarComponent, decorators: [{
|
|
3633
3711
|
type: Component,
|
|
3634
|
-
args: [{ selector: 'ea-
|
|
3635
|
-
}], propDecorators: {
|
|
3712
|
+
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;width:var(--ea-avatar-size, 2.5rem);height:var(--ea-avatar-size, 2.5rem);background-color:var(--color-bg-emphasis);color:var(--color-text-secondary);font-family:var(--font-family-sans);font-weight:var(--font-weight-medium)}.ea-avatar--xs{--ea-avatar-size: 1.5rem}.ea-avatar--sm{--ea-avatar-size: 2rem}.ea-avatar--md{--ea-avatar-size: 2.5rem}.ea-avatar--lg{--ea-avatar-size: 3rem}.ea-avatar--xl{--ea-avatar-size: 4rem}.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{font-size:calc(var(--ea-avatar-size, 2.5rem) * .4);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide);line-height:var(--line-height-none)}.ea-avatar__fallback{font-size:calc(var(--ea-avatar-size, 2.5rem) * .6)}\n"] }]
|
|
3713
|
+
}], 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 }] }] } });
|
|
3636
3714
|
|
|
3637
3715
|
/**
|
|
3638
|
-
*
|
|
3639
|
-
*
|
|
3640
|
-
* Angular forms via `ControlValueAccessor`.
|
|
3716
|
+
* Compact indicator used to communicate status, counts, or labels inline with
|
|
3717
|
+
* surrounding content.
|
|
3641
3718
|
*/
|
|
3642
|
-
class
|
|
3643
|
-
|
|
3644
|
-
/**
|
|
3645
|
-
* Optional supplementary value shown immediately after the label, dimmed
|
|
3646
|
-
* to the tertiary text token. Renders inside the same `<span>` as the
|
|
3647
|
-
* label so it shares the label's exact baseline and font metrics, keeping
|
|
3648
|
-
* "Inbox 42" / "Brand (30)" patterns aligned without a sibling element
|
|
3649
|
-
* fighting flex / inline-flow centring at the consumer's call site.
|
|
3650
|
-
*/
|
|
3651
|
-
count = input(undefined, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
3652
|
-
hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
3653
|
-
errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
|
|
3719
|
+
class BadgeComponent {
|
|
3720
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3654
3721
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3655
|
-
|
|
3656
|
-
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
3657
|
-
indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
|
|
3658
|
-
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
3659
|
-
id = input(uniqueId('ea-checkbox'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
3660
|
-
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
3661
|
-
/** Fires with the new checked state whenever the user toggles the checkbox. */
|
|
3662
|
-
changed = output();
|
|
3663
|
-
_formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
|
|
3664
|
-
isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
3665
|
-
hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
3666
|
-
showError = this.hasError;
|
|
3667
|
-
showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
|
|
3722
|
+
shape = input('pill', ...(ngDevMode ? [{ debugName: "shape" }] : /* istanbul ignore next */ []));
|
|
3668
3723
|
hostClasses = computed(() => ({
|
|
3669
|
-
[`ea-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
'ea-checkbox--indeterminate': this.indeterminate(),
|
|
3673
|
-
'ea-checkbox--error': this.hasError(),
|
|
3724
|
+
[`ea-badge--${this.variant()}`]: true,
|
|
3725
|
+
[`ea-badge--${this.size()}`]: true,
|
|
3726
|
+
[`ea-badge--${this.shape()}`]: true,
|
|
3674
3727
|
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
writeValue(val) {
|
|
3678
|
-
this.checked.set(!!val);
|
|
3679
|
-
}
|
|
3680
|
-
registerOnChange(fn) {
|
|
3681
|
-
this.onChange = fn;
|
|
3682
|
-
}
|
|
3683
|
-
registerOnTouched(fn) {
|
|
3684
|
-
this.onTouched = fn;
|
|
3685
|
-
}
|
|
3686
|
-
setDisabledState(isDisabled) {
|
|
3687
|
-
this._formDisabled.set(isDisabled);
|
|
3688
|
-
}
|
|
3689
|
-
handleChange() {
|
|
3690
|
-
if (this.isDisabled()) {
|
|
3691
|
-
return;
|
|
3692
|
-
}
|
|
3693
|
-
const newValue = !this.checked();
|
|
3694
|
-
this.checked.set(newValue);
|
|
3695
|
-
this.onChange(newValue);
|
|
3696
|
-
this.onTouched();
|
|
3697
|
-
this.changed.emit(newValue);
|
|
3698
|
-
}
|
|
3699
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3700
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: CheckboxComponent, isStandalone: true, selector: "ea-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", 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: [
|
|
3701
|
-
{
|
|
3702
|
-
provide: NG_VALUE_ACCESSOR,
|
|
3703
|
-
useExisting: forwardRef(() => CheckboxComponent),
|
|
3704
|
-
multi: true,
|
|
3705
|
-
},
|
|
3706
|
-
], 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 @if (count() !== undefined && count() !== null) {\n <span class=\"ea-checkbox__count\">{{ count() }}</span>\n }\n </span>\n }\n </label>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"showError() ? errorMsg() : null\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [":host{display:inline-flex;vertical-align:middle;line-height:1}.ea-checkbox-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-checkbox{display:inline-flex;align-items:center;gap:.5em;cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--xs{font-size:var(--font-size-xs)}.ea-checkbox--sm{font-size:var(--font-size-sm)}.ea-checkbox--md{font-size:var(--font-size-md)}.ea-checkbox--lg{font-size:var(--font-size-lg)}.ea-checkbox--xl{font-size:var(--font-size-xl)}.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;width:1.25em;height:1.25em;border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-sm);background-color:var(--color-bg-base);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__count{margin-left:.25em;color:var(--color-text-tertiary)}.ea-checkbox--error .ea-checkbox__box{border-color:var(--color-error-default)}\n"], dependencies: [{ kind: "component", type: FieldMessagesComponent, selector: "ea-field-messages", inputs: ["id", "error", "hint"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3728
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3729
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.16", type: BadgeComponent, isStandalone: true, selector: "ea-badge", inputs: { variant: { classPropertyName: "variant", publicName: "variant", 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 } }, ngImport: i0, template: "<span\n class=\"ea-badge\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n</span>\n", styles: [".ea-badge{display:inline-flex;align-items:center;gap:.25em;padding:.25em .625em;white-space:nowrap;font-family:var(--font-family-sans);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);border-style:solid;border-width:var(--ea-badge-border-width, 0);border-color:var(--ea-badge-border-color, transparent);border-radius:var(--radius-full)}.ea-badge--xs{font-size:var(--ea-badge-font-size, var(--font-size-2xs))}.ea-badge--sm{font-size:var(--ea-badge-font-size, var(--font-size-xs))}.ea-badge--md{font-size:var(--ea-badge-font-size, var(--font-size-sm))}.ea-badge--lg{font-size:var(--ea-badge-font-size, var(--font-size-md))}.ea-badge--xl{font-size:var(--ea-badge-font-size, var(--font-size-lg))}.ea-badge--default{background-color:var(--ea-badge-background-color, var(--color-bg-muted));color:var(--ea-badge-color, var(--color-text-secondary))}.ea-badge--success{background-color:var(--ea-badge-background-color, var(--color-success-subtle));color:var(--ea-badge-color, var(--color-success-text))}.ea-badge--warning{background-color:var(--ea-badge-background-color, var(--color-warning-subtle));color:var(--ea-badge-color, var(--color-warning-text))}.ea-badge--error{background-color:var(--ea-badge-background-color, var(--color-error-subtle));color:var(--ea-badge-color, var(--color-error-text))}.ea-badge--info{background-color:var(--ea-badge-background-color, var(--color-info-subtle));color:var(--ea-badge-color, var(--color-info-text))}.ea-badge--pin{justify-content:center;box-sizing:border-box;min-width:var(--ea-badge-size, 1.8em);height:var(--ea-badge-size, 1.8em);padding:0 var(--space-1);font-variant-numeric:tabular-nums}.ea-badge--pin.ea-badge--sm{font-size:var(--ea-badge-font-size, 9px)}.ea-badge--pin.ea-badge--md{font-size:var(--ea-badge-font-size, 10px)}.ea-badge--pin.ea-badge--lg{font-size:var(--ea-badge-font-size, 12px)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3707
3730
|
}
|
|
3708
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
3731
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BadgeComponent, decorators: [{
|
|
3709
3732
|
type: Component,
|
|
3710
|
-
args: [{ selector: 'ea-
|
|
3711
|
-
|
|
3712
|
-
provide: NG_VALUE_ACCESSOR,
|
|
3713
|
-
useExisting: forwardRef(() => CheckboxComponent),
|
|
3714
|
-
multi: true,
|
|
3715
|
-
},
|
|
3716
|
-
], 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 @if (count() !== undefined && count() !== null) {\n <span class=\"ea-checkbox__count\">{{ count() }}</span>\n }\n </span>\n }\n </label>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"showError() ? errorMsg() : null\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [":host{display:inline-flex;vertical-align:middle;line-height:1}.ea-checkbox-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-checkbox{display:inline-flex;align-items:center;gap:.5em;cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--xs{font-size:var(--font-size-xs)}.ea-checkbox--sm{font-size:var(--font-size-sm)}.ea-checkbox--md{font-size:var(--font-size-md)}.ea-checkbox--lg{font-size:var(--font-size-lg)}.ea-checkbox--xl{font-size:var(--font-size-xl)}.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;width:1.25em;height:1.25em;border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-sm);background-color:var(--color-bg-base);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__count{margin-left:.25em;color:var(--color-text-tertiary)}.ea-checkbox--error .ea-checkbox__box{border-color:var(--color-error-default)}\n"] }]
|
|
3717
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", 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"] }] } });
|
|
3733
|
+
args: [{ selector: 'ea-badge', imports: [NgClass], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<span\n class=\"ea-badge\"\n [ngClass]=\"hostClasses()\">\n <ng-content />\n</span>\n", styles: [".ea-badge{display:inline-flex;align-items:center;gap:.25em;padding:.25em .625em;white-space:nowrap;font-family:var(--font-family-sans);font-weight:var(--font-weight-medium);line-height:var(--line-height-none);border-style:solid;border-width:var(--ea-badge-border-width, 0);border-color:var(--ea-badge-border-color, transparent);border-radius:var(--radius-full)}.ea-badge--xs{font-size:var(--ea-badge-font-size, var(--font-size-2xs))}.ea-badge--sm{font-size:var(--ea-badge-font-size, var(--font-size-xs))}.ea-badge--md{font-size:var(--ea-badge-font-size, var(--font-size-sm))}.ea-badge--lg{font-size:var(--ea-badge-font-size, var(--font-size-md))}.ea-badge--xl{font-size:var(--ea-badge-font-size, var(--font-size-lg))}.ea-badge--default{background-color:var(--ea-badge-background-color, var(--color-bg-muted));color:var(--ea-badge-color, var(--color-text-secondary))}.ea-badge--success{background-color:var(--ea-badge-background-color, var(--color-success-subtle));color:var(--ea-badge-color, var(--color-success-text))}.ea-badge--warning{background-color:var(--ea-badge-background-color, var(--color-warning-subtle));color:var(--ea-badge-color, var(--color-warning-text))}.ea-badge--error{background-color:var(--ea-badge-background-color, var(--color-error-subtle));color:var(--ea-badge-color, var(--color-error-text))}.ea-badge--info{background-color:var(--ea-badge-background-color, var(--color-info-subtle));color:var(--ea-badge-color, var(--color-info-text))}.ea-badge--pin{justify-content:center;box-sizing:border-box;min-width:var(--ea-badge-size, 1.8em);height:var(--ea-badge-size, 1.8em);padding:0 var(--space-1);font-variant-numeric:tabular-nums}.ea-badge--pin.ea-badge--sm{font-size:var(--ea-badge-font-size, 9px)}.ea-badge--pin.ea-badge--md{font-size:var(--ea-badge-font-size, 10px)}.ea-badge--pin.ea-badge--lg{font-size:var(--ea-badge-font-size, 12px)}\n"] }]
|
|
3734
|
+
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }] } });
|
|
3718
3735
|
|
|
3719
|
-
class
|
|
3720
|
-
static slug = '
|
|
3736
|
+
class ChevronRightIconComponent extends IconComponentBase {
|
|
3737
|
+
static slug = 'chevron-right';
|
|
3721
3738
|
static category = 'feather';
|
|
3722
3739
|
static tags = [
|
|
3723
|
-
'
|
|
3724
|
-
'
|
|
3725
|
-
'
|
|
3726
|
-
'
|
|
3727
|
-
'
|
|
3728
|
-
'
|
|
3729
|
-
'
|
|
3730
|
-
'
|
|
3731
|
-
'
|
|
3732
|
-
'
|
|
3733
|
-
'βρες',
|
|
3734
|
-
'szukaj',
|
|
3735
|
-
'wyszukaj',
|
|
3740
|
+
'chevron-right',
|
|
3741
|
+
'chevron',
|
|
3742
|
+
'right',
|
|
3743
|
+
'arrow',
|
|
3744
|
+
'forward',
|
|
3745
|
+
'next',
|
|
3746
|
+
'droite',
|
|
3747
|
+
'derecha',
|
|
3748
|
+
'δεξιά',
|
|
3749
|
+
'prawo',
|
|
3736
3750
|
];
|
|
3737
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
3738
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type:
|
|
3751
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChevronRightIconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
3752
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: ChevronRightIconComponent, isStandalone: true, selector: "ea-icon-chevron-right", usesInheritance: true, ngImport: i0, template: `
|
|
3739
3753
|
<svg
|
|
3740
3754
|
viewBox="0 0 24 24"
|
|
3741
3755
|
fill="none"
|
|
@@ -3746,18 +3760,14 @@ class SearchIconComponent extends IconComponentBase {
|
|
|
3746
3760
|
aria-hidden="true"
|
|
3747
3761
|
width="100%"
|
|
3748
3762
|
height="100%">
|
|
3749
|
-
<
|
|
3750
|
-
cx="11"
|
|
3751
|
-
cy="11"
|
|
3752
|
-
r="8" />
|
|
3753
|
-
<path d="m21 21-4.35-4.35" />
|
|
3763
|
+
<polyline points="9 18 15 12 9 6" />
|
|
3754
3764
|
</svg>
|
|
3755
3765
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3756
3766
|
}
|
|
3757
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
3767
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ChevronRightIconComponent, decorators: [{
|
|
3758
3768
|
type: Component,
|
|
3759
3769
|
args: [{
|
|
3760
|
-
selector: 'ea-icon-
|
|
3770
|
+
selector: 'ea-icon-chevron-right',
|
|
3761
3771
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
3762
3772
|
template: `
|
|
3763
3773
|
<svg
|
|
@@ -3770,298 +3780,236 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
3770
3780
|
aria-hidden="true"
|
|
3771
3781
|
width="100%"
|
|
3772
3782
|
height="100%">
|
|
3773
|
-
<
|
|
3774
|
-
cx="11"
|
|
3775
|
-
cy="11"
|
|
3776
|
-
r="8" />
|
|
3777
|
-
<path d="m21 21-4.35-4.35" />
|
|
3783
|
+
<polyline points="9 18 15 12 9 6" />
|
|
3778
3784
|
</svg>
|
|
3779
3785
|
`,
|
|
3780
3786
|
}]
|
|
3781
3787
|
}] });
|
|
3782
3788
|
|
|
3783
3789
|
/**
|
|
3784
|
-
*
|
|
3785
|
-
*
|
|
3786
|
-
*
|
|
3787
|
-
*
|
|
3788
|
-
* The component does NOT bind global shortcuts; the consumer wires up
|
|
3789
|
-
* whatever trigger they want and toggles `[(open)]`. Each selected command
|
|
3790
|
-
* is emitted via `(execute)`; the palette closes automatically afterwards.
|
|
3791
|
-
*
|
|
3792
|
-
* Items can be grouped via the `group` field; ungrouped items render first.
|
|
3793
|
-
* The active row is tracked via roving `aria-activedescendant` on the search
|
|
3794
|
-
* input, which is the canonical ARIA combobox-with-listbox pattern.
|
|
3790
|
+
* Navigation trail that shows the user's location within a hierarchy. Items
|
|
3791
|
+
* with an `href` render as links, others render as buttons; the final item is
|
|
3792
|
+
* always treated as the current page and is non-interactive.
|
|
3795
3793
|
*/
|
|
3796
|
-
class
|
|
3794
|
+
class BreadcrumbsComponent {
|
|
3797
3795
|
i18n = inject(EagamiI18nService);
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
query = signal('', ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
3808
|
-
listboxId = uniqueId('ea-command-palette-listbox');
|
|
3809
|
-
/**
|
|
3810
|
-
* Items bucketed by `group`, then flattened back into display order
|
|
3811
|
-
* (ungrouped items first, then each named group). The matching
|
|
3812
|
-
* `filteredItems` array follows this same order so `flatIndex` lines up
|
|
3813
|
-
* one-to-one with what the user sees.
|
|
3814
|
-
*/
|
|
3815
|
-
groupedItems = computed(() => {
|
|
3816
|
-
const q = this.query().trim().toLowerCase();
|
|
3817
|
-
const candidates = this.items().filter(item => {
|
|
3818
|
-
if (item.disabled) {
|
|
3819
|
-
return false;
|
|
3820
|
-
}
|
|
3821
|
-
if (!q) {
|
|
3822
|
-
return true;
|
|
3823
|
-
}
|
|
3824
|
-
const haystack = [item.label, item.description ?? '', ...(item.keywords ?? [])]
|
|
3825
|
-
.join(' ')
|
|
3826
|
-
.toLowerCase();
|
|
3827
|
-
// Match when the query is a prefix of any word in the haystack.
|
|
3828
|
-
// Substring-anywhere matching would surface confusing results (typing
|
|
3829
|
-
// "c" matching "Repla*c*e" via a mid-word character); word-boundary
|
|
3830
|
-
// matching keeps results predictable.
|
|
3831
|
-
return haystack.split(/[\s\-_]+/).some(word => word.startsWith(q));
|
|
3832
|
-
});
|
|
3833
|
-
const buckets = new Map();
|
|
3834
|
-
for (const item of candidates) {
|
|
3835
|
-
const key = item.group ?? '';
|
|
3836
|
-
if (!buckets.has(key)) {
|
|
3837
|
-
buckets.set(key, []);
|
|
3838
|
-
}
|
|
3839
|
-
buckets.get(key).push(item);
|
|
3840
|
-
}
|
|
3841
|
-
const groups = [];
|
|
3842
|
-
let flatIndex = 0;
|
|
3843
|
-
const pushGroup = (group, items) => {
|
|
3844
|
-
groups.push({
|
|
3845
|
-
group,
|
|
3846
|
-
items: items.map(item => ({ item, flatIndex: flatIndex++ })),
|
|
3847
|
-
});
|
|
3848
|
-
};
|
|
3849
|
-
const ungrouped = buckets.get('');
|
|
3850
|
-
if (ungrouped && ungrouped.length > 0) {
|
|
3851
|
-
pushGroup('', ungrouped);
|
|
3852
|
-
}
|
|
3853
|
-
for (const [group, items] of buckets) {
|
|
3854
|
-
if (group !== '') {
|
|
3855
|
-
pushGroup(group, items);
|
|
3856
|
-
}
|
|
3857
|
-
}
|
|
3858
|
-
return groups;
|
|
3859
|
-
}, ...(ngDevMode ? [{ debugName: "groupedItems" }] : /* istanbul ignore next */ []));
|
|
3860
|
-
/**
|
|
3861
|
-
* Flat list of matches in display order. Drives keyboard navigation and
|
|
3862
|
-
* `aria-activedescendant`.
|
|
3863
|
-
*/
|
|
3864
|
-
filteredItems = computed(() => this.groupedItems().flatMap(group => group.items.map(entry => entry.item)), ...(ngDevMode ? [{ debugName: "filteredItems" }] : /* istanbul ignore next */ []));
|
|
3865
|
-
_activeIndex = signal(0, ...(ngDevMode ? [{ debugName: "_activeIndex" }] : /* istanbul ignore next */ []));
|
|
3866
|
-
/**
|
|
3867
|
-
* Tracks what the user last did so the visual highlight only renders when
|
|
3868
|
-
* it actually reflects what a click/Enter would select right now:
|
|
3869
|
-
* - `keyboard`: keyboard nav (or just-opened / just-typed): show the
|
|
3870
|
-
* active item's background so keyboard users see what Enter will pick.
|
|
3871
|
-
* - `mouse`: pointer is moving inside the list: rely on `:hover` for the
|
|
3872
|
-
* visual; skip the active-row background to avoid two highlights.
|
|
3873
|
-
* - `none`: pointer is outside the list and no keyboard nav has happened
|
|
3874
|
-
* since: nothing is highlighted, because nothing on screen is a
|
|
3875
|
-
* next-click target.
|
|
3876
|
-
*/
|
|
3877
|
-
interaction = signal('keyboard', ...(ngDevMode ? [{ debugName: "interaction" }] : /* istanbul ignore next */ []));
|
|
3878
|
-
activeIndex = computed(() => {
|
|
3879
|
-
const max = this.filteredItems().length - 1;
|
|
3880
|
-
if (max < 0) {
|
|
3881
|
-
return -1;
|
|
3882
|
-
}
|
|
3883
|
-
return Math.min(this._activeIndex(), max);
|
|
3884
|
-
}, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
3885
|
-
activeId = computed(() => {
|
|
3886
|
-
const idx = this.activeIndex();
|
|
3887
|
-
if (idx < 0) {
|
|
3888
|
-
return null;
|
|
3889
|
-
}
|
|
3890
|
-
return `ea-command-palette-item-${this.filteredItems()[idx].id}`;
|
|
3891
|
-
}, ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
|
|
3892
|
-
constructor() {
|
|
3893
|
-
/* When the palette opens, focus the search input and reset state. The
|
|
3894
|
-
dialog needs an extra tick to call `showModal()` before the input is
|
|
3895
|
-
focusable, so queue the focus into a microtask. */
|
|
3896
|
-
effect(() => {
|
|
3897
|
-
const isOpen = this.open();
|
|
3898
|
-
const dialog = this.dialogEl()?.nativeElement;
|
|
3899
|
-
if (!dialog) {
|
|
3900
|
-
return;
|
|
3901
|
-
}
|
|
3902
|
-
if (isOpen) {
|
|
3903
|
-
if (!dialog.open) {
|
|
3904
|
-
dialog.showModal?.();
|
|
3905
|
-
}
|
|
3906
|
-
this.query.set('');
|
|
3907
|
-
this._activeIndex.set(0);
|
|
3908
|
-
this.interaction.set('keyboard');
|
|
3909
|
-
queueMicrotask(() => this.searchEl()?.nativeElement.focus());
|
|
3910
|
-
}
|
|
3911
|
-
else if (dialog.open) {
|
|
3912
|
-
dialog.close();
|
|
3913
|
-
}
|
|
3914
|
-
});
|
|
3915
|
-
}
|
|
3916
|
-
itemDomId(item) {
|
|
3917
|
-
return `ea-command-palette-item-${item.id}`;
|
|
3918
|
-
}
|
|
3919
|
-
isActive(flatIndex) {
|
|
3920
|
-
return this.activeIndex() === flatIndex;
|
|
3921
|
-
}
|
|
3922
|
-
/**
|
|
3923
|
-
* Whether the active row should render its highlighted background right
|
|
3924
|
-
* now. False when the pointer is hovering the list (`:hover` handles the
|
|
3925
|
-
* visual) or when the pointer is out of the list entirely (nothing is a
|
|
3926
|
-
* next-click target).
|
|
3927
|
-
*/
|
|
3928
|
-
showActiveHighlight(flatIndex) {
|
|
3929
|
-
return this.interaction() === 'keyboard' && this.isActive(flatIndex);
|
|
3930
|
-
}
|
|
3931
|
-
onQueryInput(event) {
|
|
3932
|
-
this.query.set(event.target.value);
|
|
3933
|
-
this._activeIndex.set(0);
|
|
3934
|
-
// Typing implies keyboard intent; surface the first match so the user
|
|
3935
|
-
// knows what Enter would pick without having to mouse over.
|
|
3936
|
-
this.interaction.set('keyboard');
|
|
3937
|
-
}
|
|
3938
|
-
clearQuery() {
|
|
3939
|
-
this.query.set('');
|
|
3940
|
-
this._activeIndex.set(0);
|
|
3941
|
-
this.interaction.set('keyboard');
|
|
3942
|
-
this.searchEl()?.nativeElement.focus();
|
|
3796
|
+
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
3797
|
+
separator = input('chevron', ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
|
|
3798
|
+
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
3799
|
+
/** Fires when a non-disabled, non-final breadcrumb is activated. */
|
|
3800
|
+
clicked = output();
|
|
3801
|
+
/** Accessible label for the breadcrumb nav, falling back to the active locale. */
|
|
3802
|
+
resolvedAriaLabel = computed(() => this.ariaLabel() ?? this.i18n.messages().breadcrumbs.label, ...(ngDevMode ? [{ debugName: "resolvedAriaLabel" }] : /* istanbul ignore next */ []));
|
|
3803
|
+
isLast(index) {
|
|
3804
|
+
return index === this.items().length - 1;
|
|
3943
3805
|
}
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3806
|
+
handleClick(item, index, event) {
|
|
3807
|
+
if (item.disabled || this.isLast(index)) {
|
|
3808
|
+
event.preventDefault();
|
|
3947
3809
|
return;
|
|
3948
3810
|
}
|
|
3949
|
-
|
|
3950
|
-
case 'ArrowDown': {
|
|
3951
|
-
event.preventDefault();
|
|
3952
|
-
this._activeIndex.set(this.activeIndex() < max ? this.activeIndex() + 1 : 0);
|
|
3953
|
-
this.interaction.set('keyboard');
|
|
3954
|
-
this.scrollActiveIntoView();
|
|
3955
|
-
break;
|
|
3956
|
-
}
|
|
3957
|
-
case 'ArrowUp': {
|
|
3958
|
-
event.preventDefault();
|
|
3959
|
-
this._activeIndex.set(this.activeIndex() > 0 ? this.activeIndex() - 1 : max);
|
|
3960
|
-
this.interaction.set('keyboard');
|
|
3961
|
-
this.scrollActiveIntoView();
|
|
3962
|
-
break;
|
|
3963
|
-
}
|
|
3964
|
-
case 'Home': {
|
|
3965
|
-
event.preventDefault();
|
|
3966
|
-
this._activeIndex.set(0);
|
|
3967
|
-
this.interaction.set('keyboard');
|
|
3968
|
-
this.scrollActiveIntoView();
|
|
3969
|
-
break;
|
|
3970
|
-
}
|
|
3971
|
-
case 'End': {
|
|
3972
|
-
event.preventDefault();
|
|
3973
|
-
this._activeIndex.set(max);
|
|
3974
|
-
this.interaction.set('keyboard');
|
|
3975
|
-
this.scrollActiveIntoView();
|
|
3976
|
-
break;
|
|
3977
|
-
}
|
|
3978
|
-
case 'Enter': {
|
|
3979
|
-
event.preventDefault();
|
|
3980
|
-
const item = this.filteredItems()[this.activeIndex()];
|
|
3981
|
-
if (item) {
|
|
3982
|
-
this.executeItem(item);
|
|
3983
|
-
}
|
|
3984
|
-
break;
|
|
3985
|
-
}
|
|
3986
|
-
}
|
|
3811
|
+
this.clicked.emit({ item, index, event });
|
|
3987
3812
|
}
|
|
3988
|
-
|
|
3989
|
-
if (item.disabled) {
|
|
3813
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BreadcrumbsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3814
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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]=\"resolvedAriaLabel()\">\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 });
|
|
3815
|
+
}
|
|
3816
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: BreadcrumbsComponent, decorators: [{
|
|
3817
|
+
type: Component,
|
|
3818
|
+
args: [{ selector: 'ea-breadcrumbs', imports: [ChevronRightIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<nav\n class=\"ea-breadcrumbs\"\n [attr.aria-label]=\"resolvedAriaLabel()\">\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"] }]
|
|
3819
|
+
}], 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"] }] } });
|
|
3820
|
+
|
|
3821
|
+
/**
|
|
3822
|
+
* Standard action button supporting primary, secondary, ghost, and danger
|
|
3823
|
+
* variants. Includes a loading state that swaps the label for a spinner while
|
|
3824
|
+
* preserving the rendered width.
|
|
3825
|
+
*/
|
|
3826
|
+
class ButtonComponent {
|
|
3827
|
+
variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3828
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3829
|
+
type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
3830
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3831
|
+
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
3832
|
+
fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : /* istanbul ignore next */ []));
|
|
3833
|
+
/** Optional icon component rendered to the left of the label. */
|
|
3834
|
+
icon = input(undefined, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
3835
|
+
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
3836
|
+
ariaCurrent = input(undefined, { ...(ngDevMode ? { debugName: "ariaCurrent" } : /* istanbul ignore next */ {}), alias: 'aria-current' });
|
|
3837
|
+
/** Fires when the button is activated; suppressed while disabled or loading. */
|
|
3838
|
+
clicked = output();
|
|
3839
|
+
isDisabled = computed(() => this.disabled() || this.loading(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
3840
|
+
hostClasses = computed(() => ({
|
|
3841
|
+
[`ea-button--${this.variant()}`]: true,
|
|
3842
|
+
[`ea-button--${this.size()}`]: true,
|
|
3843
|
+
'ea-button--full-width': this.fullWidth(),
|
|
3844
|
+
'ea-button--loading': this.loading(),
|
|
3845
|
+
'ea-button--disabled': this.isDisabled(),
|
|
3846
|
+
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3847
|
+
handleClick(event) {
|
|
3848
|
+
if (this.isDisabled()) {
|
|
3849
|
+
event.preventDefault();
|
|
3990
3850
|
return;
|
|
3991
3851
|
}
|
|
3992
|
-
this.
|
|
3852
|
+
this.clicked.emit(event);
|
|
3993
3853
|
}
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3854
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3855
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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 }, icon: { classPropertyName: "icon", publicName: "icon", 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 @if (icon(); as iconComponent) {\n <span\n class=\"ea-button__icon\"\n aria-hidden=\"true\">\n <ng-container *ngComponentOutlet=\"iconComponent\" />\n </span>\n }\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [":host{display:inline-flex}.ea-button{display:inline-flex;align-items:center;justify-content:center;gap:.5em;position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;padding:.5em 1em;min-height:2.5em;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--xs{font-size:var(--ea-button-font-size, var(--font-size-xs))}.ea-button--sm{font-size:var(--ea-button-font-size, var(--font-size-sm))}.ea-button--md{font-size:var(--ea-button-font-size, var(--font-size-md))}.ea-button--lg{font-size:var(--ea-button-font-size, var(--font-size-lg))}.ea-button--xl{font-size:var(--ea-button-font-size, var(--font-size-xl))}.ea-button--primary{background-color:var(--ea-button-background-color, var(--color-brand-default));border-color:var(--ea-button-border-color, var(--color-brand-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-brand-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-brand-hover)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-brand-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-brand-active)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--secondary{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, var(--color-border-strong));color:var(--ea-button-color, var(--color-text-primary))}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, transparent);color:var(--ea-button-color, var(--color-text-primary))}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, transparent));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, transparent));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--danger{background-color:var(--ea-button-background-color, var(--color-error-default));border-color:var(--ea-button-border-color, var(--color-error-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)));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:.5em}.ea-button__content--hidden{visibility:hidden}.ea-button__icon{display:inline-flex;align-items:center;flex-shrink:0;font-size:var(--icon-inline-size)}.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"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3856
|
+
}
|
|
3857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: ButtonComponent, decorators: [{
|
|
3858
|
+
type: Component,
|
|
3859
|
+
args: [{ selector: 'ea-button', imports: [NgClass, NgComponentOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
3860
|
+
'[class.ea-button--full-width]': 'fullWidth()',
|
|
3861
|
+
}, 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 @if (icon(); as iconComponent) {\n <span\n class=\"ea-button__icon\"\n aria-hidden=\"true\">\n <ng-container *ngComponentOutlet=\"iconComponent\" />\n </span>\n }\n <span class=\"ea-button__label\">\n <ng-content />\n </span>\n <ng-content select=\"[slot=suffix]\" />\n </span>\n</button>\n", styles: [":host{display:inline-flex}.ea-button{display:inline-flex;align-items:center;justify-content:center;gap:.5em;position:relative;white-space:nowrap;-webkit-user-select:none;user-select:none;padding:.5em 1em;min-height:2.5em;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--xs{font-size:var(--ea-button-font-size, var(--font-size-xs))}.ea-button--sm{font-size:var(--ea-button-font-size, var(--font-size-sm))}.ea-button--md{font-size:var(--ea-button-font-size, var(--font-size-md))}.ea-button--lg{font-size:var(--ea-button-font-size, var(--font-size-lg))}.ea-button--xl{font-size:var(--ea-button-font-size, var(--font-size-xl))}.ea-button--primary{background-color:var(--ea-button-background-color, var(--color-brand-default));border-color:var(--ea-button-border-color, var(--color-brand-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--primary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-brand-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-brand-hover)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--primary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-brand-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-brand-active)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--secondary{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, var(--color-border-strong));color:var(--ea-button-color, var(--color-text-primary))}.ea-button--secondary:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--secondary:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-neutral-500)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost{background-color:var(--ea-button-background-color, transparent);border-color:var(--ea-button-border-color, transparent);color:var(--ea-button-color, var(--color-text-primary))}.ea-button--ghost:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-state-hover)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, transparent));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-text-primary)))}.ea-button--ghost:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-state-active)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, transparent));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-text-primary)))}.ea-button--danger{background-color:var(--ea-button-background-color, var(--color-error-default));border-color:var(--ea-button-border-color, var(--color-error-default));color:var(--ea-button-color, var(--color-neutral-0))}.ea-button--danger:hover:not(.ea-button--disabled){background-color:var(--ea-button-background-color-hover, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-hover, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-hover, var(--ea-button-color, var(--color-neutral-0)))}.ea-button--danger:active:not(.ea-button--disabled){background-color:var(--ea-button-background-color-active, var(--ea-button-background-color, var(--color-error-700)));border-color:var(--ea-button-border-color-active, var(--ea-button-border-color, var(--color-error-700)));color:var(--ea-button-color-active, var(--ea-button-color, var(--color-neutral-0)));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:.5em}.ea-button__content--hidden{visibility:hidden}.ea-button__icon{display:inline-flex;align-items:center;flex-shrink:0;font-size:var(--icon-inline-size)}.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"] }]
|
|
3862
|
+
}], 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 }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", 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"] }] } });
|
|
3863
|
+
|
|
3864
|
+
/**
|
|
3865
|
+
* Thin separator used to visually divide content. Renders horizontally by
|
|
3866
|
+
* default and may include an optional centred label (e.g. "or").
|
|
3867
|
+
*/
|
|
3868
|
+
class DividerComponent {
|
|
3869
|
+
orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
3870
|
+
label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
3871
|
+
/** Renders a heavier rule. */
|
|
3872
|
+
thick = input(false, ...(ngDevMode ? [{ debugName: "thick" }] : /* istanbul ignore next */ []));
|
|
3873
|
+
hostClasses = computed(() => ({
|
|
3874
|
+
[`ea-divider--${this.orientation()}`]: true,
|
|
3875
|
+
'ea-divider--with-label': !!this.label(),
|
|
3876
|
+
'ea-divider--thick': this.thick(),
|
|
3877
|
+
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3878
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DividerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3879
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: DividerComponent, isStandalone: true, selector: "ea-divider", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, thick: { classPropertyName: "thick", publicName: "thick", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, 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{--ea-divider-thickness: 1px;flex-shrink:0;border:0;font-family:var(--font-family-sans)}.ea-divider--thick{--ea-divider-thickness: 2px}.ea-divider--horizontal{display:flex;align-items:center;width:100%;height:var(--ea-divider-thickness);background-color:var(--color-divider)}.ea-divider--vertical{display:inline-block;width:var(--ea-divider-thickness);height:1.5em;min-height:1rem;background-color:var(--color-divider)}.ea-divider--vertical.ea-divider--with-label{display:inline-flex;flex-direction:column;align-items:center;width:auto;height:auto;background-color:transparent;gap:var(--space-3)}.ea-divider--vertical.ea-divider--with-label:before,.ea-divider--vertical.ea-divider--with-label:after{content:\"\";flex:1;width:var(--ea-divider-thickness);height:auto;min-height:2em;background-color:var(--color-divider)}.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:var(--ea-divider-thickness);background-color:var(--color-divider)}.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"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3880
|
+
}
|
|
3881
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DividerComponent, decorators: [{
|
|
3882
|
+
type: Component,
|
|
3883
|
+
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{--ea-divider-thickness: 1px;flex-shrink:0;border:0;font-family:var(--font-family-sans)}.ea-divider--thick{--ea-divider-thickness: 2px}.ea-divider--horizontal{display:flex;align-items:center;width:100%;height:var(--ea-divider-thickness);background-color:var(--color-divider)}.ea-divider--vertical{display:inline-block;width:var(--ea-divider-thickness);height:1.5em;min-height:1rem;background-color:var(--color-divider)}.ea-divider--vertical.ea-divider--with-label{display:inline-flex;flex-direction:column;align-items:center;width:auto;height:auto;background-color:transparent;gap:var(--space-3)}.ea-divider--vertical.ea-divider--with-label:before,.ea-divider--vertical.ea-divider--with-label:after{content:\"\";flex:1;width:var(--ea-divider-thickness);height:auto;min-height:2em;background-color:var(--color-divider)}.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:var(--ea-divider-thickness);background-color:var(--color-divider)}.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"] }]
|
|
3884
|
+
}], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], thick: [{ type: i0.Input, args: [{ isSignal: true, alias: "thick", required: false }] }] } });
|
|
3885
|
+
|
|
3886
|
+
/**
|
|
3887
|
+
* Surface for grouping related content. Provides optional `header` and
|
|
3888
|
+
* `footer` content slots and supports elevated, outlined, and filled
|
|
3889
|
+
* variants. The card shadow can be customised per instance via the
|
|
3890
|
+
* `--ea-card-shadow` CSS custom property.
|
|
3891
|
+
*/
|
|
3892
|
+
class CardComponent {
|
|
3893
|
+
variant = input('elevated', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3894
|
+
padding = input('md', ...(ngDevMode ? [{ debugName: "padding" }] : /* istanbul ignore next */ []));
|
|
3895
|
+
fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : /* istanbul ignore next */ []));
|
|
3896
|
+
headerAlign = input('center', ...(ngDevMode ? [{ debugName: "headerAlign" }] : /* istanbul ignore next */ []));
|
|
3897
|
+
headerDivider = input(false, ...(ngDevMode ? [{ debugName: "headerDivider" }] : /* istanbul ignore next */ []));
|
|
3898
|
+
hostClasses = computed(() => ({
|
|
3899
|
+
[`ea-card--${this.variant()}`]: true,
|
|
3900
|
+
[`ea-card--padding-${this.padding()}`]: true,
|
|
3901
|
+
'ea-card--full-width': this.fullWidth(),
|
|
3902
|
+
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3903
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3904
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", 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-width:0;max-width:100%;min-height:0}.ea-card{display:flex;flex-direction:column;min-width:0;max-width:100%;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-elevated);border:var(--border-width-thin) solid var(--color-border-default);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: "component", type: DividerComponent, selector: "ea-divider", inputs: ["orientation", "label", "thick"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3905
|
+
}
|
|
3906
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CardComponent, decorators: [{
|
|
3907
|
+
type: Component,
|
|
3908
|
+
args: [{ selector: 'ea-card', imports: [DividerComponent, NgClass], 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-width:0;max-width:100%;min-height:0}.ea-card{display:flex;flex-direction:column;min-width:0;max-width:100%;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-elevated);border:var(--border-width-thin) solid var(--color-border-default);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"] }]
|
|
3909
|
+
}], 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 }] }] } });
|
|
3910
|
+
|
|
3911
|
+
/**
|
|
3912
|
+
* Boolean form control with support for an indeterminate visual state. Pairs
|
|
3913
|
+
* a visually hidden native input with a custom checkmark and integrates with
|
|
3914
|
+
* Angular forms via `ControlValueAccessor`.
|
|
3915
|
+
*/
|
|
3916
|
+
class CheckboxComponent {
|
|
3917
|
+
label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
3918
|
+
/**
|
|
3919
|
+
* Optional supplementary value shown immediately after the label, dimmed
|
|
3920
|
+
* to the tertiary text token. Renders inside the same `<span>` as the
|
|
3921
|
+
* label so it shares the label's exact baseline and font metrics, keeping
|
|
3922
|
+
* "Inbox 42" / "Brand (30)" patterns aligned without a sibling element
|
|
3923
|
+
* fighting flex / inline-flow centring at the consumer's call site.
|
|
3924
|
+
*/
|
|
3925
|
+
count = input(undefined, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
3926
|
+
hint = input(undefined, ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
3927
|
+
errorMsg = input(undefined, ...(ngDevMode ? [{ debugName: "errorMsg" }] : /* istanbul ignore next */ []));
|
|
3928
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3929
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
3930
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
3931
|
+
indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
|
|
3932
|
+
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
3933
|
+
id = input(uniqueId('ea-checkbox'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
3934
|
+
checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
3935
|
+
/** Fires with the new checked state whenever the user toggles the checkbox. */
|
|
3936
|
+
changed = output();
|
|
3937
|
+
_formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
|
|
3938
|
+
isDisabled = computed(() => this.disabled() || this._formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
3939
|
+
hasError = computed(() => !!this.errorMsg(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
3940
|
+
showError = this.hasError;
|
|
3941
|
+
showHint = computed(() => !!this.hint() && !this.hasError(), ...(ngDevMode ? [{ debugName: "showHint" }] : /* istanbul ignore next */ []));
|
|
3942
|
+
hostClasses = computed(() => ({
|
|
3943
|
+
[`ea-checkbox--${this.size()}`]: true,
|
|
3944
|
+
'ea-checkbox--disabled': this.isDisabled(),
|
|
3945
|
+
'ea-checkbox--checked': this.checked(),
|
|
3946
|
+
'ea-checkbox--indeterminate': this.indeterminate(),
|
|
3947
|
+
'ea-checkbox--error': this.hasError(),
|
|
3948
|
+
}), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
3949
|
+
onChange = () => { };
|
|
3950
|
+
onTouched = () => { };
|
|
3951
|
+
writeValue(val) {
|
|
3952
|
+
this.checked.set(!!val);
|
|
3997
3953
|
}
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
click, so drop the keyboard-highlight too. A subsequent keyboard nav
|
|
4001
|
-
will restore it. */
|
|
4002
|
-
this.interaction.set('none');
|
|
3954
|
+
registerOnChange(fn) {
|
|
3955
|
+
this.onChange = fn;
|
|
4003
3956
|
}
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
the backdrop; clicks inside content bubble up via the panel. So a click
|
|
4007
|
-
whose target IS the dialog element means the user clicked the backdrop. */
|
|
4008
|
-
if (event.target === this.dialogEl()?.nativeElement) {
|
|
4009
|
-
this.open.set(false);
|
|
4010
|
-
}
|
|
3957
|
+
registerOnTouched(fn) {
|
|
3958
|
+
this.onTouched = fn;
|
|
4011
3959
|
}
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
backdrop dispatches `close`. Mirror that back into the `open` model
|
|
4015
|
-
so consumers stay in sync. */
|
|
4016
|
-
if (this.open()) {
|
|
4017
|
-
this.open.set(false);
|
|
4018
|
-
}
|
|
3960
|
+
setDisabledState(isDisabled) {
|
|
3961
|
+
this._formDisabled.set(isDisabled);
|
|
4019
3962
|
}
|
|
4020
|
-
|
|
4021
|
-
if (
|
|
3963
|
+
handleChange() {
|
|
3964
|
+
if (this.isDisabled()) {
|
|
4022
3965
|
return;
|
|
4023
3966
|
}
|
|
4024
|
-
this.
|
|
4025
|
-
this.
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
const id = this.activeId();
|
|
4030
|
-
if (!id) {
|
|
4031
|
-
return;
|
|
4032
|
-
}
|
|
4033
|
-
const el = this.hostEl.nativeElement.querySelector(`#${id}`);
|
|
4034
|
-
el?.scrollIntoView({ block: 'nearest' });
|
|
4035
|
-
});
|
|
3967
|
+
const newValue = !this.checked();
|
|
3968
|
+
this.checked.set(newValue);
|
|
3969
|
+
this.onChange(newValue);
|
|
3970
|
+
this.onTouched();
|
|
3971
|
+
this.changed.emit(newValue);
|
|
4036
3972
|
}
|
|
4037
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
4038
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type:
|
|
3973
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3974
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: CheckboxComponent, isStandalone: true, selector: "ea-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, count: { classPropertyName: "count", publicName: "count", 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: [
|
|
3975
|
+
{
|
|
3976
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3977
|
+
useExisting: forwardRef(() => CheckboxComponent),
|
|
3978
|
+
multi: true,
|
|
3979
|
+
},
|
|
3980
|
+
], 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 @if (count() !== undefined && count() !== null) {\n <span class=\"ea-checkbox__count\">{{ count() }}</span>\n }\n </span>\n }\n </label>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"showError() ? errorMsg() : null\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [":host{display:inline-flex;vertical-align:middle;line-height:1}.ea-checkbox-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-checkbox{display:inline-flex;align-items:center;gap:.5em;cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--xs{font-size:var(--font-size-xs)}.ea-checkbox--sm{font-size:var(--font-size-sm)}.ea-checkbox--md{font-size:var(--font-size-md)}.ea-checkbox--lg{font-size:var(--font-size-lg)}.ea-checkbox--xl{font-size:var(--font-size-xl)}.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;width:1.25em;height:1.25em;border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-sm);background-color:var(--color-bg-base);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__count{margin-left:.25em;color:var(--color-text-tertiary)}.ea-checkbox--error .ea-checkbox__box{border-color:var(--color-error-default)}\n"], dependencies: [{ kind: "component", type: FieldMessagesComponent, selector: "ea-field-messages", inputs: ["id", "error", "hint"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4039
3981
|
}
|
|
4040
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
3982
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CheckboxComponent, decorators: [{
|
|
4041
3983
|
type: Component,
|
|
4042
|
-
args: [{ selector: 'ea-
|
|
4043
|
-
|
|
3984
|
+
args: [{ selector: 'ea-checkbox', imports: [FieldMessagesComponent, NgClass], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
3985
|
+
{
|
|
3986
|
+
provide: NG_VALUE_ACCESSOR,
|
|
3987
|
+
useExisting: forwardRef(() => CheckboxComponent),
|
|
3988
|
+
multi: true,
|
|
3989
|
+
},
|
|
3990
|
+
], 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 @if (count() !== undefined && count() !== null) {\n <span class=\"ea-checkbox__count\">{{ count() }}</span>\n }\n </span>\n }\n </label>\n\n <ea-field-messages\n [id]=\"id()\"\n [error]=\"showError() ? errorMsg() : null\"\n [hint]=\"showHint() ? hint() : null\" />\n</div>\n", styles: [":host{display:inline-flex;vertical-align:middle;line-height:1}.ea-checkbox-field{display:inline-flex;flex-direction:column;gap:var(--space-1-5)}.ea-checkbox{display:inline-flex;align-items:center;gap:.5em;cursor:pointer;-webkit-user-select:none;user-select:none;font-family:var(--font-family-sans);color:var(--color-text-primary)}.ea-checkbox--xs{font-size:var(--font-size-xs)}.ea-checkbox--sm{font-size:var(--font-size-sm)}.ea-checkbox--md{font-size:var(--font-size-md)}.ea-checkbox--lg{font-size:var(--font-size-lg)}.ea-checkbox--xl{font-size:var(--font-size-xl)}.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;width:1.25em;height:1.25em;border:var(--border-width-thin) solid var(--color-border-strong);border-radius:var(--radius-sm);background-color:var(--color-bg-base);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__count{margin-left:.25em;color:var(--color-text-tertiary)}.ea-checkbox--error .ea-checkbox__box{border-color:var(--color-error-default)}\n"] }]
|
|
3991
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", 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"] }] } });
|
|
4044
3992
|
|
|
4045
|
-
class
|
|
4046
|
-
static slug = '
|
|
3993
|
+
class SearchIconComponent extends IconComponentBase {
|
|
3994
|
+
static slug = 'search';
|
|
4047
3995
|
static category = 'feather';
|
|
4048
3996
|
static tags = [
|
|
4049
|
-
'
|
|
4050
|
-
'
|
|
4051
|
-
'
|
|
4052
|
-
'
|
|
4053
|
-
'
|
|
4054
|
-
'
|
|
4055
|
-
'
|
|
4056
|
-
'
|
|
4057
|
-
'
|
|
4058
|
-
'
|
|
4059
|
-
'
|
|
4060
|
-
'
|
|
4061
|
-
'
|
|
3997
|
+
'search',
|
|
3998
|
+
'find',
|
|
3999
|
+
'magnify',
|
|
4000
|
+
'lookup',
|
|
4001
|
+
'query',
|
|
4002
|
+
'recherche',
|
|
4003
|
+
'chercher',
|
|
4004
|
+
'buscar',
|
|
4005
|
+
'búsqueda',
|
|
4006
|
+
'αναζήτηση',
|
|
4007
|
+
'βρες',
|
|
4008
|
+
'szukaj',
|
|
4009
|
+
'wyszukaj',
|
|
4062
4010
|
];
|
|
4063
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
4064
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type:
|
|
4011
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SearchIconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
4012
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: SearchIconComponent, isStandalone: true, selector: "ea-icon-search", usesInheritance: true, ngImport: i0, template: `
|
|
4065
4013
|
<svg
|
|
4066
4014
|
viewBox="0 0 24 24"
|
|
4067
4015
|
fill="none"
|
|
@@ -4072,14 +4020,18 @@ class DropletIconComponent extends IconComponentBase {
|
|
|
4072
4020
|
aria-hidden="true"
|
|
4073
4021
|
width="100%"
|
|
4074
4022
|
height="100%">
|
|
4075
|
-
<
|
|
4023
|
+
<circle
|
|
4024
|
+
cx="11"
|
|
4025
|
+
cy="11"
|
|
4026
|
+
r="8" />
|
|
4027
|
+
<path d="m21 21-4.35-4.35" />
|
|
4076
4028
|
</svg>
|
|
4077
4029
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4078
4030
|
}
|
|
4079
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
4031
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: SearchIconComponent, decorators: [{
|
|
4080
4032
|
type: Component,
|
|
4081
4033
|
args: [{
|
|
4082
|
-
selector: 'ea-icon-
|
|
4034
|
+
selector: 'ea-icon-search',
|
|
4083
4035
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4084
4036
|
template: `
|
|
4085
4037
|
<svg
|
|
@@ -4092,298 +4044,333 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
4092
4044
|
aria-hidden="true"
|
|
4093
4045
|
width="100%"
|
|
4094
4046
|
height="100%">
|
|
4095
|
-
<
|
|
4047
|
+
<circle
|
|
4048
|
+
cx="11"
|
|
4049
|
+
cy="11"
|
|
4050
|
+
r="8" />
|
|
4051
|
+
<path d="m21 21-4.35-4.35" />
|
|
4096
4052
|
</svg>
|
|
4097
4053
|
`,
|
|
4098
4054
|
}]
|
|
4099
4055
|
}] });
|
|
4100
4056
|
|
|
4101
4057
|
/**
|
|
4102
|
-
*
|
|
4103
|
-
*
|
|
4104
|
-
*
|
|
4105
|
-
*
|
|
4106
|
-
* The primitive is intentionally low-level: a parent component drives the
|
|
4107
|
-
* `[open]` state and listens for `(closeRequested)` to mirror it back. Internal
|
|
4108
|
-
* library components (`<ea-menu>`, `<ea-dropdown>`, `<ea-color-picker>`,
|
|
4109
|
-
* `<ea-date-picker>`, `[eaTooltip]`) compose on top of it; downstream apps can
|
|
4110
|
-
* use it directly to build their own popover-based UI.
|
|
4058
|
+
* `<ea-command-palette>` is a search-driven action launcher: a modal dialog
|
|
4059
|
+
* containing a search input and a filtered list of commands. Designed for
|
|
4060
|
+
* `Cmd/Ctrl + K`-style global menus.
|
|
4111
4061
|
*
|
|
4112
|
-
*
|
|
4113
|
-
*
|
|
4114
|
-
*
|
|
4115
|
-
*
|
|
4116
|
-
*
|
|
4117
|
-
*
|
|
4118
|
-
*
|
|
4119
|
-
*/
|
|
4120
|
-
class
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
/** DOM id for the surface so trigger elements can reference it via aria-controls. */
|
|
4134
|
-
surfaceId = input(uniqueId('ea-popover'), ...(ngDevMode ? [{ debugName: "surfaceId" }] : /* istanbul ignore next */ []));
|
|
4062
|
+
* The component does NOT bind global shortcuts; the consumer wires up
|
|
4063
|
+
* whatever trigger they want and toggles `[(open)]`. Each selected command
|
|
4064
|
+
* is emitted via `(execute)`; the palette closes automatically afterwards.
|
|
4065
|
+
*
|
|
4066
|
+
* Items can be grouped via the `group` field; ungrouped items render first.
|
|
4067
|
+
* The active row is tracked via roving `aria-activedescendant` on the search
|
|
4068
|
+
* input, which is the canonical ARIA combobox-with-listbox pattern.
|
|
4069
|
+
*/
|
|
4070
|
+
class CommandPaletteComponent {
|
|
4071
|
+
i18n = inject(EagamiI18nService);
|
|
4072
|
+
hostEl = inject(ElementRef);
|
|
4073
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
4074
|
+
open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
4075
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
4076
|
+
emptyMessage = input('', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
4077
|
+
execute = output();
|
|
4078
|
+
messages = this.i18n.messages;
|
|
4079
|
+
dialogEl = viewChild('dialogEl', ...(ngDevMode ? [{ debugName: "dialogEl" }] : /* istanbul ignore next */ []));
|
|
4080
|
+
searchEl = viewChild('searchEl', ...(ngDevMode ? [{ debugName: "searchEl" }] : /* istanbul ignore next */ []));
|
|
4081
|
+
query = signal('', ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
4082
|
+
listboxId = uniqueId('ea-command-palette-listbox');
|
|
4135
4083
|
/**
|
|
4136
|
-
*
|
|
4137
|
-
*
|
|
4084
|
+
* Items bucketed by `group`, then flattened back into display order
|
|
4085
|
+
* (ungrouped items first, then each named group). The matching
|
|
4086
|
+
* `filteredItems` array follows this same order so `flatIndex` lines up
|
|
4087
|
+
* one-to-one with what the user sees.
|
|
4138
4088
|
*/
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
/** Set the popover's `min-width` to match the anchor's width (dropdown pattern). */
|
|
4145
|
-
matchAnchorWidth = input(false, ...(ngDevMode ? [{ debugName: "matchAnchorWidth" }] : /* istanbul ignore next */ []));
|
|
4146
|
-
/** Close on click outside the popover and the anchor. */
|
|
4147
|
-
closeOnOutsideClick = input(true, ...(ngDevMode ? [{ debugName: "closeOnOutsideClick" }] : /* istanbul ignore next */ []));
|
|
4148
|
-
/** Close on Escape. */
|
|
4149
|
-
closeOnEscape = input(true, ...(ngDevMode ? [{ debugName: "closeOnEscape" }] : /* istanbul ignore next */ []));
|
|
4150
|
-
/** What to do on scroll / resize while open. */
|
|
4151
|
-
scrollBehavior = input('reposition', ...(ngDevMode ? [{ debugName: "scrollBehavior" }] : /* istanbul ignore next */ []));
|
|
4152
|
-
/** Requested close. The parent should mirror this into `[open]`. */
|
|
4153
|
-
closeRequested = output();
|
|
4154
|
-
position = signal(null, ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
4155
|
-
/** True placement after flip, for class-based styling (e.g. arrow direction). */
|
|
4156
|
-
effectivePlacement = computed(() => this.position()?.placement ?? this.placement(), ...(ngDevMode ? [{ debugName: "effectivePlacement" }] : /* istanbul ignore next */ []));
|
|
4157
|
-
/** Latches true once the post-rAF reposition has run, so the surface is
|
|
4158
|
-
* only revealed after its dimensions are guaranteed stable. Reset on close. */
|
|
4159
|
-
stable = signal(false, ...(ngDevMode ? [{ debugName: "stable" }] : /* istanbul ignore next */ []));
|
|
4160
|
-
/** True once the first `reposition()` has resolved a placement on a
|
|
4161
|
-
* laid-out surface. Drives the `--positioned` class. */
|
|
4162
|
-
isPositioned = computed(() => this.open() && this.position() !== null && this.stable(), ...(ngDevMode ? [{ debugName: "isPositioned" }] : /* istanbul ignore next */ []));
|
|
4163
|
-
/** Class list for the surface. Computed in TS so the placement key (with
|
|
4164
|
-
* its interpolated suffix) and the positioned modifier compose cleanly. */
|
|
4165
|
-
surfaceClass = computed(() => `ea-popover__surface ea-popover__surface--${this.effectivePlacement()}${this.isPositioned() ? ' ea-popover__surface--positioned' : ''}`, ...(ngDevMode ? [{ debugName: "surfaceClass" }] : /* istanbul ignore next */ []));
|
|
4166
|
-
/** Inline style applied to the surface element. */
|
|
4167
|
-
surfaceStyle = computed(() => {
|
|
4168
|
-
if (!this.open()) {
|
|
4169
|
-
return { display: 'none' };
|
|
4170
|
-
}
|
|
4171
|
-
const p = this.position();
|
|
4172
|
-
if (!p) {
|
|
4173
|
-
return {};
|
|
4174
|
-
}
|
|
4175
|
-
const style = {
|
|
4176
|
-
top: `${p.top}px`,
|
|
4177
|
-
left: `${p.left}px`,
|
|
4178
|
-
};
|
|
4179
|
-
if (p.width !== undefined) {
|
|
4180
|
-
style['min-width'] = `${p.width}px`;
|
|
4181
|
-
}
|
|
4182
|
-
return style;
|
|
4183
|
-
}, ...(ngDevMode ? [{ debugName: "surfaceStyle" }] : /* istanbul ignore next */ []));
|
|
4184
|
-
constructor() {
|
|
4185
|
-
// Re-measure and reposition whenever the anchor, placement, surface, or
|
|
4186
|
-
// open state changes. Reading `surfaceEl()` here makes it a tracked signal
|
|
4187
|
-
// dependency, so the effect re-runs once Angular has rendered the `@if`
|
|
4188
|
-
// block and the viewChild signal has updated; at that point both the
|
|
4189
|
-
// anchor and the surface have a `getBoundingClientRect`, and the position
|
|
4190
|
-
// can be computed. This is more reliable than `afterNextRender` because it
|
|
4191
|
-
// doesn't depend on a single render cycle landing in the expected order
|
|
4192
|
-
// (some host environments, Storybook docs mode for example, defer that
|
|
4193
|
-
// callback in a way that leaves the surface stuck at `visibility: hidden`).
|
|
4194
|
-
// Naturally SSR-safe: the surface never renders on the server, so the
|
|
4195
|
-
// effect always early-returns during prerender.
|
|
4196
|
-
// Teleport the surface to `document.body` as soon as it exists so
|
|
4197
|
-
// `position: fixed` is always relative to the actual viewport (escaping
|
|
4198
|
-
// any transformed/contained ancestor that would otherwise create a new
|
|
4199
|
-
// containing block). Doing the move on init, not on open, also means
|
|
4200
|
-
// the first `getBoundingClientRect` call inside `reposition()` reads a
|
|
4201
|
-
// surface that's already in its final DOM home, so the browser's layout
|
|
4202
|
-
// is settled and dimensions are accurate. Skipped in SSR (no `document`).
|
|
4203
|
-
effect(() => {
|
|
4204
|
-
const surface = this.surfaceEl()?.nativeElement;
|
|
4205
|
-
if (surface &&
|
|
4206
|
-
typeof document !== 'undefined' &&
|
|
4207
|
-
surface.parentNode !== document.body) {
|
|
4208
|
-
document.body.appendChild(surface);
|
|
4209
|
-
}
|
|
4210
|
-
});
|
|
4211
|
-
effect(() => {
|
|
4212
|
-
const surface = this.surfaceEl()?.nativeElement;
|
|
4213
|
-
const anchor = this.resolveAnchor();
|
|
4214
|
-
const isOpen = this.open();
|
|
4215
|
-
if (!surface || !anchor || !isOpen) {
|
|
4216
|
-
this.position.set(null);
|
|
4217
|
-
this.stable.set(false);
|
|
4218
|
-
return;
|
|
4219
|
-
}
|
|
4220
|
-
// Re-read inputs so signal subscriptions stay current after a re-open.
|
|
4221
|
-
this.placement();
|
|
4222
|
-
this.offset();
|
|
4223
|
-
this.flip();
|
|
4224
|
-
this.clamp();
|
|
4225
|
-
this.matchAnchorWidth();
|
|
4226
|
-
// First reposition runs synchronously off the open effect (fast), but
|
|
4227
|
-
// the surface is still transitioning out of `display: none` and the
|
|
4228
|
-
// first `getBoundingClientRect` can report the surface's natural width
|
|
4229
|
-
// even when that overflows the viewport. We deliberately keep the
|
|
4230
|
-
// surface hidden (`visibility: hidden` from CSS) until the next rAF
|
|
4231
|
-
// when the browser has finished laying it out at its real dimensions;
|
|
4232
|
-
// the second reposition then uses accurate measurements and the
|
|
4233
|
-
// `stable` latch flips, revealing the surface at the final position
|
|
4234
|
-
// with no visible jump. SSR / non-browser hosts fall back to flipping
|
|
4235
|
-
// `stable` synchronously.
|
|
4236
|
-
this.reposition();
|
|
4237
|
-
if (typeof requestAnimationFrame !== 'undefined') {
|
|
4238
|
-
requestAnimationFrame(() => {
|
|
4239
|
-
if (!this.open()) {
|
|
4240
|
-
return;
|
|
4241
|
-
}
|
|
4242
|
-
this.reposition();
|
|
4243
|
-
this.stable.set(true);
|
|
4244
|
-
});
|
|
4089
|
+
groupedItems = computed(() => {
|
|
4090
|
+
const q = this.query().trim().toLowerCase();
|
|
4091
|
+
const candidates = this.items().filter(item => {
|
|
4092
|
+
if (item.disabled) {
|
|
4093
|
+
return false;
|
|
4245
4094
|
}
|
|
4246
|
-
|
|
4247
|
-
|
|
4095
|
+
if (!q) {
|
|
4096
|
+
return true;
|
|
4248
4097
|
}
|
|
4098
|
+
const haystack = [item.label, item.description ?? '', ...(item.keywords ?? [])]
|
|
4099
|
+
.join(' ')
|
|
4100
|
+
.toLowerCase();
|
|
4101
|
+
// Match when the query is a prefix of any word in the haystack.
|
|
4102
|
+
// Substring-anywhere matching would surface confusing results (typing
|
|
4103
|
+
// "c" matching "Repla*c*e" via a mid-word character); word-boundary
|
|
4104
|
+
// matching keeps results predictable.
|
|
4105
|
+
return haystack.split(/[\s\-_]+/).some(word => word.startsWith(q));
|
|
4249
4106
|
});
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
// dimensions, giving us a second, accurate measurement to clamp against.
|
|
4258
|
-
// Also catches projected-content size changes while the popover is open
|
|
4259
|
-
// (e.g. virtualised lists adding rows).
|
|
4260
|
-
if (typeof ResizeObserver !== 'undefined') {
|
|
4261
|
-
const surfaceResizeObserver = new ResizeObserver(() => {
|
|
4262
|
-
if (this.open()) {
|
|
4263
|
-
this.reposition();
|
|
4264
|
-
}
|
|
4265
|
-
});
|
|
4266
|
-
effect(() => {
|
|
4267
|
-
const surface = this.surfaceEl()?.nativeElement;
|
|
4268
|
-
surfaceResizeObserver.disconnect();
|
|
4269
|
-
if (surface) {
|
|
4270
|
-
surfaceResizeObserver.observe(surface);
|
|
4271
|
-
}
|
|
4272
|
-
});
|
|
4273
|
-
this.destroyRef.onDestroy(() => surfaceResizeObserver.disconnect());
|
|
4107
|
+
const buckets = new Map();
|
|
4108
|
+
for (const item of candidates) {
|
|
4109
|
+
const key = item.group ?? '';
|
|
4110
|
+
if (!buckets.has(key)) {
|
|
4111
|
+
buckets.set(key, []);
|
|
4112
|
+
}
|
|
4113
|
+
buckets.get(key).push(item);
|
|
4274
4114
|
}
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
return;
|
|
4282
|
-
}
|
|
4283
|
-
// Scrolling within the popover's own surface (e.g. a long dropdown list)
|
|
4284
|
-
// must not dismiss or re-track it; only outside/viewport scroll should.
|
|
4285
|
-
const target = event?.target;
|
|
4286
|
-
if (event?.type === 'scroll' &&
|
|
4287
|
-
target &&
|
|
4288
|
-
this.surfaceEl()?.nativeElement.contains(target)) {
|
|
4289
|
-
return;
|
|
4290
|
-
}
|
|
4291
|
-
const behavior = this.scrollBehavior();
|
|
4292
|
-
if (behavior === 'close') {
|
|
4293
|
-
this.closeRequested.emit();
|
|
4294
|
-
}
|
|
4295
|
-
else if (behavior === 'reposition') {
|
|
4296
|
-
this.reposition();
|
|
4297
|
-
}
|
|
4298
|
-
};
|
|
4299
|
-
window.addEventListener('scroll', onViewportChange, {
|
|
4300
|
-
capture: true,
|
|
4301
|
-
passive: true,
|
|
4302
|
-
});
|
|
4303
|
-
window.addEventListener('resize', onViewportChange);
|
|
4304
|
-
this.destroyRef.onDestroy(() => {
|
|
4305
|
-
window.removeEventListener('scroll', onViewportChange, { capture: true });
|
|
4306
|
-
window.removeEventListener('resize', onViewportChange);
|
|
4115
|
+
const groups = [];
|
|
4116
|
+
let flatIndex = 0;
|
|
4117
|
+
const pushGroup = (group, items) => {
|
|
4118
|
+
groups.push({
|
|
4119
|
+
group,
|
|
4120
|
+
items: items.map(item => ({ item, flatIndex: flatIndex++ })),
|
|
4307
4121
|
});
|
|
4122
|
+
};
|
|
4123
|
+
const ungrouped = buckets.get('');
|
|
4124
|
+
if (ungrouped && ungrouped.length > 0) {
|
|
4125
|
+
pushGroup('', ungrouped);
|
|
4126
|
+
}
|
|
4127
|
+
for (const [group, items] of buckets) {
|
|
4128
|
+
if (group !== '') {
|
|
4129
|
+
pushGroup(group, items);
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4132
|
+
return groups;
|
|
4133
|
+
}, ...(ngDevMode ? [{ debugName: "groupedItems" }] : /* istanbul ignore next */ []));
|
|
4134
|
+
/**
|
|
4135
|
+
* Flat list of matches in display order. Drives keyboard navigation and
|
|
4136
|
+
* `aria-activedescendant`.
|
|
4137
|
+
*/
|
|
4138
|
+
filteredItems = computed(() => this.groupedItems().flatMap(group => group.items.map(entry => entry.item)), ...(ngDevMode ? [{ debugName: "filteredItems" }] : /* istanbul ignore next */ []));
|
|
4139
|
+
_activeIndex = signal(0, ...(ngDevMode ? [{ debugName: "_activeIndex" }] : /* istanbul ignore next */ []));
|
|
4140
|
+
/**
|
|
4141
|
+
* Tracks what the user last did so the visual highlight only renders when
|
|
4142
|
+
* it actually reflects what a click/Enter would select right now:
|
|
4143
|
+
* - `keyboard`: keyboard nav (or just-opened / just-typed): show the
|
|
4144
|
+
* active item's background so keyboard users see what Enter will pick.
|
|
4145
|
+
* - `mouse`: pointer is moving inside the list: rely on `:hover` for the
|
|
4146
|
+
* visual; skip the active-row background to avoid two highlights.
|
|
4147
|
+
* - `none`: pointer is outside the list and no keyboard nav has happened
|
|
4148
|
+
* since: nothing is highlighted, because nothing on screen is a
|
|
4149
|
+
* next-click target.
|
|
4150
|
+
*/
|
|
4151
|
+
interaction = signal('keyboard', ...(ngDevMode ? [{ debugName: "interaction" }] : /* istanbul ignore next */ []));
|
|
4152
|
+
activeIndex = computed(() => {
|
|
4153
|
+
const max = this.filteredItems().length - 1;
|
|
4154
|
+
if (max < 0) {
|
|
4155
|
+
return -1;
|
|
4156
|
+
}
|
|
4157
|
+
return Math.min(this._activeIndex(), max);
|
|
4158
|
+
}, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
4159
|
+
activeId = computed(() => {
|
|
4160
|
+
const idx = this.activeIndex();
|
|
4161
|
+
if (idx < 0) {
|
|
4162
|
+
return null;
|
|
4308
4163
|
}
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4164
|
+
return `ea-command-palette-item-${this.filteredItems()[idx].id}`;
|
|
4165
|
+
}, ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
|
|
4166
|
+
constructor() {
|
|
4167
|
+
/* When the palette opens, focus the search input and reset state. The
|
|
4168
|
+
dialog needs an extra tick to call `showModal()` before the input is
|
|
4169
|
+
focusable, so queue the focus into a microtask. */
|
|
4170
|
+
effect(() => {
|
|
4171
|
+
const isOpen = this.open();
|
|
4172
|
+
const dialog = this.dialogEl()?.nativeElement;
|
|
4173
|
+
if (!dialog) {
|
|
4174
|
+
return;
|
|
4175
|
+
}
|
|
4176
|
+
if (isOpen) {
|
|
4177
|
+
if (!dialog.open) {
|
|
4178
|
+
dialog.showModal?.();
|
|
4179
|
+
}
|
|
4180
|
+
this.query.set('');
|
|
4181
|
+
this._activeIndex.set(0);
|
|
4182
|
+
this.interaction.set('keyboard');
|
|
4183
|
+
queueMicrotask(() => this.searchEl()?.nativeElement.focus());
|
|
4184
|
+
}
|
|
4185
|
+
else if (dialog.open) {
|
|
4186
|
+
dialog.close();
|
|
4187
|
+
}
|
|
4320
4188
|
});
|
|
4321
4189
|
}
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
if (!a) {
|
|
4325
|
-
return null;
|
|
4326
|
-
}
|
|
4327
|
-
return a instanceof ElementRef ? a.nativeElement : a;
|
|
4190
|
+
itemDomId(item) {
|
|
4191
|
+
return `ea-command-palette-item-${item.id}`;
|
|
4328
4192
|
}
|
|
4329
|
-
|
|
4330
|
-
|
|
4193
|
+
isActive(flatIndex) {
|
|
4194
|
+
return this.activeIndex() === flatIndex;
|
|
4195
|
+
}
|
|
4196
|
+
/**
|
|
4197
|
+
* Whether the active row should render its highlighted background right
|
|
4198
|
+
* now. False when the pointer is hovering the list (`:hover` handles the
|
|
4199
|
+
* visual) or when the pointer is out of the list entirely (nothing is a
|
|
4200
|
+
* next-click target).
|
|
4201
|
+
*/
|
|
4202
|
+
showActiveHighlight(flatIndex) {
|
|
4203
|
+
return this.interaction() === 'keyboard' && this.isActive(flatIndex);
|
|
4204
|
+
}
|
|
4205
|
+
onQueryInput(event) {
|
|
4206
|
+
this.query.set(event.target.value);
|
|
4207
|
+
this._activeIndex.set(0);
|
|
4208
|
+
// Typing implies keyboard intent; surface the first match so the user
|
|
4209
|
+
// knows what Enter would pick without having to mouse over.
|
|
4210
|
+
this.interaction.set('keyboard');
|
|
4211
|
+
}
|
|
4212
|
+
clearQuery() {
|
|
4213
|
+
this.query.set('');
|
|
4214
|
+
this._activeIndex.set(0);
|
|
4215
|
+
this.interaction.set('keyboard');
|
|
4216
|
+
this.searchEl()?.nativeElement.focus();
|
|
4217
|
+
}
|
|
4218
|
+
onSearchKeydown(event) {
|
|
4219
|
+
const max = this.filteredItems().length - 1;
|
|
4220
|
+
if (max < 0) {
|
|
4331
4221
|
return;
|
|
4332
4222
|
}
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4223
|
+
switch (event.key) {
|
|
4224
|
+
case 'ArrowDown': {
|
|
4225
|
+
event.preventDefault();
|
|
4226
|
+
this._activeIndex.set(this.activeIndex() < max ? this.activeIndex() + 1 : 0);
|
|
4227
|
+
this.interaction.set('keyboard');
|
|
4228
|
+
this.scrollActiveIntoView();
|
|
4229
|
+
break;
|
|
4230
|
+
}
|
|
4231
|
+
case 'ArrowUp': {
|
|
4232
|
+
event.preventDefault();
|
|
4233
|
+
this._activeIndex.set(this.activeIndex() > 0 ? this.activeIndex() - 1 : max);
|
|
4234
|
+
this.interaction.set('keyboard');
|
|
4235
|
+
this.scrollActiveIntoView();
|
|
4236
|
+
break;
|
|
4237
|
+
}
|
|
4238
|
+
case 'Home': {
|
|
4239
|
+
event.preventDefault();
|
|
4240
|
+
this._activeIndex.set(0);
|
|
4241
|
+
this.interaction.set('keyboard');
|
|
4242
|
+
this.scrollActiveIntoView();
|
|
4243
|
+
break;
|
|
4244
|
+
}
|
|
4245
|
+
case 'End': {
|
|
4246
|
+
event.preventDefault();
|
|
4247
|
+
this._activeIndex.set(max);
|
|
4248
|
+
this.interaction.set('keyboard');
|
|
4249
|
+
this.scrollActiveIntoView();
|
|
4250
|
+
break;
|
|
4251
|
+
}
|
|
4252
|
+
case 'Enter': {
|
|
4253
|
+
event.preventDefault();
|
|
4254
|
+
const item = this.filteredItems()[this.activeIndex()];
|
|
4255
|
+
if (item) {
|
|
4256
|
+
this.executeItem(item);
|
|
4257
|
+
}
|
|
4258
|
+
break;
|
|
4259
|
+
}
|
|
4337
4260
|
}
|
|
4338
|
-
const anchorRect = anchor.getBoundingClientRect();
|
|
4339
|
-
const surfaceRect = surface.getBoundingClientRect();
|
|
4340
|
-
this.position.set(computePopoverPosition(anchorRect, { width: surfaceRect.width, height: surfaceRect.height }, { width: window.innerWidth, height: window.innerHeight }, {
|
|
4341
|
-
placement: this.placement(),
|
|
4342
|
-
offset: this.offset(),
|
|
4343
|
-
flip: this.flip(),
|
|
4344
|
-
clamp: this.clamp(),
|
|
4345
|
-
matchAnchorWidth: this.matchAnchorWidth(),
|
|
4346
|
-
}));
|
|
4347
4261
|
}
|
|
4348
|
-
|
|
4349
|
-
if (
|
|
4350
|
-
return;
|
|
4351
|
-
}
|
|
4352
|
-
const target = event.target;
|
|
4353
|
-
if (!target) {
|
|
4262
|
+
onItemClick(item) {
|
|
4263
|
+
if (item.disabled) {
|
|
4354
4264
|
return;
|
|
4355
4265
|
}
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4266
|
+
this.executeItem(item);
|
|
4267
|
+
}
|
|
4268
|
+
onItemMouseEnter(flatIndex) {
|
|
4269
|
+
this._activeIndex.set(flatIndex);
|
|
4270
|
+
this.interaction.set('mouse');
|
|
4271
|
+
}
|
|
4272
|
+
onListMouseLeave() {
|
|
4273
|
+
/* Once the pointer leaves the list, no item is a candidate for the next
|
|
4274
|
+
click, so drop the keyboard-highlight too. A subsequent keyboard nav
|
|
4275
|
+
will restore it. */
|
|
4276
|
+
this.interaction.set('none');
|
|
4277
|
+
}
|
|
4278
|
+
onBackdropClick(event) {
|
|
4279
|
+
/* Native `<dialog>` clicks land on the dialog itself when the user clicks
|
|
4280
|
+
the backdrop; clicks inside content bubble up via the panel. So a click
|
|
4281
|
+
whose target IS the dialog element means the user clicked the backdrop. */
|
|
4282
|
+
if (event.target === this.dialogEl()?.nativeElement) {
|
|
4283
|
+
this.open.set(false);
|
|
4359
4284
|
}
|
|
4360
|
-
|
|
4361
|
-
|
|
4285
|
+
}
|
|
4286
|
+
onDialogClose() {
|
|
4287
|
+
/* The dialog's native `close` event fires when the user hits Esc or the
|
|
4288
|
+
backdrop dispatches `close`. Mirror that back into the `open` model
|
|
4289
|
+
so consumers stay in sync. */
|
|
4290
|
+
if (this.open()) {
|
|
4291
|
+
this.open.set(false);
|
|
4362
4292
|
}
|
|
4363
|
-
this.closeRequested.emit();
|
|
4364
4293
|
}
|
|
4365
|
-
|
|
4366
|
-
if (
|
|
4294
|
+
executeItem(item) {
|
|
4295
|
+
if (item.disabled) {
|
|
4367
4296
|
return;
|
|
4368
4297
|
}
|
|
4369
|
-
this.
|
|
4298
|
+
this.execute.emit(item);
|
|
4299
|
+
this.open.set(false);
|
|
4370
4300
|
}
|
|
4371
|
-
|
|
4372
|
-
|
|
4301
|
+
scrollActiveIntoView() {
|
|
4302
|
+
queueMicrotask(() => {
|
|
4303
|
+
const id = this.activeId();
|
|
4304
|
+
if (!id) {
|
|
4305
|
+
return;
|
|
4306
|
+
}
|
|
4307
|
+
const el = this.hostEl.nativeElement.querySelector(`#${id}`);
|
|
4308
|
+
el?.scrollIntoView({ block: 'nearest' });
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4311
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CommandPaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4312
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: CommandPaletteComponent, isStandalone: true, selector: "ea-command-palette", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", execute: "execute" }, viewQueries: [{ propertyName: "dialogEl", first: true, predicate: ["dialogEl"], descendants: true, isSignal: true }, { propertyName: "searchEl", first: true, predicate: ["searchEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<dialog\n #dialogEl\n class=\"ea-command-palette\"\n [attr.aria-label]=\"messages().commandPalette.dialogLabel\"\n (close)=\"onDialogClose()\"\n (click)=\"onBackdropClick($event)\">\n <div class=\"ea-command-palette__panel\">\n <div class=\"ea-command-palette__search\">\n <ea-icon-search\n class=\"ea-command-palette__search-icon\"\n aria-hidden=\"true\" />\n <input\n #searchEl\n class=\"ea-command-palette__input\"\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-activedescendant]=\"activeId()\"\n [placeholder]=\"placeholder() || messages().commandPalette.searchPlaceholder\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n (keydown)=\"onSearchKeydown($event)\" />\n @if (query()) {\n <button\n type=\"button\"\n class=\"ea-command-palette__clear\"\n [attr.aria-label]=\"messages().commandPalette.clear\"\n (click)=\"clearQuery()\">\n <ea-icon-x />\n </button>\n }\n </div>\n\n @if (filteredItems().length === 0) {\n <p class=\"ea-command-palette__empty\">\n {{ emptyMessage() || messages().commandPalette.empty }}\n </p>\n } @else {\n <ul\n class=\"ea-command-palette__list\"\n role=\"listbox\"\n [id]=\"listboxId\"\n (mouseleave)=\"onListMouseLeave()\">\n @for (group of groupedItems(); track group.group) {\n @if (group.group) {\n <li\n class=\"ea-command-palette__group\"\n role=\"presentation\">\n {{ group.group }}\n </li>\n }\n @for (entry of group.items; track entry.item.id) {\n <li\n class=\"ea-command-palette__item\"\n role=\"option\"\n [id]=\"itemDomId(entry.item)\"\n [attr.aria-selected]=\"isActive(entry.flatIndex)\"\n [class.ea-command-palette__item--active]=\"\n showActiveHighlight(entry.flatIndex)\n \"\n [class.ea-command-palette__item--disabled]=\"entry.item.disabled\"\n (click)=\"onItemClick(entry.item)\"\n (mouseenter)=\"onItemMouseEnter(entry.flatIndex)\">\n @if (entry.item.icon; as iconClass) {\n <span\n class=\"ea-command-palette__item-icon\"\n aria-hidden=\"true\">\n <ng-container *ngComponentOutlet=\"iconClass\" />\n </span>\n }\n <span class=\"ea-command-palette__item-text\">\n <span class=\"ea-command-palette__item-label\">\n {{ entry.item.label }}\n </span>\n @if (entry.item.description) {\n <span class=\"ea-command-palette__item-description\">\n {{ entry.item.description }}\n </span>\n }\n </span>\n @if (entry.item.shortcut) {\n <kbd class=\"ea-command-palette__item-shortcut\">\n {{ entry.item.shortcut }}\n </kbd>\n }\n </li>\n }\n }\n </ul>\n }\n </div>\n</dialog>\n", styles: [".ea-command-palette{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,100vw - var(--space-8));max-height:70vh;padding:0;border:none;border-radius:var(--radius-lg);background:transparent;color:var(--color-text-primary)}.ea-command-palette::backdrop{background-color:var(--color-bg-overlay)}.ea-command-palette__panel{display:flex;flex-direction:column;max-height:70vh;overflow:hidden;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);background-color:var(--color-bg-elevated)}.ea-command-palette__search{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-command-palette__search-icon{display:inline-flex;align-items:center;width:1.125em;height:1.125em;color:var(--color-text-secondary)}.ea-command-palette__input{flex:1;min-width:0;font-size:var(--font-size-md);border:none;background:transparent;color:inherit;outline:none}.ea-command-palette__input::placeholder{color:var(--color-text-tertiary)}.ea-command-palette__clear{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-command-palette__clear>*{font-size:1.25em}.ea-command-palette__clear:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-command-palette__clear:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-command-palette__clear:disabled{cursor:not-allowed;opacity:.5}.ea-command-palette__list{flex:1;padding:var(--space-1);margin:0;overflow-y:auto;list-style:none}.ea-command-palette__group{position:relative;margin-top:var(--space-3);padding:var(--space-2) var(--space-3) var(--space-1);font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);letter-spacing:.08em;text-transform:uppercase;color:var(--color-text-tertiary);-webkit-user-select:none;user-select:none}.ea-command-palette__group:before{content:\"\";position:absolute;top:0;right:0;left:0;height:var(--border-width-thin);background-color:var(--color-border-default)}.ea-command-palette__group:first-child{margin-top:0}.ea-command-palette__group:first-child:before{display:none}.ea-command-palette__item{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);cursor:pointer;transition:var(--transition-colors);-webkit-user-select:none;user-select:none}.ea-command-palette__item:hover:not(.ea-command-palette__item--disabled){background-color:var(--color-state-hover)}.ea-command-palette__item--active{background-color:var(--color-state-active)}.ea-command-palette__item--disabled{opacity:.5;cursor:not-allowed}.ea-command-palette__item-icon{display:inline-flex;align-items:center;justify-content:center;width:1em;height:1em;flex-shrink:0;color:var(--color-text-secondary)}.ea-command-palette__item-text{display:flex;flex:1;flex-direction:column;min-width:0}.ea-command-palette__item-label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ea-command-palette__item-description{font-size:var(--font-size-xs);color:var(--color-text-secondary);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ea-command-palette__item-shortcut{flex-shrink:0;padding:var(--space-1) var(--space-2);font-size:var(--font-size-xs);font-family:var(--font-family-mono);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-sm);background-color:var(--color-bg-elevated);color:var(--color-text-secondary)}.ea-command-palette__empty{padding:var(--space-6) var(--space-4);margin:0;font-size:var(--font-size-sm);text-align:center;color:var(--color-text-tertiary)}\n"], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: SearchIconComponent, selector: "ea-icon-search" }, { kind: "component", type: XIconComponent, selector: "ea-icon-x" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
4373
4313
|
}
|
|
4374
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type:
|
|
4314
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: CommandPaletteComponent, decorators: [{
|
|
4375
4315
|
type: Component,
|
|
4376
|
-
args: [{ selector: 'ea-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4316
|
+
args: [{ selector: 'ea-command-palette', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [NgComponentOutlet, SearchIconComponent, XIconComponent], template: "<dialog\n #dialogEl\n class=\"ea-command-palette\"\n [attr.aria-label]=\"messages().commandPalette.dialogLabel\"\n (close)=\"onDialogClose()\"\n (click)=\"onBackdropClick($event)\">\n <div class=\"ea-command-palette__panel\">\n <div class=\"ea-command-palette__search\">\n <ea-icon-search\n class=\"ea-command-palette__search-icon\"\n aria-hidden=\"true\" />\n <input\n #searchEl\n class=\"ea-command-palette__input\"\n type=\"text\"\n role=\"combobox\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-activedescendant]=\"activeId()\"\n [placeholder]=\"placeholder() || messages().commandPalette.searchPlaceholder\"\n [value]=\"query()\"\n (input)=\"onQueryInput($event)\"\n (keydown)=\"onSearchKeydown($event)\" />\n @if (query()) {\n <button\n type=\"button\"\n class=\"ea-command-palette__clear\"\n [attr.aria-label]=\"messages().commandPalette.clear\"\n (click)=\"clearQuery()\">\n <ea-icon-x />\n </button>\n }\n </div>\n\n @if (filteredItems().length === 0) {\n <p class=\"ea-command-palette__empty\">\n {{ emptyMessage() || messages().commandPalette.empty }}\n </p>\n } @else {\n <ul\n class=\"ea-command-palette__list\"\n role=\"listbox\"\n [id]=\"listboxId\"\n (mouseleave)=\"onListMouseLeave()\">\n @for (group of groupedItems(); track group.group) {\n @if (group.group) {\n <li\n class=\"ea-command-palette__group\"\n role=\"presentation\">\n {{ group.group }}\n </li>\n }\n @for (entry of group.items; track entry.item.id) {\n <li\n class=\"ea-command-palette__item\"\n role=\"option\"\n [id]=\"itemDomId(entry.item)\"\n [attr.aria-selected]=\"isActive(entry.flatIndex)\"\n [class.ea-command-palette__item--active]=\"\n showActiveHighlight(entry.flatIndex)\n \"\n [class.ea-command-palette__item--disabled]=\"entry.item.disabled\"\n (click)=\"onItemClick(entry.item)\"\n (mouseenter)=\"onItemMouseEnter(entry.flatIndex)\">\n @if (entry.item.icon; as iconClass) {\n <span\n class=\"ea-command-palette__item-icon\"\n aria-hidden=\"true\">\n <ng-container *ngComponentOutlet=\"iconClass\" />\n </span>\n }\n <span class=\"ea-command-palette__item-text\">\n <span class=\"ea-command-palette__item-label\">\n {{ entry.item.label }}\n </span>\n @if (entry.item.description) {\n <span class=\"ea-command-palette__item-description\">\n {{ entry.item.description }}\n </span>\n }\n </span>\n @if (entry.item.shortcut) {\n <kbd class=\"ea-command-palette__item-shortcut\">\n {{ entry.item.shortcut }}\n </kbd>\n }\n </li>\n }\n }\n </ul>\n }\n </div>\n</dialog>\n", styles: [".ea-command-palette{position:fixed;top:15vh;left:50%;transform:translate(-50%);width:min(640px,100vw - var(--space-8));max-height:70vh;padding:0;border:none;border-radius:var(--radius-lg);background:transparent;color:var(--color-text-primary)}.ea-command-palette::backdrop{background-color:var(--color-bg-overlay)}.ea-command-palette__panel{display:flex;flex-direction:column;max-height:70vh;overflow:hidden;border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);background-color:var(--color-bg-elevated)}.ea-command-palette__search{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-bottom:var(--border-width-thin) solid var(--color-border-default)}.ea-command-palette__search-icon{display:inline-flex;align-items:center;width:1.125em;height:1.125em;color:var(--color-text-secondary)}.ea-command-palette__input{flex:1;min-width:0;font-size:var(--font-size-md);border:none;background:transparent;color:inherit;outline:none}.ea-command-palette__input::placeholder{color:var(--color-text-tertiary)}.ea-command-palette__clear{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:var(--ea-icon-button-size, 1.75em);height:var(--ea-icon-button-size, 1.75em);padding:0;border:none;border-radius:var(--radius-sm);background:none;color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-colors)}.ea-command-palette__clear>*{font-size:1.25em}.ea-command-palette__clear:hover{background-color:var(--color-state-hover);color:var(--color-text-primary)}.ea-command-palette__clear:focus-visible{outline:none;box-shadow:var(--shadow-focus-ring)}.ea-command-palette__clear:disabled{cursor:not-allowed;opacity:.5}.ea-command-palette__list{flex:1;padding:var(--space-1);margin:0;overflow-y:auto;list-style:none}.ea-command-palette__group{position:relative;margin-top:var(--space-3);padding:var(--space-2) var(--space-3) var(--space-1);font-size:var(--font-size-xs);font-weight:var(--font-weight-semibold);letter-spacing:.08em;text-transform:uppercase;color:var(--color-text-tertiary);-webkit-user-select:none;user-select:none}.ea-command-palette__group:before{content:\"\";position:absolute;top:0;right:0;left:0;height:var(--border-width-thin);background-color:var(--color-border-default)}.ea-command-palette__group:first-child{margin-top:0}.ea-command-palette__group:first-child:before{display:none}.ea-command-palette__item{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);cursor:pointer;transition:var(--transition-colors);-webkit-user-select:none;user-select:none}.ea-command-palette__item:hover:not(.ea-command-palette__item--disabled){background-color:var(--color-state-hover)}.ea-command-palette__item--active{background-color:var(--color-state-active)}.ea-command-palette__item--disabled{opacity:.5;cursor:not-allowed}.ea-command-palette__item-icon{display:inline-flex;align-items:center;justify-content:center;width:1em;height:1em;flex-shrink:0;color:var(--color-text-secondary)}.ea-command-palette__item-text{display:flex;flex:1;flex-direction:column;min-width:0}.ea-command-palette__item-label{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ea-command-palette__item-description{font-size:var(--font-size-xs);color:var(--color-text-secondary);white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ea-command-palette__item-shortcut{flex-shrink:0;padding:var(--space-1) var(--space-2);font-size:var(--font-size-xs);font-family:var(--font-family-mono);border:var(--border-width-thin) solid var(--color-border-default);border-radius:var(--radius-sm);background-color:var(--color-bg-elevated);color:var(--color-text-secondary)}.ea-command-palette__empty{padding:var(--space-6) var(--space-4);margin:0;font-size:var(--font-size-sm);text-align:center;color:var(--color-text-tertiary)}\n"] }]
|
|
4317
|
+
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], execute: [{ type: i0.Output, args: ["execute"] }], dialogEl: [{ type: i0.ViewChild, args: ['dialogEl', { isSignal: true }] }], searchEl: [{ type: i0.ViewChild, args: ['searchEl', { isSignal: true }] }] } });
|
|
4318
|
+
|
|
4319
|
+
class DropletIconComponent extends IconComponentBase {
|
|
4320
|
+
static slug = 'droplet';
|
|
4321
|
+
static category = 'feather';
|
|
4322
|
+
static tags = [
|
|
4323
|
+
'droplet',
|
|
4324
|
+
'water',
|
|
4325
|
+
'drop',
|
|
4326
|
+
'liquid',
|
|
4327
|
+
'rain',
|
|
4328
|
+
'goutte',
|
|
4329
|
+
'eau',
|
|
4330
|
+
'gota',
|
|
4331
|
+
'agua',
|
|
4332
|
+
'σταγόνα',
|
|
4333
|
+
'νερό',
|
|
4334
|
+
'kropla',
|
|
4335
|
+
'woda',
|
|
4336
|
+
];
|
|
4337
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DropletIconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
4338
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.16", type: DropletIconComponent, isStandalone: true, selector: "ea-icon-droplet", usesInheritance: true, ngImport: i0, template: `
|
|
4339
|
+
<svg
|
|
4340
|
+
viewBox="0 0 24 24"
|
|
4341
|
+
fill="none"
|
|
4342
|
+
stroke="currentColor"
|
|
4343
|
+
[attr.stroke-width]="strokeWidth()"
|
|
4344
|
+
stroke-linecap="round"
|
|
4345
|
+
stroke-linejoin="round"
|
|
4346
|
+
aria-hidden="true"
|
|
4347
|
+
width="100%"
|
|
4348
|
+
height="100%">
|
|
4349
|
+
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" />
|
|
4350
|
+
</svg>
|
|
4351
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4352
|
+
}
|
|
4353
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: DropletIconComponent, decorators: [{
|
|
4354
|
+
type: Component,
|
|
4355
|
+
args: [{
|
|
4356
|
+
selector: 'ea-icon-droplet',
|
|
4357
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4358
|
+
template: `
|
|
4359
|
+
<svg
|
|
4360
|
+
viewBox="0 0 24 24"
|
|
4361
|
+
fill="none"
|
|
4362
|
+
stroke="currentColor"
|
|
4363
|
+
[attr.stroke-width]="strokeWidth()"
|
|
4364
|
+
stroke-linecap="round"
|
|
4365
|
+
stroke-linejoin="round"
|
|
4366
|
+
aria-hidden="true"
|
|
4367
|
+
width="100%"
|
|
4368
|
+
height="100%">
|
|
4369
|
+
<path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z" />
|
|
4370
|
+
</svg>
|
|
4371
|
+
`,
|
|
4372
|
+
}]
|
|
4373
|
+
}] });
|
|
4387
4374
|
|
|
4388
4375
|
const DEFAULT_PRESETS = [
|
|
4389
4376
|
'#ef4444',
|