@lifecorner/angular-ui-kit 3.32.0 → 3.33.1
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/lifecorner-angular-ui-kit-bottom-nav.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-bottom-nav.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs +21 -5
- package/fesm2022/lifecorner-angular-ui-kit-chat.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs +65 -19
- package/fesm2022/lifecorner-angular-ui-kit-combobox.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs +7 -6
- package/fesm2022/lifecorner-angular-ui-kit-datepicker.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +21 -4
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-internal-a11y.mjs +21 -1
- package/fesm2022/lifecorner-angular-ui-kit-internal-a11y.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +21 -4
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs +5 -4
- package/fesm2022/lifecorner-angular-ui-kit-select.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-tag-input.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-textarea.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-toast.mjs +9 -4
- package/fesm2022/lifecorner-angular-ui-kit-toast.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-tooltip.mjs +7 -0
- package/fesm2022/lifecorner-angular-ui-kit-tooltip.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/theme-contrast.spec.ts +14 -6
- package/types/lifecorner-angular-ui-kit-bottom-nav.d.ts +3 -2
- package/types/lifecorner-angular-ui-kit-chat.d.ts +14 -1
- package/types/lifecorner-angular-ui-kit-combobox.d.ts +18 -1
- package/types/lifecorner-angular-ui-kit-datepicker.d.ts +4 -1
- package/types/lifecorner-angular-ui-kit-header.d.ts +26 -0
- package/types/lifecorner-angular-ui-kit-internal-a11y.d.ts +12 -1
- package/types/lifecorner-angular-ui-kit-list.d.ts +6 -1
- package/types/lifecorner-angular-ui-kit-next-step-card.d.ts +15 -0
- package/types/lifecorner-angular-ui-kit-select.d.ts +7 -0
- package/types/lifecorner-angular-ui-kit-sidenav.d.ts +3 -1
- package/types/lifecorner-angular-ui-kit-toast.d.ts +17 -3
- package/types/lifecorner-angular-ui-kit-tooltip.d.ts +7 -2
|
@@ -38,6 +38,7 @@ var SelectComponent = class SelectComponent {
|
|
|
38
38
|
isDisabled = computed(() => this.disabled() || this.formDisabled(), ...ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []);
|
|
39
39
|
host = inject(ElementRef);
|
|
40
40
|
panelLang = computed(() => this.isOpen() ? closestLang(this.host.nativeElement) : null, ...ngDevMode ? [{ debugName: "panelLang" }] : /* istanbul ignore next */ []);
|
|
41
|
+
fieldWidth = computed(() => this.isOpen() ? this.selectTrigger()?.nativeElement.getBoundingClientRect().width ?? null : null, ...ngDevMode ? [{ debugName: "fieldWidth" }] : /* istanbul ignore next */ []);
|
|
41
42
|
filteredOptions = computed(() => {
|
|
42
43
|
const query = this.searchQuery().toLowerCase();
|
|
43
44
|
const opts = this.options();
|
|
@@ -389,8 +390,8 @@ var SelectComponent = class SelectComponent {
|
|
|
389
390
|
isSignal: true
|
|
390
391
|
}],
|
|
391
392
|
ngImport: i0,
|
|
392
|
-
template: "<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #dropdownPanel\n class=\"lc-select__dropdown\"\n [class.lc-select__dropdown--open]=\"isOpen()\"\n [attr.lang]=\"panelLang()\"\n >\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
|
|
393
|
-
styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{position:relative;display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;background:none;background-clip:content-box;border:none;border-radius:calc(var(--border-radius-sm) + .125rem);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:200px;max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}.lc-select__clear:focus-visible{outline-color:Highlight}}\n"],
|
|
393
|
+
template: "<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #dropdownPanel\n class=\"lc-select__dropdown\"\n [class.lc-select__dropdown--open]=\"isOpen()\"\n [style.--_lc-select-field-width.px]=\"fieldWidth()\"\n [attr.lang]=\"panelLang()\"\n >\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
|
|
394
|
+
styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{position:relative;display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;background:none;background-clip:content-box;border:none;border-radius:calc(var(--border-radius-sm) + .125rem);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:max(200px,var(--_lc-select-field-width, 0px));max-width:calc(100vw - 2 * var(--spacing-2));max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}.lc-select__clear:focus-visible{outline-color:Highlight}}\n"],
|
|
394
395
|
dependencies: [
|
|
395
396
|
{
|
|
396
397
|
kind: "ngmodule",
|
|
@@ -485,8 +486,8 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
485
486
|
useExisting: forwardRef(() => SelectComponent),
|
|
486
487
|
multi: true
|
|
487
488
|
}],
|
|
488
|
-
template: "<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #dropdownPanel\n class=\"lc-select__dropdown\"\n [class.lc-select__dropdown--open]=\"isOpen()\"\n [attr.lang]=\"panelLang()\"\n >\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
|
|
489
|
-
styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{position:relative;display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;background:none;background-clip:content-box;border:none;border-radius:calc(var(--border-radius-sm) + .125rem);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:200px;max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}.lc-select__clear:focus-visible{outline-color:Highlight}}\n"]
|
|
489
|
+
template: "<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #dropdownPanel\n class=\"lc-select__dropdown\"\n [class.lc-select__dropdown--open]=\"isOpen()\"\n [style.--_lc-select-field-width.px]=\"fieldWidth()\"\n [attr.lang]=\"panelLang()\"\n >\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n",
|
|
490
|
+
styles: [".lc-select-wrapper{display:flex;flex-direction:column;gap:var(--lc-density-gap-xs, var(--spacing-1));width:100%;position:relative}.lc-select{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;font-family:var(--font-family-sans);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background-color:var(--color-surface-2);border:1px solid var(--color-field-border);border-radius:var(--border-radius-md);transition:all var(--animation-duration-base) var(--animation-timing-ease);cursor:pointer;-webkit-user-select:none;user-select:none}.lc-select:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){border-color:var(--color-text-secondary)}.lc-select:focus,.lc-select:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0px;border-color:var(--color-primary-500)}.lc-select.lc-select--xs{height:var(--size-interactive-xs-height);padding:var(--size-interactive-xs-padding);padding-right:var(--spacing-8);font-size:var(--size-interactive-xs-font-size)}.lc-select.lc-select--sm{height:var(--size-interactive-sm-height);padding:var(--size-interactive-sm-padding);padding-right:var(--spacing-9);font-size:var(--size-interactive-sm-font-size)}.lc-select.lc-select--md{height:var(--size-interactive-md-height);padding:var(--size-interactive-md-padding);padding-right:var(--spacing-10);font-size:var(--size-interactive-md-font-size)}.lc-select.lc-select--lg{height:var(--size-interactive-lg-height);padding:var(--size-interactive-lg-padding);padding-right:var(--spacing-12);font-size:var(--size-interactive-lg-font-size)}.lc-select.lc-select--filled{background-color:var(--color-surface-sunken);border-color:var(--color-field-border)}.lc-select.lc-select--filled:hover:not(.lc-select--disabled):not(.lc-select--error):not(:focus){background-color:var(--color-surface-hover);border-color:var(--color-text-secondary)}.lc-select.lc-select--filled:focus,.lc-select.lc-select--filled:focus-visible{background-color:var(--color-surface);border-color:var(--color-primary-500)}.lc-select.lc-select--error{border-color:var(--color-error-600)}.lc-select.lc-select--error:focus,.lc-select.lc-select--error:focus-visible{outline-color:var(--color-error-600);border-color:var(--color-error-600)}.lc-select.lc-select--disabled{background-color:var(--color-surface-muted);border-color:var(--color-border);cursor:not-allowed;opacity:.6}.lc-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lc-select__placeholder{color:var(--color-text-secondary)}.lc-select__icons{position:absolute;right:var(--spacing-3);display:flex;align-items:center;gap:var(--spacing-1);flex-shrink:0;pointer-events:none}.lc-select__icons button{pointer-events:auto}.lc-select__spinner{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.lc-select__clear{position:relative;display:var(--lc-select-clear-display, flex);align-items:center;justify-content:center;width:1.5rem;height:1.5rem;margin:-.125rem;padding:.125rem;background:none;background-clip:content-box;border:none;border-radius:calc(var(--border-radius-sm) + .125rem);color:var(--lc-select-clear-fg, var(--color-text-secondary));cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__clear:hover{color:var(--lc-select-clear-hover-fg, var(--color-text-primary));background-color:var(--lc-select-clear-hover-bg, var(--color-surface-hover))}.lc-select__clear:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:0}.lc-select__clear svg{width:1rem;height:1rem}.lc-select__chevron{width:1.25rem;height:1.25rem;color:var(--color-text-secondary);transition:transform var(--animation-duration-base) var(--animation-timing-ease)}.lc-select__chevron.lc-select__chevron--open{transform:rotate(180deg)}.lc-select__dropdown{position:absolute;z-index:1000;margin-top:var(--spacing-1);padding:var(--lc-density-padding-xs, var(--spacing-2));background-color:var(--color-surface);background-image:var(--gradient-surface);border:1px solid var(--color-border-strong);border-radius:var(--border-radius-lg);box-shadow:var(--elevation-4);min-width:max(200px,var(--_lc-select-field-width, 0px));max-width:calc(100vw - 2 * var(--spacing-2));max-height:320px;overflow-y:auto;opacity:0;transform:translateY(-8px);transition:all var(--animation-duration-base) var(--animation-timing-ease);pointer-events:none}.lc-select__dropdown.lc-select__dropdown--open{opacity:1;transform:translateY(0);pointer-events:auto}.lc-select__dropdown::-webkit-scrollbar{width:8px}.lc-select__dropdown::-webkit-scrollbar-track{background:var(--color-surface-sunken);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:var(--border-radius-md)}.lc-select__dropdown::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}.lc-select__search{padding:var(--lc-density-padding-xs, var(--spacing-2));border-bottom:1px solid var(--color-border);margin-bottom:var(--spacing-2)}.lc-select__search-input{width:100%;padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm);color:var(--color-text-primary);background-color:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--border-radius-md);outline:none;transition:all var(--animation-duration-fast) var(--animation-timing-ease)}.lc-select__search-input:focus{border-color:var(--color-primary-500)}.lc-select__search-input::placeholder{color:var(--color-text-secondary)}.lc-select__options{list-style:none;padding:0;margin:0}.lc-select__option{display:flex;align-items:center;padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--font-size-sm);color:var(--color-text-primary);background:none;border:none;border-radius:var(--border-radius-md);cursor:pointer;transition:all var(--animation-duration-fast) var(--animation-timing-ease);text-align:left;width:100%}.lc-select__option:hover:not(.lc-select__option--disabled){background-color:var(--color-surface-hover)}.lc-select__option.lc-select__option--selected{font-weight:var(--font-weight-semibold);color:var(--color-primary-600);background-color:var(--color-primary-50)}.lc-select__option.lc-select__option--highlighted{background-color:var(--color-surface-hover);outline:2px solid var(--color-primary-500);outline-offset:-2px}.lc-select__option.lc-select__option--disabled{color:var(--color-text-disabled);cursor:not-allowed;opacity:.5}.lc-select__option-label{flex:1}.lc-select__check{width:1rem;height:1rem;margin-left:var(--spacing-2);flex-shrink:0;color:var(--color-primary-600)}.lc-select__checkbox{margin-right:var(--spacing-2);width:1rem;height:1rem;pointer-events:none}.lc-select__empty{padding:var(--lc-density-padding-md, var(--spacing-4));text-align:center;font-size:var(--font-size-sm);color:var(--color-text-secondary)}.lc-select__error{font-size:var(--font-size-xs);color:var(--color-error-600);margin-top:var(--spacing-1)}.lc-select__helper{font-size:var(--font-size-xs);color:var(--color-text-secondary);margin-top:var(--spacing-1)}@media(forced-colors:active){.lc-select__option.lc-select__option--highlighted{outline-color:Highlight}.lc-select__clear:focus-visible{outline-color:Highlight}}\n"]
|
|
490
491
|
}]
|
|
491
492
|
}],
|
|
492
493
|
propDecorators: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-select.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/select/select.component.ts","../../../../libs/angular-ui-kit/src/lib/select/select.component.html"],"sourcesContent":["import {\n Component,\n input,\n output,\n signal,\n computed,\n linkedSignal,\n ChangeDetectionStrategy,\n forwardRef,\n ElementRef,\n viewChild,\n inject,\n DOCUMENT,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\nimport { closestLang } from '@lifecorner/angular-ui-kit/internal/a11y';\n\nexport interface SelectOption {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectOptionGroup {\n label: string;\n options: SelectOption[];\n}\n\nexport type SelectValue = string | number | string[] | number[] | null;\n\n/**\n * Select component for dropdown option selection.\n *\n * Features:\n * - Single and multiple selection modes\n * - Searchable/filterable option list\n * - Option groups with headers\n * - Loading state indicator\n * - Variant styles (outline, filled)\n * - Size presets (xs, sm, md, lg)\n * - Keyboard navigation support\n * - CDK overlay positioning\n * - ControlValueAccessor integration for reactive forms\n *\n * The dropdown takes the `lang` of the host's closest `[lang]` (3.31).\n *\n * @example\n * ```html\n * <lc-select [options]=\"options\" placeholder=\"Choose\" [(ngModel)]=\"selected\" />\n * ```\n */\n@Component({\n selector: 'lc-select',\n standalone: true,\n imports: [FormsModule, OverlayModule],\n templateUrl: './select.component.html',\n styleUrl: './select.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SelectComponent),\n multi: true,\n },\n ],\n})\nexport class SelectComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance id base; the listbox and its options derive their ids from it. */\n readonly selectId = `lc-select-${++SelectComponent.nextId}`;\n readonly listboxId = `${this.selectId}-listbox`;\n\n private readonly selectTrigger = viewChild<ElementRef<HTMLElement>>('selectTrigger');\n private readonly dropdownPanel = viewChild<ElementRef<HTMLElement>>('dropdownPanel');\n\n /**\n * Visual variant of the select\n */\n readonly variant = input<'outline' | 'filled'>('outline');\n\n /**\n * Size of the select\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the select is disabled\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the select is in error state\n */\n readonly error = input<boolean>(false);\n\n /**\n * Whether the select is required\n */\n readonly required = input<boolean>(false);\n\n /**\n * Whether the select is in loading state\n */\n readonly loading = input<boolean>(false);\n\n /**\n * Whether the select allows searching\n */\n readonly searchable = input<boolean>(false);\n\n /**\n * Whether multiple options can be selected\n */\n readonly multiple = input<boolean>(false);\n\n /**\n * Placeholder text when no option is selected\n */\n readonly placeholder = input<string>('Select an option');\n\n /**\n * Helper text displayed below the select\n */\n readonly helperText = input<string>('');\n\n /**\n * Error message displayed when error is true\n */\n readonly errorMessage = input<string>('');\n\n /**\n * ARIA label for accessibility\n */\n readonly ariaLabel = input<string | undefined>(undefined);\n\n /**\n * Select options (flat list or groups)\n */\n readonly options = input<SelectOption[] | SelectOptionGroup[]>([]);\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear selection');\n\n /** Placeholder of the search field (`searchable`). */\n readonly searchPlaceholder = input('Search...');\n\n /** Accessible name of the search field. Empty: \"Search \" + `ariaLabel`, or \"Search options\". */\n readonly searchAriaLabel = input('');\n\n /** Shown when the search matches no option. */\n readonly noOptionsLabel = input('No options found');\n\n /**\n * Emitted when selection changes\n */\n readonly selectionChange = output<SelectValue>();\n\n /**\n * Emitted when dropdown opens\n */\n readonly opened = output<void>();\n\n /**\n * Emitted when dropdown closes\n */\n readonly closed = output<void>();\n\n // Internal state\n readonly value = signal<SelectValue>(null);\n readonly isOpen = signal<boolean>(false);\n readonly searchQuery = signal<string>('');\n\n /** Disabled state pushed in by the forms API (setDisabledState). */\n private readonly formDisabled = signal<boolean>(false);\n\n /** Effective disabled state: the `disabled` input OR the form control's disabled state. */\n readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /**\n * `lang` of the open dropdown (3.31, request 050, WCAG 3.1.2): the overlay\n * renders under `<body>`, so it takes the host's closest `[lang]`, else none.\n * Read at every opening; `null` while closed, so the server never reads the DOM.\n */\n protected readonly panelLang = computed(() => (this.isOpen() ? closestLang(this.host.nativeElement) : null));\n\n // Computed values\n readonly filteredOptions = computed(() => {\n const query = this.searchQuery().toLowerCase();\n const opts = this.options();\n\n if (!query || !this.searchable()) {\n return this.flattenOptions(opts);\n }\n\n return this.flattenOptions(opts).filter((opt) => opt.label.toLowerCase().includes(query));\n });\n\n /** Keyboard highlight; resets whenever the visible option list changes so it never points at a stale row. */\n readonly highlightedIndex = linkedSignal<SelectOption[], number>({\n source: this.filteredOptions,\n computation: () => -1,\n });\n\n readonly activeDescendantId = computed(() => {\n const index = this.highlightedIndex();\n return this.isOpen() && index >= 0 ? this.optionId(index) : null;\n });\n\n readonly selectedLabel = computed(() => {\n const currentValue = this.value();\n const opts = this.options();\n\n if (currentValue === null) {\n return '';\n }\n\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [currentValue];\n return values\n .map((val) => this.findOptionByValue(val, opts)?.label)\n .filter(Boolean)\n .join(', ');\n }\n\n const val = Array.isArray(currentValue) ? currentValue[0] : currentValue;\n return this.findOptionByValue(val ?? '', opts)?.label || '';\n });\n\n readonly displayValue = computed(() => {\n const label = this.selectedLabel();\n if (label) {\n const currentValue = this.value();\n if (this.multiple() && Array.isArray(currentValue)) {\n const count = currentValue.length;\n return count > 1 ? `${count} selected` : label;\n }\n return label;\n }\n return this.placeholder();\n });\n\n /** id of the helper/error text the trigger is described by (aria-describedby) */\n readonly describedBy = computed(() => {\n if (this.error() && this.errorMessage()) {\n return `${this.selectId}-error`;\n }\n return this.helperText() ? `${this.selectId}-helper` : null;\n });\n\n /**\n * Computed classes for the select trigger element\n */\n readonly selectClasses = computed(() => {\n const classes = ['lc-select', `lc-select--${this.variant()}`, `lc-select--${this.size()}`];\n\n if (this.isDisabled()) {\n classes.push('lc-select--disabled');\n }\n\n if (this.error()) {\n classes.push('lc-select--error');\n }\n\n if (this.loading()) {\n classes.push('lc-select--loading');\n }\n\n if (this.isOpen()) {\n classes.push('lc-select--open');\n }\n\n return classes.join(' ');\n });\n\n // Private properties\n private readonly document = inject(DOCUMENT);\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onChange: (value: SelectValue) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onTouched: () => void = () => {};\n\n // Public methods\n /**\n * Id of the option at `index` in the filtered list (used for aria-activedescendant)\n */\n optionId(index: number): string {\n return `${this.selectId}-option-${index}`;\n }\n\n /**\n * Toggle dropdown open/closed\n */\n toggle(): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n if (this.isOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /**\n * Open dropdown\n */\n open(): void {\n if (this.isDisabled() || this.loading() || this.isOpen()) {\n return;\n }\n this.isOpen.set(true);\n this.opened.emit();\n }\n\n /**\n * Close dropdown. Idempotent: the overlay's `detach` re-enters here after\n * `isOpen` flips, and that second call must not emit `closed` again.\n */\n close(): void {\n if (!this.isOpen()) {\n return;\n }\n // If focus is inside the panel (search input) it would fall to <body> when the\n // overlay is torn down; hand it back to the trigger first.\n this.restoreFocusFromPanel();\n this.isOpen.set(false);\n this.searchQuery.set('');\n this.highlightedIndex.set(-1);\n this.closed.emit();\n }\n\n /**\n * Select an option\n */\n selectOption(option: SelectOption): void {\n if (option.disabled) {\n return;\n }\n\n if (this.multiple()) {\n const currentValue = this.value() || [];\n const currentArray = (Array.isArray(currentValue) ? currentValue : []) as (string | number)[];\n const index = currentArray.indexOf(option.value);\n\n const newValue = (\n index > -1\n ? currentArray.filter((v) => v !== option.value) // Deselect\n : [...currentArray, option.value] // Select\n ) as SelectValue;\n this.value.set(newValue);\n this.onChange(newValue);\n this.selectionChange.emit(newValue);\n } else {\n this.value.set(option.value);\n this.onChange(option.value);\n this.selectionChange.emit(option.value);\n this.close();\n }\n }\n\n /**\n * Check if an option is selected\n */\n isSelected(option: SelectOption): boolean {\n const currentValue = this.value();\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [];\n return values.some((v) => v === option.value);\n }\n return currentValue === option.value;\n }\n\n /**\n * Clear selection\n */\n clear(): void {\n if (this.multiple()) {\n this.value.set([]);\n this.onChange([]);\n } else {\n this.value.set(null);\n this.onChange(null);\n }\n this.selectionChange.emit(this.value());\n }\n\n /**\n * Handle keyboard navigation (trigger and search input share this handler)\n */\n onKeyDown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n\n switch (event.key) {\n case ' ':\n case 'Enter':\n // Space must keep typing into the search box.\n if (event.key === ' ' && this.isSearchInput(event.target)) {\n return;\n }\n if (!this.isOpen()) {\n this.open();\n } else {\n const option = this.filteredOptions()[this.highlightedIndex()];\n if (option) {\n this.selectOption(option);\n }\n }\n event.preventDefault();\n break;\n\n case 'Escape':\n if (this.isOpen()) {\n this.close();\n event.preventDefault();\n // Only this select should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n }\n break;\n\n case 'ArrowDown':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n this.highlightedIndex.set((this.highlightedIndex() + 1) % count);\n }\n }\n event.preventDefault();\n break;\n\n case 'ArrowUp':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n const current = this.highlightedIndex();\n this.highlightedIndex.set(current <= 0 ? count - 1 : current - 1);\n }\n }\n event.preventDefault();\n break;\n\n case 'Home':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(0);\n event.preventDefault();\n }\n break;\n\n case 'End':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(this.filteredOptions().length - 1);\n event.preventDefault();\n }\n break;\n }\n }\n\n /**\n * Handle blur event\n */\n onBlur(): void {\n this.onTouched();\n }\n\n /**\n * Handle click outside\n */\n onClickOutside(): void {\n this.close();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: SelectValue): void {\n this.value.set(value);\n }\n\n registerOnChange(fn: (value: SelectValue) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n // Private helper methods\n private isSearchInput(target: EventTarget | null): boolean {\n return target instanceof HTMLInputElement;\n }\n\n private restoreFocusFromPanel(): void {\n const panel = this.dropdownPanel()?.nativeElement;\n const active = this.document.activeElement;\n if (panel && active && panel.contains(active)) {\n this.selectTrigger()?.nativeElement.focus();\n }\n }\n\n private findOptionByValue(\n value: string | number,\n options: SelectOption[] | SelectOptionGroup[],\n ): SelectOption | undefined {\n const flatOptions = this.flattenOptions(options);\n return flatOptions.find((opt) => opt.value === value);\n }\n\n private flattenOptions(options: SelectOption[] | SelectOptionGroup[]): SelectOption[] {\n if (!options || options.length === 0) {\n return [];\n }\n\n // Check if first item is a group\n const firstItem = options[0];\n if (firstItem && 'options' in firstItem) {\n return (options as SelectOptionGroup[]).flatMap((group) => group.options);\n }\n\n return options as SelectOption[];\n }\n}\n","<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #dropdownPanel\n class=\"lc-select__dropdown\"\n [class.lc-select__dropdown--open]=\"isOpen()\"\n [attr.lang]=\"panelLang()\"\n >\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-select.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/select/select.component.ts","../../../../libs/angular-ui-kit/src/lib/select/select.component.html"],"sourcesContent":["import {\n Component,\n input,\n output,\n signal,\n computed,\n linkedSignal,\n ChangeDetectionStrategy,\n forwardRef,\n ElementRef,\n viewChild,\n inject,\n DOCUMENT,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';\nimport { OverlayModule } from '@angular/cdk/overlay';\nimport { closestLang } from '@lifecorner/angular-ui-kit/internal/a11y';\n\nexport interface SelectOption {\n value: string | number;\n label: string;\n disabled?: boolean;\n}\n\nexport interface SelectOptionGroup {\n label: string;\n options: SelectOption[];\n}\n\nexport type SelectValue = string | number | string[] | number[] | null;\n\n/**\n * Select component for dropdown option selection.\n *\n * Features:\n * - Single and multiple selection modes\n * - Searchable/filterable option list\n * - Option groups with headers\n * - Loading state indicator\n * - Variant styles (outline, filled)\n * - Size presets (xs, sm, md, lg)\n * - Keyboard navigation support\n * - CDK overlay positioning\n * - ControlValueAccessor integration for reactive forms\n *\n * The dropdown takes the `lang` of the host's closest `[lang]` (3.31).\n *\n * @example\n * ```html\n * <lc-select [options]=\"options\" placeholder=\"Choose\" [(ngModel)]=\"selected\" />\n * ```\n */\n@Component({\n selector: 'lc-select',\n standalone: true,\n imports: [FormsModule, OverlayModule],\n templateUrl: './select.component.html',\n styleUrl: './select.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SelectComponent),\n multi: true,\n },\n ],\n})\nexport class SelectComponent implements ControlValueAccessor {\n private static nextId = 0;\n\n /** Per-instance id base; the listbox and its options derive their ids from it. */\n readonly selectId = `lc-select-${++SelectComponent.nextId}`;\n readonly listboxId = `${this.selectId}-listbox`;\n\n private readonly selectTrigger = viewChild<ElementRef<HTMLElement>>('selectTrigger');\n private readonly dropdownPanel = viewChild<ElementRef<HTMLElement>>('dropdownPanel');\n\n /**\n * Visual variant of the select\n */\n readonly variant = input<'outline' | 'filled'>('outline');\n\n /**\n * Size of the select\n */\n readonly size = input<'xs' | 'sm' | 'md' | 'lg'>('md');\n\n /**\n * Whether the select is disabled\n */\n readonly disabled = input<boolean>(false);\n\n /**\n * Whether the select is in error state\n */\n readonly error = input<boolean>(false);\n\n /**\n * Whether the select is required\n */\n readonly required = input<boolean>(false);\n\n /**\n * Whether the select is in loading state\n */\n readonly loading = input<boolean>(false);\n\n /**\n * Whether the select allows searching\n */\n readonly searchable = input<boolean>(false);\n\n /**\n * Whether multiple options can be selected\n */\n readonly multiple = input<boolean>(false);\n\n /**\n * Placeholder text when no option is selected\n */\n readonly placeholder = input<string>('Select an option');\n\n /**\n * Helper text displayed below the select\n */\n readonly helperText = input<string>('');\n\n /**\n * Error message displayed when error is true\n */\n readonly errorMessage = input<string>('');\n\n /**\n * ARIA label for accessibility\n */\n readonly ariaLabel = input<string | undefined>(undefined);\n\n /**\n * Select options (flat list or groups)\n */\n readonly options = input<SelectOption[] | SelectOptionGroup[]>([]);\n\n /** Accessible name of the clear button. */\n readonly clearAriaLabel = input('Clear selection');\n\n /** Placeholder of the search field (`searchable`). */\n readonly searchPlaceholder = input('Search...');\n\n /** Accessible name of the search field. Empty: \"Search \" + `ariaLabel`, or \"Search options\". */\n readonly searchAriaLabel = input('');\n\n /** Shown when the search matches no option. */\n readonly noOptionsLabel = input('No options found');\n\n /**\n * Emitted when selection changes\n */\n readonly selectionChange = output<SelectValue>();\n\n /**\n * Emitted when dropdown opens\n */\n readonly opened = output<void>();\n\n /**\n * Emitted when dropdown closes\n */\n readonly closed = output<void>();\n\n // Internal state\n readonly value = signal<SelectValue>(null);\n readonly isOpen = signal<boolean>(false);\n readonly searchQuery = signal<string>('');\n\n /** Disabled state pushed in by the forms API (setDisabledState). */\n private readonly formDisabled = signal<boolean>(false);\n\n /** Effective disabled state: the `disabled` input OR the form control's disabled state. */\n readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /**\n * `lang` of the open dropdown (3.31, request 050, WCAG 3.1.2): the overlay\n * renders under `<body>`, so it takes the host's closest `[lang]`, else none.\n * Read at every opening; `null` while closed, so the server never reads the DOM.\n */\n protected readonly panelLang = computed(() => (this.isOpen() ? closestLang(this.host.nativeElement) : null));\n\n /**\n * The trigger's width in px while the dropdown is open (3.33, request 052,\n * 050-n4), read at every opening: the panel's floor next to its 200 px\n * (`min-width`), so it is at least as wide as the field and wider content\n * still grows it. `null` while closed.\n */\n protected readonly fieldWidth = computed(() =>\n this.isOpen() ? (this.selectTrigger()?.nativeElement.getBoundingClientRect().width ?? null) : null,\n );\n\n // Computed values\n readonly filteredOptions = computed(() => {\n const query = this.searchQuery().toLowerCase();\n const opts = this.options();\n\n if (!query || !this.searchable()) {\n return this.flattenOptions(opts);\n }\n\n return this.flattenOptions(opts).filter((opt) => opt.label.toLowerCase().includes(query));\n });\n\n /** Keyboard highlight; resets whenever the visible option list changes so it never points at a stale row. */\n readonly highlightedIndex = linkedSignal<SelectOption[], number>({\n source: this.filteredOptions,\n computation: () => -1,\n });\n\n readonly activeDescendantId = computed(() => {\n const index = this.highlightedIndex();\n return this.isOpen() && index >= 0 ? this.optionId(index) : null;\n });\n\n readonly selectedLabel = computed(() => {\n const currentValue = this.value();\n const opts = this.options();\n\n if (currentValue === null) {\n return '';\n }\n\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [currentValue];\n return values\n .map((val) => this.findOptionByValue(val, opts)?.label)\n .filter(Boolean)\n .join(', ');\n }\n\n const val = Array.isArray(currentValue) ? currentValue[0] : currentValue;\n return this.findOptionByValue(val ?? '', opts)?.label || '';\n });\n\n readonly displayValue = computed(() => {\n const label = this.selectedLabel();\n if (label) {\n const currentValue = this.value();\n if (this.multiple() && Array.isArray(currentValue)) {\n const count = currentValue.length;\n return count > 1 ? `${count} selected` : label;\n }\n return label;\n }\n return this.placeholder();\n });\n\n /** id of the helper/error text the trigger is described by (aria-describedby) */\n readonly describedBy = computed(() => {\n if (this.error() && this.errorMessage()) {\n return `${this.selectId}-error`;\n }\n return this.helperText() ? `${this.selectId}-helper` : null;\n });\n\n /**\n * Computed classes for the select trigger element\n */\n readonly selectClasses = computed(() => {\n const classes = ['lc-select', `lc-select--${this.variant()}`, `lc-select--${this.size()}`];\n\n if (this.isDisabled()) {\n classes.push('lc-select--disabled');\n }\n\n if (this.error()) {\n classes.push('lc-select--error');\n }\n\n if (this.loading()) {\n classes.push('lc-select--loading');\n }\n\n if (this.isOpen()) {\n classes.push('lc-select--open');\n }\n\n return classes.join(' ');\n });\n\n // Private properties\n private readonly document = inject(DOCUMENT);\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onChange: (value: SelectValue) => void = () => {};\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n private onTouched: () => void = () => {};\n\n // Public methods\n /**\n * Id of the option at `index` in the filtered list (used for aria-activedescendant)\n */\n optionId(index: number): string {\n return `${this.selectId}-option-${index}`;\n }\n\n /**\n * Toggle dropdown open/closed\n */\n toggle(): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n if (this.isOpen()) {\n this.close();\n } else {\n this.open();\n }\n }\n\n /**\n * Open dropdown\n */\n open(): void {\n if (this.isDisabled() || this.loading() || this.isOpen()) {\n return;\n }\n this.isOpen.set(true);\n this.opened.emit();\n }\n\n /**\n * Close dropdown. Idempotent: the overlay's `detach` re-enters here after\n * `isOpen` flips, and that second call must not emit `closed` again.\n */\n close(): void {\n if (!this.isOpen()) {\n return;\n }\n // If focus is inside the panel (search input) it would fall to <body> when the\n // overlay is torn down; hand it back to the trigger first.\n this.restoreFocusFromPanel();\n this.isOpen.set(false);\n this.searchQuery.set('');\n this.highlightedIndex.set(-1);\n this.closed.emit();\n }\n\n /**\n * Select an option\n */\n selectOption(option: SelectOption): void {\n if (option.disabled) {\n return;\n }\n\n if (this.multiple()) {\n const currentValue = this.value() || [];\n const currentArray = (Array.isArray(currentValue) ? currentValue : []) as (string | number)[];\n const index = currentArray.indexOf(option.value);\n\n const newValue = (\n index > -1\n ? currentArray.filter((v) => v !== option.value) // Deselect\n : [...currentArray, option.value] // Select\n ) as SelectValue;\n this.value.set(newValue);\n this.onChange(newValue);\n this.selectionChange.emit(newValue);\n } else {\n this.value.set(option.value);\n this.onChange(option.value);\n this.selectionChange.emit(option.value);\n this.close();\n }\n }\n\n /**\n * Check if an option is selected\n */\n isSelected(option: SelectOption): boolean {\n const currentValue = this.value();\n if (this.multiple()) {\n const values = Array.isArray(currentValue) ? currentValue : [];\n return values.some((v) => v === option.value);\n }\n return currentValue === option.value;\n }\n\n /**\n * Clear selection\n */\n clear(): void {\n if (this.multiple()) {\n this.value.set([]);\n this.onChange([]);\n } else {\n this.value.set(null);\n this.onChange(null);\n }\n this.selectionChange.emit(this.value());\n }\n\n /**\n * Handle keyboard navigation (trigger and search input share this handler)\n */\n onKeyDown(event: KeyboardEvent): void {\n if (this.isDisabled() || this.loading()) {\n return;\n }\n\n switch (event.key) {\n case ' ':\n case 'Enter':\n // Space must keep typing into the search box.\n if (event.key === ' ' && this.isSearchInput(event.target)) {\n return;\n }\n if (!this.isOpen()) {\n this.open();\n } else {\n const option = this.filteredOptions()[this.highlightedIndex()];\n if (option) {\n this.selectOption(option);\n }\n }\n event.preventDefault();\n break;\n\n case 'Escape':\n if (this.isOpen()) {\n this.close();\n event.preventDefault();\n // Only this select should react; keep the key from reaching enclosing overlays.\n event.stopPropagation();\n }\n break;\n\n case 'ArrowDown':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n this.highlightedIndex.set((this.highlightedIndex() + 1) % count);\n }\n }\n event.preventDefault();\n break;\n\n case 'ArrowUp':\n if (!this.isOpen()) {\n this.open();\n } else {\n const count = this.filteredOptions().length;\n if (count > 0) {\n const current = this.highlightedIndex();\n this.highlightedIndex.set(current <= 0 ? count - 1 : current - 1);\n }\n }\n event.preventDefault();\n break;\n\n case 'Home':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(0);\n event.preventDefault();\n }\n break;\n\n case 'End':\n if (this.isOpen() && this.filteredOptions().length > 0) {\n this.highlightedIndex.set(this.filteredOptions().length - 1);\n event.preventDefault();\n }\n break;\n }\n }\n\n /**\n * Handle blur event\n */\n onBlur(): void {\n this.onTouched();\n }\n\n /**\n * Handle click outside\n */\n onClickOutside(): void {\n this.close();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: SelectValue): void {\n this.value.set(value);\n }\n\n registerOnChange(fn: (value: SelectValue) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n\n // Private helper methods\n private isSearchInput(target: EventTarget | null): boolean {\n return target instanceof HTMLInputElement;\n }\n\n private restoreFocusFromPanel(): void {\n const panel = this.dropdownPanel()?.nativeElement;\n const active = this.document.activeElement;\n if (panel && active && panel.contains(active)) {\n this.selectTrigger()?.nativeElement.focus();\n }\n }\n\n private findOptionByValue(\n value: string | number,\n options: SelectOption[] | SelectOptionGroup[],\n ): SelectOption | undefined {\n const flatOptions = this.flattenOptions(options);\n return flatOptions.find((opt) => opt.value === value);\n }\n\n private flattenOptions(options: SelectOption[] | SelectOptionGroup[]): SelectOption[] {\n if (!options || options.length === 0) {\n return [];\n }\n\n // Check if first item is a group\n const firstItem = options[0];\n if (firstItem && 'options' in firstItem) {\n return (options as SelectOptionGroup[]).flatMap((group) => group.options);\n }\n\n return options as SelectOption[];\n }\n}\n","<div class=\"lc-select-wrapper\">\n <div\n #selectTrigger\n [class]=\"selectClasses()\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"isOpen() ? listboxId : null\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-required]=\"required() ? 'true' : null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : null\"\n [attr.aria-invalid]=\"error() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.tabindex]=\"isDisabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"onKeyDown($event)\"\n (blur)=\"onBlur()\"\n >\n <div class=\"lc-select__value\">\n <span [class.lc-select__placeholder]=\"!selectedLabel()\">\n {{ displayValue() }}\n </span>\n </div>\n\n <div class=\"lc-select__icons\">\n @if (loading()) {\n <svg\n class=\"lc-select__spinner\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"\n ></path>\n </svg>\n } @else if (value() && !isDisabled() && !multiple()) {\n <button\n type=\"button\"\n class=\"lc-select__clear\"\n (click)=\"clear(); $event.stopPropagation()\"\n [attr.aria-label]=\"clearAriaLabel()\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\"\n />\n </svg>\n </button>\n }\n\n <svg\n class=\"lc-select__chevron\"\n [class.lc-select__chevron--open]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n </div>\n </div>\n\n <!-- Dropdown Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"selectTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n (backdropClick)=\"onClickOutside()\"\n (detach)=\"close()\"\n >\n <div\n #dropdownPanel\n class=\"lc-select__dropdown\"\n [class.lc-select__dropdown--open]=\"isOpen()\"\n [style.--_lc-select-field-width.px]=\"fieldWidth()\"\n [attr.lang]=\"panelLang()\"\n >\n @if (searchable()) {\n <div class=\"lc-select__search\">\n <input\n type=\"text\"\n class=\"lc-select__search-input\"\n [placeholder]=\"searchPlaceholder()\"\n aria-autocomplete=\"list\"\n [attr.aria-controls]=\"listboxId\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"searchAriaLabel() || (ariaLabel() ? 'Search ' + ariaLabel() : 'Search options')\"\n [(ngModel)]=\"searchQuery\"\n (keydown)=\"onKeyDown($event)\"\n (click)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div\n class=\"lc-select__options\"\n role=\"listbox\"\n [id]=\"listboxId\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-multiselectable]=\"multiple() ? 'true' : null\"\n >\n @if (filteredOptions().length === 0) {\n <div\n class=\"lc-select__option lc-select__option--no-results\"\n role=\"option\"\n aria-disabled=\"true\"\n aria-selected=\"false\"\n >\n {{ noOptionsLabel() }}\n </div>\n } @else {\n @for (option of filteredOptions(); track option.value; let i = $index) {\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -- listbox option: focus stays on the trigger/search, keyboard selection via aria-activedescendant -->\n <div\n class=\"lc-select__option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"isSelected(option) ? 'true' : 'false'\"\n [attr.aria-disabled]=\"option.disabled ? 'true' : null\"\n [class.lc-select__option--selected]=\"isSelected(option)\"\n [class.lc-select__option--highlighted]=\"highlightedIndex() === i\"\n [class.lc-select__option--disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"highlightedIndex.set(i)\"\n >\n @if (multiple()) {\n <!-- Purely visual: the option itself carries the selected state (role=option\n + aria-selected); the checkbox is inert so clicks land on the option. -->\n <input\n type=\"checkbox\"\n [checked]=\"isSelected(option)\"\n [disabled]=\"option.disabled\"\n class=\"lc-select__checkbox\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n }\n <span class=\"lc-select__option-label\">{{ option.label }}</span>\n @if (isSelected(option) && !multiple()) {\n <svg\n class=\"lc-select__check\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\"\n />\n </svg>\n }\n </div>\n }\n }\n </div>\n </div>\n </ng-template>\n\n <!-- Helper/Error Text -->\n @if (error() && errorMessage()) {\n <div class=\"lc-select__error\" [id]=\"selectId + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </div>\n } @else if (helperText()) {\n <div class=\"lc-select__helper\" [id]=\"selectId + '-helper'\">\n {{ helperText() }}\n </div>\n }\n</div>\n"],"mappings":"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"}
|