@styloviz/select-dropdown 0.1.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/LICENSE +21 -0
- package/README.md +71 -0
- package/fesm2022/styloviz-select-dropdown.mjs +638 -0
- package/fesm2022/styloviz-select-dropdown.mjs.map +1 -0
- package/package.json +43 -0
- package/types/styloviz-select-dropdown.d.ts +217 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styloviz-select-dropdown.mjs","sources":["../../../../projects/select-dropdown-free/src/lib/select-dropdown.component.ts","../../../../projects/select-dropdown-free/src/lib/select-dropdown.component.html","../../../../projects/select-dropdown-free/src/styloviz-select-dropdown.ts"],"sourcesContent":["import {\n ApplicationRef,\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n EmbeddedViewRef,\n forwardRef,\n HostListener,\n inject,\n input,\n model,\n OnDestroy,\n output,\n signal,\n TemplateRef,\n viewChild,\n ViewChild,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nexport type SelectSize = 'sm' | 'md' | 'lg';\nexport type SelectVariant = 'default' | 'filled' | 'flushed';\n\n/** Process-wide counter for generating unique fallback ids. */\nlet _svSelectUid = 0;\n\nexport interface SelectOption {\n value: string;\n label: string;\n sublabel?: string;\n iconPath?: string;\n avatarUrl?: string;\n badge?: string;\n badgeColor?: 'gray' | 'blue' | 'green' | 'red' | 'yellow' | 'purple';\n disabled?: boolean;\n}\n\nexport interface SelectGroup {\n label: string;\n options: SelectOption[];\n}\n\n/**\n * SelectDropdown — A fully-featured, accessible select component for dashboards.\n *\n * Features:\n * - Single and multi-select modes via the `multiple` input\n * - Flat option list and grouped option list (or both together)\n * - Typeahead search with query filtering\n * - Keyboard navigation (↑ ↓ Enter Escape Tab) with scroll-into-view\n * - Chip display for multi-select (up to 3 visible, +N overflow badge)\n * - Clearable selection via an inline × button\n * - Avatar / icon / sublabel / badge per option row\n * - Max-selection cap (`maxSelected`) with disabled-state enforcement\n * - 3 sizes × 3 visual variants (default · filled · flushed)\n * - Full `ControlValueAccessor` integration — works with `FormControl` and `ngModel`\n * - `setDisabledState()` honours both `[disabled]` input and `formControl.disable()`\n * - Full dark-mode support\n * - Accessible: `role=\"combobox\"`, `aria-expanded`, `aria-selected`, `aria-disabled`\n */\n@Component({\n selector: 'sv-select-dropdown',\n standalone: true,\n imports: [NgClass],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './select-dropdown.component.html',\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SvSelectDropdownComponent),\n multi: true,\n },\n ],\n})\nexport class SvSelectDropdownComponent implements ControlValueAccessor, OnDestroy {\n // ── Inputs ─────────────────────────────────────────────────────────────────\n /** Selected value(s) — string for single, string[] for multiple (two-way). */\n value = model<string | string[]>('');\n /** Flat list of options. Use `groups` instead for sectioned lists. */\n options = input<SelectOption[]>([]);\n /** Grouped options with section labels. */\n groups = input<SelectGroup[]>([]);\n /** Placeholder shown when nothing is selected. @default 'Select an option' */\n placeholder = input('Select an option');\n /** Field label. */\n label = input('');\n /** Helper text shown below the field. */\n hint = input('');\n /** Error message; puts the field in an error state when set. */\n errorMessage = input('');\n /** Field size: sm, md or lg. @default 'md' */\n size = input<SelectSize>('md');\n /** Visual variant. @default 'default' */\n variant = input<SelectVariant>('default');\n /** Allow selecting multiple options. @default false */\n multiple = input(false);\n /** Show a search box to filter options. @default false */\n searchable = input(false);\n /** Placeholder for the search box. @default 'Search…' */\n searchPlaceholder = input('Search…');\n /** Text shown when a search yields no matches. @default 'No results found' */\n noResultsText = input('No results found');\n /** Show a clear (×) control. @default false */\n clearable = input(false);\n /** Disable the field. @default false */\n disabled = input(false);\n /** Show a loading state. @default false */\n loading = input(false);\n /** Mark the field as required. @default false */\n required = input(false);\n /** Show an \"optional\" tag next to the label. @default false */\n optionalTag = input(false);\n /** Max selectable options in multiple mode (0 = unlimited). @default 0 */\n maxSelected = input(0);\n /** Explicit id for the control (for external <label for>). */\n inputId = input('');\n /**\n * Accessible name for the trigger when there is no visible `label`.\n * Use this instead of a native `aria-label` on the host element (which is\n * not a labelable role and would be an ARIA violation). Falls back to the\n * `placeholder` so the combobox always has an accessible name.\n */\n ariaLabel = input('');\n /** Extra CSS classes for the control. */\n customClass = input('');\n\n // ── Outputs ────────────────────────────────────────────────────────────────\n /** Emitted with the new selection (string or string[]). */\n selectionChange = output<string | string[]>();\n /** Emitted when the dropdown opens. */\n dropdownOpen = output<void>();\n /** Emitted when the dropdown closes. */\n dropdownClose = output<void>();\n /** Emitted with the search query whenever it changes (for remote filtering). */\n searchChange = output<string>();\n\n // ── Internal state ─────────────────────────────────────────────────────────\n isOpen = signal(false);\n searchQuery = signal('');\n activeIndex = signal(-1);\n isFocused = signal(false);\n /** How many chips to render; 999 = uncapped (all visible). */\n visibleChipCount = signal<number>(999);\n\n // ── Panel portal style (set in computePanelPosition, consumed by the portal template) ──\n readonly panelStyle = signal<Record<string, string>>({});\n\n /** Tracks disabled state set programmatically via formControl.disable(). */\n private readonly _formDisabled = signal(false);\n\n /**\n * Merged disabled state — true when either the [disabled] input or the\n * parent FormControl is disabled. Use this everywhere instead of disabled().\n */\n readonly resolvedDisabled = computed(() => this.disabled() || this._formDisabled());\n\n /** Stable unique fallback id so label + ARIA associations always work. */\n private readonly _autoId = `sv-select-${++_svSelectUid}`;\n /** Effective id used by the combobox, label and ARIA references. */\n readonly resolvedId = computed(() => this.inputId() || this._autoId);\n /** id of the listbox popup (referenced by aria-controls). */\n readonly listboxId = computed(() => `${this.resolvedId()}-listbox`);\n /** id of the visible label (referenced by aria-labelledby). */\n readonly labelId = computed(() => `${this.resolvedId()}-label`);\n /** id of the hint/error description (referenced by aria-describedby). */\n readonly describedById = computed(() => `${this.resolvedId()}-desc`);\n /** True when a hint or error description is rendered. */\n readonly hasDescription = computed(() => !!this.errorMessage() || !!this.hint());\n\n /** DOM id for an option row — used by aria-activedescendant. */\n optionDomId(value: string): string {\n return `${this.resolvedId()}-opt-${value.replace(/[^a-zA-Z0-9_-]/g, '-')}`;\n }\n\n /** id of the currently keyboard-active option, or null. */\n readonly activeDescendantId = computed<string | null>(() => {\n const active = this.activeOption();\n return active ? this.optionDomId(active.value) : null;\n });\n\n @ViewChild('panelTpl', { read: TemplateRef })\n private panelTpl?: TemplateRef<object>;\n\n private searchRef = viewChild<ElementRef<HTMLInputElement>>('searchInput');\n private triggerRef = viewChild<ElementRef<HTMLButtonElement>>('trigger');\n private listRef = viewChild<ElementRef<HTMLUListElement>>('listbox');\n private chipWrapperRef = viewChild<ElementRef<HTMLElement>>('chipWrapper');\n private host = inject(ElementRef<HTMLElement>);\n private appRef = inject(ApplicationRef);\n\n /** Container div appended to document.body while the panel is open. */\n private portalEl: HTMLElement | null = null;\n /** Embedded view holding the panel template nodes. */\n private portalView: EmbeddedViewRef<object> | null = null;\n /** Capture-phase scroll handler — registered once, removed on destroy. */\n private _boundScrollClose!: (e: Event) => void;\n\n constructor() {\n // When the selected values change in uncapped multi-mode, reset visible\n // count to all, then measure which chips actually fit after the next render.\n effect(() => {\n this.selectedValues(); // track\n if (this.multiple() && !this.maxSelected()) {\n this.visibleChipCount.set(999);\n setTimeout(() => this.measureVisibleChips());\n }\n });\n\n this._boundScrollClose = (e: Event) => {\n if (!this.isOpen()) return;\n if (this.portalEl?.contains(e.target as Node)) return;\n this.closeDropdown();\n };\n document.addEventListener('scroll', this._boundScrollClose, { capture: true, passive: true });\n }\n\n // CVA callbacks\n private onChange: (v: string | string[]) => void = () => {};\n private onTouched: () => void = () => {};\n\n // ── Flatten all options (groups + flat) ────────────────────────────────────\n allOptions = computed<SelectOption[]>(() => {\n const flat = this.options();\n const grouped = this.groups().flatMap(g => g.options);\n return [...flat, ...grouped];\n });\n\n // ── Filtered options / groups ──────────────────────────────────────────────\n filteredOptions = computed<SelectOption[]>(() => {\n const q = this.searchQuery().toLowerCase().trim();\n const opts = this.options();\n if (!q) return opts;\n return opts.filter(o => o.label.toLowerCase().includes(q) || o.sublabel?.toLowerCase().includes(q));\n });\n\n filteredGroups = computed<SelectGroup[]>(() => {\n const q = this.searchQuery().toLowerCase().trim();\n const grps = this.groups();\n if (!q) return grps;\n return grps\n .map(g => ({\n ...g,\n options: g.options.filter(o => o.label.toLowerCase().includes(q) || o.sublabel?.toLowerCase().includes(q)),\n }))\n .filter(g => g.options.length > 0);\n });\n\n noResults = computed(() => this.filteredOptions().length === 0 && this.filteredGroups().length === 0);\n\n // ── Flat navigable list (for keyboard nav) ─────────────────────────────────\n navigableOptions = computed<SelectOption[]>(() => [\n ...this.filteredOptions(),\n ...this.filteredGroups().flatMap(g => g.options),\n ]);\n\n // ── Selected option helpers ────────────────────────────────────────────────\n selectedValues = computed<string[]>(() => {\n const v = this.value();\n if (Array.isArray(v)) return v;\n return v ? [v] : [];\n });\n\n selectedOptions = computed<SelectOption[]>(() =>\n this.allOptions().filter(o => this.selectedValues().includes(o.value))\n );\n\n displayLabel = computed<string>(() => {\n const sel = this.selectedOptions();\n if (!sel.length) return '';\n if (this.multiple()) return '';\n return sel[0].label;\n });\n\n hasValue = computed(() => this.selectedValues().length > 0);\n\n showClear = computed(() => this.clearable() && this.hasValue() && !this.resolvedDisabled() && !this.loading());\n\n // ── Overflow chip count ────────────────────────────────────────────────────\n visibleChips = computed<SelectOption[]>(() => {\n const sel = this.selectedOptions();\n // When maxSelected is set use legacy cap of 3; otherwise use measured count.\n const cap = this.maxSelected() > 0 ? 3 : this.visibleChipCount();\n return sel.slice(0, cap);\n });\n\n overflowCount = computed(() => {\n const total = this.selectedOptions().length;\n const cap = this.maxSelected() > 0 ? 3 : this.visibleChipCount();\n return Math.max(0, total - cap);\n });\n\n // ── Max reached ───────────────────────────────────────────────────────────\n maxReached = computed(() => this.multiple() && this.maxSelected() > 0 && this.selectedValues().length >= this.maxSelected());\n\n // ── Trigger label ─────────────────────────────────────────────────────────\n triggerText = computed(() => {\n if (this.multiple()) return '';\n return this.displayLabel() || '';\n });\n\n // ── CSS helpers ───────────────────────────────────────────────────────────\n labelSizeClass = computed(() => ({\n sm: 'text-xs',\n md: 'text-sm',\n lg: 'text-base',\n })[this.size()]);\n\n triggerClasses = computed(() => {\n const s = this.size();\n const v = this.variant();\n const err = !!this.errorMessage();\n const focus = this.isFocused();\n const dis = this.resolvedDisabled();\n const isFloat = false;\n\n const heights: Record<SelectSize, string> = isFloat\n ? { sm: 'min-h-12', md: 'min-h-14', lg: 'min-h-16' }\n : { sm: 'min-h-8', md: 'min-h-10', lg: 'min-h-11' };\n const pads: Record<SelectSize, string> = isFloat\n ? { sm: 'px-2.5 pt-1 pb-1', md: 'px-3 pt-3 pb-2', lg: 'px-4 pt-3 pb-2' }\n : { sm: 'px-2.5 py-1', md: 'px-3 py-2', lg: 'px-4 py-2.5' };\n const text: Record<SelectSize, string> = { sm: 'text-xs', md: 'text-sm', lg: 'text-base' };\n\n const base = [\n 'relative flex w-full items-center gap-2 text-left transition-all duration-150',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n heights[s], pads[s], text[s],\n ];\n\n if (v === 'flushed') {\n base.push(\n 'rounded-none border-0 border-b bg-transparent px-0',\n err\n ? 'border-red-500 dark:border-red-400'\n : focus\n ? 'border-blue-500 dark:border-blue-400'\n : 'border-gray-300 dark:border-gray-600',\n 'focus:outline-none'\n );\n } else if (v === 'filled') {\n base.push(\n 'rounded-md border',\n 'bg-gray-100 dark:bg-gray-800/60',\n err\n ? 'border-red-400 dark:border-red-500'\n : focus\n ? 'border-blue-500 ring-2 ring-blue-500/20 dark:border-blue-400 dark:ring-blue-400/20'\n : 'border-transparent hover:border-gray-300 dark:hover:border-gray-600',\n 'focus:outline-none'\n );\n } else {\n // default and floating — both use a bordered card style\n base.push(\n 'rounded-md border bg-white dark:bg-gray-900',\n err\n ? 'border-red-400 dark:border-red-500 ring-1 ring-red-400/30'\n : focus\n ? 'border-blue-500 ring-2 ring-blue-500/20 dark:border-blue-400 dark:ring-blue-400/20'\n : 'border-gray-300 dark:border-gray-700 hover:border-gray-400 dark:hover:border-gray-600',\n 'focus:outline-none'\n );\n }\n\n if (dis) base.push('bg-gray-50 dark:bg-gray-800/40');\n return base.join(' ');\n });\n\n iconSizeClass = computed(() => ({ sm: 'h-3.5 w-3.5', md: 'h-4 w-4', lg: 'h-5 w-5' })[this.size()]);\n chevronSizeClass = computed(() => ({ sm: 'h-3 w-3', md: 'h-4 w-4', lg: 'h-4 w-4' })[this.size()]);\n chipTextClass = computed(() => ({ sm: 'text-xs', md: 'text-xs', lg: 'text-sm' })[this.size()]);\n\n optionPadClass = computed(() => ({ sm: 'px-2.5 py-1.5', md: 'px-3 py-2', lg: 'px-4 py-2.5' })[this.size()]);\n optionTextClass = computed(() => ({ sm: 'text-xs', md: 'text-sm', lg: 'text-base' })[this.size()]);\n\n /**\n * Static color-class map for option badge chips.\n * `readonly` so the reference is stable; accessed directly in the template\n * as `badgeColorMap[opt.badgeColor ?? 'gray']` — no method call needed.\n */\n readonly badgeColorMap: Readonly<Record<string, string | undefined>> = {\n gray: 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-300',\n blue: 'bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-300',\n green: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300',\n red: 'bg-red-100 text-red-700 dark:bg-red-900/40 dark:text-red-300',\n yellow: 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/40 dark:text-yellow-300',\n purple: 'bg-purple-100 text-purple-700 dark:bg-purple-900/40 dark:text-purple-300',\n };\n\n // ── Dropdown / keyboard ────────────────────────────────────────────────────\n openDropdown() {\n if (this.resolvedDisabled() || this.loading()) return;\n this.computePanelPosition();\n this.isOpen.set(true);\n this.activeIndex.set(-1);\n this.dropdownOpen.emit();\n if (this.panelTpl) {\n this.portalEl = document.createElement('div');\n this.portalEl.className = 'sv-sd-portal';\n document.body.appendChild(this.portalEl);\n this.portalView = this.panelTpl.createEmbeddedView({});\n this.appRef.attachView(this.portalView);\n this.portalView.rootNodes.forEach((n: Node) => this.portalEl!.appendChild(n));\n this.portalView.detectChanges();\n }\n if (this.searchable()) {\n setTimeout(() => this.searchRef()?.nativeElement.focus(), 30);\n }\n }\n\n closeDropdown() {\n this.destroyPortal();\n this.isOpen.set(false);\n this.searchQuery.set('');\n this.activeIndex.set(-1);\n this.isFocused.set(false);\n this.dropdownClose.emit();\n }\n\n toggleDropdown() {\n this.isOpen() ? this.closeDropdown() : this.openDropdown();\n }\n\n ngOnDestroy(): void {\n this.destroyPortal();\n document.removeEventListener('scroll', this._boundScrollClose, { capture: true });\n }\n\n private destroyPortal(): void {\n if (this.portalView) {\n this.appRef.detachView(this.portalView);\n this.portalView.destroy();\n this.portalView = null;\n }\n if (this.portalEl) {\n this.portalEl.remove();\n this.portalEl = null;\n }\n }\n\n @HostListener('document:mousedown', ['$event'])\n onDocumentMousedown(e: MouseEvent) {\n const t = e.target as Node;\n if (this.host.nativeElement.contains(t)) return;\n if (this.portalEl?.contains(t)) return;\n this.closeDropdown();\n }\n\n @HostListener('window:scroll', ['$event'])\n onWindowScroll(e: Event): void {\n if (this.isOpen() && !this.portalEl?.contains(e.target as Node)) {\n this.closeDropdown();\n }\n }\n\n @HostListener('window:resize')\n onWindowResize(): void {\n if (this.isOpen()) this.closeDropdown();\n }\n\n private computePanelPosition(): void {\n const trigger = this.triggerRef()?.nativeElement;\n if (!trigger) return;\n const rect = trigger.getBoundingClientRect();\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const MARGIN = 8;\n const GAP = 4;\n const PREFERRED_HEIGHT = 240;\n\n const spaceBelow = vh - rect.bottom - MARGIN;\n const spaceAbove = rect.top - MARGIN;\n const openUpward = spaceBelow < PREFERRED_HEIGHT && spaceAbove > spaceBelow;\n const alignRight = rect.left + rect.width > vw - MARGIN;\n const maxHeight = Math.max(120, openUpward ? spaceAbove : spaceBelow);\n\n const style: Record<string, string> = {\n position: 'fixed',\n zIndex: '9999',\n width: `${rect.width}px`,\n maxHeight: `${maxHeight}px`,\n };\n style[openUpward ? 'bottom' : 'top'] = openUpward\n ? `${vh - rect.top + GAP}px`\n : `${rect.bottom + GAP}px`;\n style[alignRight ? 'right' : 'left'] = alignRight\n ? `${vw - rect.right}px`\n : `${rect.left}px`;\n\n this.panelStyle.set(style);\n }\n\n /**\n * Measures the chip wrapper element to determine how many chips fit in one\n * row, then updates `visibleChipCount` accordingly. Called after render via\n * a `setTimeout` inside the `effect` so DOM positions are available.\n */\n private measureVisibleChips(): void {\n const wrapper = this.chipWrapperRef()?.nativeElement;\n if (!wrapper) return;\n const chips = Array.from(wrapper.querySelectorAll<HTMLElement>('[data-chip]'));\n if (!chips.length) { this.visibleChipCount.set(0); return; }\n\n const wrapperRight = wrapper.getBoundingClientRect().right;\n\n // Check if every chip fits inside the wrapper (no overflow)\n const allFit = chips.every(c => c.getBoundingClientRect().right <= wrapperRight + 1);\n if (allFit) {\n this.visibleChipCount.set(chips.length);\n return;\n }\n\n // Some chips overflow — find how many fit while leaving ~60 px for \"+N more\"\n const BADGE_RESERVE = 60;\n const availRight = wrapperRight - BADGE_RESERVE;\n let count = 0;\n for (const chip of chips) {\n if (chip.getBoundingClientRect().right > availRight) break;\n count++;\n }\n this.visibleChipCount.set(Math.max(1, count));\n }\n\n onTriggerKeydown(e: KeyboardEvent) {\n if (['ArrowDown', 'ArrowUp', ' ', 'Enter', 'Home', 'End'].includes(e.key)) {\n e.preventDefault();\n if (!this.isOpen()) {\n this.openDropdown();\n this.activeIndex.set(0);\n } else {\n this.navigateList(e.key);\n }\n }\n if (e.key === 'Escape') this.closeDropdown();\n if (e.key === 'Tab') this.closeDropdown();\n }\n\n onSearchKeydown(e: KeyboardEvent) {\n if (e.key === 'ArrowDown') { e.preventDefault(); this.navigateList('ArrowDown'); }\n if (e.key === 'ArrowUp') { e.preventDefault(); this.navigateList('ArrowUp'); }\n if (e.key === 'Home') { e.preventDefault(); this.navigateList('Home'); }\n if (e.key === 'End') { e.preventDefault(); this.navigateList('End'); }\n if (e.key === 'Enter') { e.preventDefault(); this.selectActive(); }\n if (e.key === 'Escape') { this.closeDropdown(); this.triggerRef()?.nativeElement.focus(); }\n }\n\n /** Updates the search query and notifies listeners (for remote filtering). */\n setSearch(q: string): void {\n this.searchQuery.set(q);\n this.activeIndex.set(-1);\n this.searchChange.emit(q);\n }\n\n private navigateList(key: string) {\n const opts = this.navigableOptions().filter(o => !o.disabled);\n if (!opts.length) return;\n const cur = this.activeIndex();\n let next = cur;\n if (key === 'ArrowDown' || key === ' ') next = cur < opts.length - 1 ? cur + 1 : 0;\n if (key === 'ArrowUp') next = cur > 0 ? cur - 1 : opts.length - 1;\n if (key === 'Home') next = 0;\n if (key === 'End') next = opts.length - 1;\n if (key === 'Enter') { this.selectActive(); return; }\n this.activeIndex.set(next);\n this.scrollActiveIntoView();\n }\n\n private selectActive() {\n const opts = this.navigableOptions().filter(o => !o.disabled);\n const idx = this.activeIndex();\n if (idx >= 0 && idx < opts.length) this.selectOption(opts[idx]);\n }\n\n private scrollActiveIntoView() {\n setTimeout(() => {\n const list = this.listRef()?.nativeElement;\n if (!list) return;\n const active = list.querySelector('[data-active=\"true\"]') as HTMLElement | null;\n active?.scrollIntoView({ block: 'nearest' });\n });\n }\n\n selectOption(opt: SelectOption) {\n if (opt.disabled) return;\n if (this.multiple()) {\n const current = [...this.selectedValues()];\n const idx = current.indexOf(opt.value);\n if (idx > -1) {\n current.splice(idx, 1);\n } else {\n if (this.maxReached()) return;\n current.push(opt.value);\n }\n this.value.set(current);\n this.onChange(current);\n this.selectionChange.emit(current);\n } else {\n this.value.set(opt.value);\n this.onChange(opt.value);\n this.selectionChange.emit(opt.value);\n this.closeDropdown();\n this.triggerRef()?.nativeElement.focus();\n }\n }\n\n removeChip(value: string, e: MouseEvent) {\n e.stopPropagation();\n if (this.resolvedDisabled()) return;\n const current = this.selectedValues().filter(v => v !== value);\n this.value.set(current);\n this.onChange(current);\n this.selectionChange.emit(current);\n }\n\n clearAll(e: MouseEvent) {\n e.stopPropagation();\n const empty = this.multiple() ? [] : '';\n this.value.set(empty);\n this.onChange(empty);\n this.selectionChange.emit(empty);\n }\n\n /**\n * The currently keyboard-active option, or `null` when nothing is active.\n * Computed once per change-detection cycle so the template can do a cheap\n * identity check (`opt === activeOption()`) instead of calling the O(n)\n * `isActive(opt)` method for every option row.\n */\n activeOption = computed<SelectOption | null>(() => {\n const opts = this.navigableOptions().filter(o => !o.disabled);\n const idx = this.activeIndex();\n return (idx >= 0 && idx < opts.length) ? opts[idx] : null;\n });\n\n isSelected(value: string): boolean {\n return this.selectedValues().includes(value);\n }\n\n // ── Floating label helpers ────────────────────────────────────────────\n\n isFloating = computed(() => false);\n labelIsFloated = computed(() => this.isOpen() || this.hasValue());\n\n floatingLabelClasses = computed<string>(() => {\n const floated = this.labelIsFloated();\n const err = !!this.errorMessage();\n const active = this.isFocused() || this.isOpen();\n\n const notFloatedLeft = 'left-3.5';\n const floatedLeft = 'left-3';\n const leftClass = floated ? floatedLeft : notFloatedLeft;\n const topClass = floated ? '-top-px' : 'top-1/2';\n const textSize = floated ? 'text-[0.7rem] leading-none' : this.labelSizeClass();\n const bg = floated ? 'px-1 bg-white dark:bg-gray-900' : '';\n\n let color: string;\n if (floated && active) {\n color = err ? 'text-red-500' : 'text-blue-600 dark:text-blue-400';\n } else if (floated) {\n color = err ? 'text-red-500 dark:text-red-400' : 'text-gray-500 dark:text-gray-400';\n } else {\n color = 'text-gray-500 dark:text-gray-400';\n }\n\n return [\n 'absolute z-10 pointer-events-none select-none -translate-y-1/2',\n 'transition-[top,left,font-size,color,padding,background-color] duration-200 ease-in-out',\n `${leftClass} ${topClass}`,\n textSize, bg, color,\n ].filter(Boolean).join(' ');\n });\n\n onFocus() { this.isFocused.set(true); }\n onBlur() { this.onTouched(); }\n\n // ── ControlValueAccessor ───────────────────────────────────────────────────\n writeValue(v: string | string[]): void {\n this.value.set(v ?? (this.multiple() ? [] : ''));\n }\n registerOnChange(fn: (v: string | string[]) => void): void { this.onChange = fn; }\n registerOnTouched(fn: () => void): void { this.onTouched = fn; }\n setDisabledState(isDisabled: boolean): void { this._formDisabled.set(isDisabled); }\n\n}\n","<!-- Root wrapper -->\n<div [ngClass]=\"['flex flex-col gap-1.5 w-full', customClass()]\">\n\n <!-- Label row (hidden for floating variant) -->\n @if (label()) {\n <div class=\"flex items-baseline justify-between gap-2\">\n <label\n [attr.id]=\"labelId()\"\n [ngClass]=\"['font-medium text-gray-700 dark:text-gray-200', labelSizeClass()]\"\n [attr.for]=\"resolvedId()\"\n >\n {{ label() }}\n @if (required()) {\n <span class=\"ml-0.5 text-red-500\" aria-hidden=\"true\">*</span>\n }\n @if (optionalTag() && !required()) {\n <span class=\"ml-1.5 font-normal text-gray-500 dark:text-gray-400 text-xs\">(optional)</span>\n }\n </label>\n </div>\n }\n\n <!-- Trigger button -->\n <div class=\"relative\">\n\n <!-- Floating label (renders inside trigger wrapper, animates to border on open/value) -->\n @if (isFloating() && label()) {\n <label\n [attr.id]=\"labelId()\"\n [ngClass]=\"floatingLabelClasses()\"\n [attr.for]=\"resolvedId()\"\n >\n {{ label() }}\n @if (required()) {\n <span class=\"ml-0.5 text-red-500\" aria-hidden=\"true\">*</span>\n }\n @if (optionalTag() && !required()) {\n <span class=\"ml-1 font-normal text-[0.65rem]\" aria-hidden=\"true\">(opt)</span>\n }\n </label>\n }\n <button\n #trigger\n type=\"button\"\n role=\"combobox\"\n [attr.id]=\"resolvedId()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-controls]=\"isOpen() ? listboxId() : null\"\n [attr.aria-activedescendant]=\"isOpen() ? activeDescendantId() : null\"\n [attr.aria-required]=\"required() || null\"\n [attr.aria-invalid]=\"!!errorMessage() || null\"\n [attr.aria-labelledby]=\"label() ? labelId() : null\"\n [attr.aria-label]=\"label() ? null : (ariaLabel() || placeholder())\"\n [attr.aria-describedby]=\"hasDescription() ? describedById() : null\"\n [disabled]=\"resolvedDisabled() || loading()\"\n [ngClass]=\"triggerClasses()\"\n (click)=\"toggleDropdown()\"\n (keydown)=\"onTriggerKeydown($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n >\n\n <!-- Loading spinner -->\n @if (loading()) {\n <span class=\"flex shrink-0 items-center text-gray-400\" aria-hidden=\"true\">\n <svg [ngClass]=\"iconSizeClass()\" class=\"animate-spin\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"/>\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"/>\n </svg>\n </span>\n }\n\n <!-- Selected value(s) display -->\n <span class=\"flex min-w-0 flex-1 items-center gap-1.5\">\n\n @if (multiple()) {\n <!-- Multi: single-row chip strip (clips overflow visually) -->\n <span #chipWrapper\n class=\"flex min-w-0 flex-1 flex-nowrap items-center gap-1.5 overflow-hidden\">\n @for (chip of visibleChips(); track chip.value) {\n <span\n data-chip\n [ngClass]=\"[\n 'inline-flex shrink-0 items-center gap-1 rounded-md border border-gray-200 bg-gray-100',\n 'text-gray-700 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200',\n chipTextClass(), 'px-1.5 py-0.5 font-medium leading-none'\n ]\"\n >\n @if (chip.iconPath) {\n <svg [ngClass]=\"'h-3 w-3'\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path [attr.d]=\"chip.iconPath\"/>\n </svg>\n }\n {{ chip.label }}\n @if (!resolvedDisabled()) {\n <button\n type=\"button\"\n class=\"ml-0.5 rounded text-gray-400 hover:text-gray-600 dark:hover:text-gray-200\n focus:outline-none focus-visible:ring-1 focus-visible:ring-primary-400\"\n [attr.aria-label]=\"'Remove ' + chip.label\"\n (click)=\"removeChip(chip.value, $event)\"\n tabindex=\"-1\"\n >\n <svg class=\"h-3 w-3\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M18 6 6 18M6 6l12 12\"/>\n </svg>\n </button>\n }\n </span>\n }\n\n @if (!hasValue() && (!isFloating() || labelIsFloated())) {\n <span class=\"text-gray-500 dark:text-gray-400 truncate\">{{ placeholder() }}</span>\n }\n </span>\n\n <!-- Overflow badge — lives OUTSIDE the clipping wrapper so it's always visible -->\n @if (overflowCount() > 0) {\n <span [ngClass]=\"[chipTextClass(), 'shrink-0 text-gray-500 dark:text-gray-400 font-medium']\">\n +{{ overflowCount() }} more\n </span>\n }\n\n } @else {\n <!-- Single: label or placeholder -->\n @if (displayLabel()) {\n @let selectedOpt = selectedOptions()[0];\n <span class=\"flex min-w-0 items-center gap-2\">\n @if (selectedOpt?.avatarUrl) {\n <img [src]=\"selectedOpt.avatarUrl\" alt=\"\"\n class=\"h-5 w-5 shrink-0 rounded-full object-cover\" aria-hidden=\"true\"/>\n } @else if (selectedOpt?.iconPath) {\n <svg [ngClass]=\"iconSizeClass()\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path [attr.d]=\"selectedOpt.iconPath\"/>\n </svg>\n }\n <span class=\"truncate text-gray-900 dark:text-gray-100\">{{ displayLabel() }}</span>\n </span>\n } @else if (!isFloating() || labelIsFloated()) {\n <span class=\"truncate text-gray-500 dark:text-gray-400\">{{ placeholder() }}</span>\n }\n }\n </span>\n\n <!-- Right-side controls -->\n <span class=\"ml-auto flex shrink-0 items-center gap-1 pl-1\">\n\n <!-- Clear button -->\n @if (showClear()) {\n <span\n role=\"button\"\n tabindex=\"-1\"\n class=\"flex items-center rounded text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\n focus:outline-none focus-visible:ring-1 focus-visible:ring-primary-400\"\n aria-label=\"Clear selection\"\n (click)=\"clearAll($event)\"\n (mousedown)=\"$event.preventDefault()\"\n >\n <svg [ngClass]=\"chevronSizeClass()\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M18 6 6 18M6 6l12 12\"/>\n </svg>\n </span>\n <span class=\"h-4 w-px bg-gray-300 dark:bg-gray-600\"></span>\n }\n\n <!-- Chevron -->\n <svg\n [ngClass]=\"[chevronSizeClass(), 'text-gray-400 transition-transform duration-200', isOpen() ? 'rotate-180' : '']\"\n viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\"/>\n </svg>\n\n </span>\n </button>\n\n <!-- ── Dropdown panel — portaled into document.body ──────────────────── -->\n <ng-template #panelTpl>\n <div\n class=\"flex flex-col overflow-hidden rounded-xl border\n border-gray-200 bg-white shadow-xl shadow-gray-900/10\n dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-900/40\"\n [style.position]=\"panelStyle()['position']\"\n [style.zIndex]=\"panelStyle()['zIndex']\"\n [style.top]=\"panelStyle()['top']\"\n [style.bottom]=\"panelStyle()['bottom']\"\n [style.left]=\"panelStyle()['left']\"\n [style.right]=\"panelStyle()['right']\"\n [style.width]=\"panelStyle()['width']\"\n [style.maxHeight]=\"panelStyle()['maxHeight']\"\n role=\"dialog\"\n aria-modal=\"false\"\n >\n\n <!-- Search input -->\n @if (searchable()) {\n <div class=\"border-b border-gray-100 px-3 py-2.5 dark:border-gray-800\">\n <div class=\"flex items-center gap-2\">\n <svg class=\"h-4 w-4 shrink-0 text-gray-400\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/>\n <path d=\"m21 21-4.35-4.35\"/>\n </svg>\n <input\n #searchInput\n type=\"text\"\n role=\"combobox\"\n [attr.aria-expanded]=\"true\"\n [attr.aria-controls]=\"listboxId()\"\n [attr.aria-activedescendant]=\"activeDescendantId()\"\n [attr.aria-label]=\"label() || 'Search options'\"\n class=\"flex-1 bg-transparent text-sm text-gray-900 placeholder-gray-400\n outline-none dark:text-gray-100 dark:placeholder-gray-500\"\n [attr.placeholder]=\"searchPlaceholder()\"\n autocomplete=\"off\"\n [value]=\"searchQuery()\"\n (input)=\"setSearch($any($event.target).value)\"\n (keydown)=\"onSearchKeydown($event)\"\n />\n @if (searchQuery()) {\n <button type=\"button\"\n class=\"text-gray-400 hover:text-gray-600 dark:hover:text-gray-300\"\n (click)=\"setSearch('')\" tabindex=\"-1\" aria-label=\"Clear search\">\n <svg class=\"h-3.5 w-3.5\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M18 6 6 18M6 6l12 12\"/>\n </svg>\n </button>\n }\n </div>\n </div>\n }\n\n <!-- Multi-select count bar -->\n @if (multiple() && maxSelected() > 0) {\n <div class=\"border-b border-gray-100 px-3 py-2 dark:border-gray-800\">\n <p class=\"text-xs text-gray-500 dark:text-gray-400\" aria-live=\"polite\">\n {{ selectedValues().length }} / {{ maxSelected() }} selected\n </p>\n </div>\n }\n\n <!-- Options list -->\n <ul\n #listbox\n [attr.id]=\"listboxId()\"\n role=\"listbox\"\n [attr.aria-multiselectable]=\"multiple()\"\n [attr.aria-label]=\"label() || placeholder()\"\n class=\"min-h-0 flex-1 overflow-y-auto overscroll-contain py-1.5\"\n >\n\n @if (noResults()) {\n <li class=\"px-4 py-6 text-center text-sm text-gray-500 dark:text-gray-400\">\n <svg class=\"mx-auto mb-2 h-8 w-8 opacity-40\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/>\n <path d=\"m21 21-4.35-4.35\"/>\n </svg>\n {{ noResultsText() }}\n </li>\n }\n\n <!-- Flat options -->\n @for (opt of filteredOptions(); track opt.value) {\n <li\n role=\"option\"\n [attr.id]=\"optionDomId(opt.value)\"\n [attr.aria-selected]=\"isSelected(opt.value)\"\n [attr.aria-disabled]=\"opt.disabled || null\"\n [attr.data-active]=\"opt === activeOption()\"\n [ngClass]=\"[\n 'flex cursor-pointer items-center gap-3 transition-colors duration-100',\n optionPadClass(), optionTextClass(),\n opt.disabled\n ? 'cursor-not-allowed opacity-40'\n : opt === activeOption()\n ? 'bg-primary-50 text-primary-700 dark:bg-primary-900/30 dark:text-primary-300'\n : 'text-gray-700 hover:bg-gray-50 dark:text-gray-200 dark:hover:bg-gray-800/60'\n ]\"\n (click)=\"selectOption(opt)\"\n (mouseenter)=\"activeIndex.set(navigableOptions().indexOf(opt))\"\n >\n\n <!-- Checkbox for multi -->\n @if (multiple()) {\n <span\n [ngClass]=\"[\n 'flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors',\n isSelected(opt.value)\n ? 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400'\n : 'border-gray-300 bg-white dark:border-gray-600 dark:bg-gray-800'\n ]\"\n aria-hidden=\"true\"\n >\n @if (isSelected(opt.value)) {\n <svg class=\"h-2.5 w-2.5 text-white dark:text-gray-900\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"3\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m20 6-11 11-5-5\"/>\n </svg>\n }\n </span>\n }\n\n <!-- Avatar -->\n @if (opt.avatarUrl) {\n <img [src]=\"opt.avatarUrl\" alt=\"\" class=\"h-6 w-6 shrink-0 rounded-full object-cover\" aria-hidden=\"true\"/>\n } @else if (opt.iconPath) {\n <svg [ngClass]=\"['shrink-0', iconSizeClass()]\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path [attr.d]=\"opt.iconPath\"/>\n </svg>\n }\n\n <!-- Label + sublabel -->\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate font-medium\">{{ opt.label }}</span>\n @if (opt.sublabel) {\n <span class=\"block truncate text-xs text-gray-500 dark:text-gray-400\">{{ opt.sublabel }}</span>\n }\n </span>\n\n <!-- Badge -->\n @if (opt.badge) {\n <span [ngClass]=\"['shrink-0 rounded-full px-2 py-0.5 text-xs font-medium', badgeColorMap[opt.badgeColor ?? 'gray'] ?? badgeColorMap['gray']]\">\n {{ opt.badge }}\n </span>\n }\n\n <!-- Checkmark for single -->\n @if (!multiple() && isSelected(opt.value)) {\n <svg class=\"ml-auto h-4 w-4 shrink-0 text-primary-500 dark:text-primary-400\"\n viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m20 6-11 11-5-5\"/>\n </svg>\n }\n\n </li>\n }\n\n <!-- Grouped options -->\n @for (group of filteredGroups(); track group.label) {\n <li role=\"presentation\">\n <p class=\"px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 first:pt-1.5\">\n {{ group.label }}\n </p>\n <ul role=\"group\" [attr.aria-label]=\"group.label\">\n @for (opt of group.options; track opt.value) {\n <li\n role=\"option\"\n [attr.id]=\"optionDomId(opt.value)\"\n [attr.aria-selected]=\"isSelected(opt.value)\"\n [attr.aria-disabled]=\"opt.disabled || null\"\n [attr.data-active]=\"opt === activeOption()\"\n [ngClass]=\"[\n 'flex cursor-pointer items-center gap-3 transition-colors duration-100',\n optionPadClass(), optionTextClass(),\n opt.disabled\n ? 'cursor-not-allowed opacity-40'\n : opt === activeOption()\n ? 'bg-primary-50 text-primary-700 dark:bg-primary-900/30 dark:text-primary-300'\n : 'text-gray-700 hover:bg-gray-50 dark:text-gray-200 dark:hover:bg-gray-800/60'\n ]\"\n (click)=\"selectOption(opt)\"\n (mouseenter)=\"activeIndex.set(navigableOptions().indexOf(opt))\"\n >\n @if (multiple()) {\n <span\n [ngClass]=\"[\n 'flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors',\n isSelected(opt.value)\n ? 'border-primary-500 bg-primary-500 dark:border-primary-400 dark:bg-primary-400'\n : 'border-gray-300 bg-white dark:border-gray-600 dark:bg-gray-800'\n ]\"\n aria-hidden=\"true\"\n >\n @if (isSelected(opt.value)) {\n <svg class=\"h-2.5 w-2.5 text-white dark:text-gray-900\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"3\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m20 6-11 11-5-5\"/>\n </svg>\n }\n </span>\n }\n @if (opt.avatarUrl) {\n <img [src]=\"opt.avatarUrl\" alt=\"\" class=\"h-6 w-6 shrink-0 rounded-full object-cover\" aria-hidden=\"true\"/>\n } @else if (opt.iconPath) {\n <svg [ngClass]=\"['shrink-0', iconSizeClass()]\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path [attr.d]=\"opt.iconPath\"/>\n </svg>\n }\n <span class=\"min-w-0 flex-1\">\n <span class=\"block truncate font-medium\">{{ opt.label }}</span>\n @if (opt.sublabel) {\n <span class=\"block truncate text-xs text-gray-500 dark:text-gray-400\">{{ opt.sublabel }}</span>\n }\n </span>\n @if (opt.badge) {\n <span [ngClass]=\"['shrink-0 rounded-full px-2 py-0.5 text-xs font-medium', badgeColorMap[opt.badgeColor ?? 'gray'] ?? badgeColorMap['gray']]\">\n {{ opt.badge }}\n </span>\n }\n @if (!multiple() && isSelected(opt.value)) {\n <svg class=\"ml-auto h-4 w-4 shrink-0 text-primary-500 dark:text-primary-400\"\n viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"m20 6-11 11-5-5\"/>\n </svg>\n }\n </li>\n }\n </ul>\n </li>\n }\n\n </ul>\n\n <!-- Footer slot: multi select-all / clear -->\n @if (multiple() && hasValue()) {\n <div class=\"border-t border-gray-100 px-3 py-2 dark:border-gray-800\">\n <button\n type=\"button\"\n class=\"text-xs font-medium text-gray-500 hover:text-gray-700\n dark:text-gray-400 dark:hover:text-gray-200 transition-colors\"\n (click)=\"clearAll($event)\"\n >\n Clear all ({{ selectedValues().length }})\n </button>\n </div>\n }\n\n </div>\n </ng-template>\n\n </div><!-- /relative -->\n\n <!-- Hint / error -->\n @if (errorMessage() || hint()) {\n <div>\n @if (errorMessage()) {\n <p [attr.id]=\"describedById()\" class=\"flex items-center gap-1 text-xs font-medium text-red-600 dark:text-red-400\" role=\"alert\">\n <svg class=\"h-3.5 w-3.5 shrink-0\" viewBox=\"0 0 24 24\" fill=\"none\"\n stroke=\"currentColor\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"/>\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"/>\n </svg>\n {{ errorMessage() }}\n </p>\n } @else if (hint()) {\n <p [attr.id]=\"describedById()\" class=\"text-xs text-gray-500 dark:text-gray-400\">{{ hint() }}</p>\n }\n </div>\n }\n\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@styloviz/select-dropdown",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Accessible select / dropdown with search, multi-select and custom option templates.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "sazzad-bs23",
|
|
7
|
+
"homepage": "https://styloviz.dev",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/rhossain/angular-tailwind-dashboard-components.git",
|
|
11
|
+
"directory": "projects/select-dropdown-free"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/rhossain/angular-tailwind-dashboard-components/issues"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"@angular/common": ">=21.0.0",
|
|
18
|
+
"@angular/core": ">=21.0.0",
|
|
19
|
+
"@angular/forms": ">=21.0.0"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"module": "fesm2022/styloviz-select-dropdown.mjs",
|
|
29
|
+
"typings": "types/styloviz-select-dropdown.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
"./package.json": {
|
|
32
|
+
"default": "./package.json"
|
|
33
|
+
},
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./types/styloviz-select-dropdown.d.ts",
|
|
36
|
+
"default": "./fesm2022/styloviz-select-dropdown.mjs"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"type": "module",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"tslib": "^2.3.0"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { OnDestroy } from '@angular/core';
|
|
3
|
+
import { ControlValueAccessor } from '@angular/forms';
|
|
4
|
+
|
|
5
|
+
type SelectSize = 'sm' | 'md' | 'lg';
|
|
6
|
+
type SelectVariant = 'default' | 'filled' | 'flushed';
|
|
7
|
+
interface SelectOption {
|
|
8
|
+
value: string;
|
|
9
|
+
label: string;
|
|
10
|
+
sublabel?: string;
|
|
11
|
+
iconPath?: string;
|
|
12
|
+
avatarUrl?: string;
|
|
13
|
+
badge?: string;
|
|
14
|
+
badgeColor?: 'gray' | 'blue' | 'green' | 'red' | 'yellow' | 'purple';
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
}
|
|
17
|
+
interface SelectGroup {
|
|
18
|
+
label: string;
|
|
19
|
+
options: SelectOption[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* SelectDropdown — A fully-featured, accessible select component for dashboards.
|
|
23
|
+
*
|
|
24
|
+
* Features:
|
|
25
|
+
* - Single and multi-select modes via the `multiple` input
|
|
26
|
+
* - Flat option list and grouped option list (or both together)
|
|
27
|
+
* - Typeahead search with query filtering
|
|
28
|
+
* - Keyboard navigation (↑ ↓ Enter Escape Tab) with scroll-into-view
|
|
29
|
+
* - Chip display for multi-select (up to 3 visible, +N overflow badge)
|
|
30
|
+
* - Clearable selection via an inline × button
|
|
31
|
+
* - Avatar / icon / sublabel / badge per option row
|
|
32
|
+
* - Max-selection cap (`maxSelected`) with disabled-state enforcement
|
|
33
|
+
* - 3 sizes × 3 visual variants (default · filled · flushed)
|
|
34
|
+
* - Full `ControlValueAccessor` integration — works with `FormControl` and `ngModel`
|
|
35
|
+
* - `setDisabledState()` honours both `[disabled]` input and `formControl.disable()`
|
|
36
|
+
* - Full dark-mode support
|
|
37
|
+
* - Accessible: `role="combobox"`, `aria-expanded`, `aria-selected`, `aria-disabled`
|
|
38
|
+
*/
|
|
39
|
+
declare class SvSelectDropdownComponent implements ControlValueAccessor, OnDestroy {
|
|
40
|
+
/** Selected value(s) — string for single, string[] for multiple (two-way). */
|
|
41
|
+
value: _angular_core.ModelSignal<string | string[]>;
|
|
42
|
+
/** Flat list of options. Use `groups` instead for sectioned lists. */
|
|
43
|
+
options: _angular_core.InputSignal<SelectOption[]>;
|
|
44
|
+
/** Grouped options with section labels. */
|
|
45
|
+
groups: _angular_core.InputSignal<SelectGroup[]>;
|
|
46
|
+
/** Placeholder shown when nothing is selected. @default 'Select an option' */
|
|
47
|
+
placeholder: _angular_core.InputSignal<string>;
|
|
48
|
+
/** Field label. */
|
|
49
|
+
label: _angular_core.InputSignal<string>;
|
|
50
|
+
/** Helper text shown below the field. */
|
|
51
|
+
hint: _angular_core.InputSignal<string>;
|
|
52
|
+
/** Error message; puts the field in an error state when set. */
|
|
53
|
+
errorMessage: _angular_core.InputSignal<string>;
|
|
54
|
+
/** Field size: sm, md or lg. @default 'md' */
|
|
55
|
+
size: _angular_core.InputSignal<SelectSize>;
|
|
56
|
+
/** Visual variant. @default 'default' */
|
|
57
|
+
variant: _angular_core.InputSignal<SelectVariant>;
|
|
58
|
+
/** Allow selecting multiple options. @default false */
|
|
59
|
+
multiple: _angular_core.InputSignal<boolean>;
|
|
60
|
+
/** Show a search box to filter options. @default false */
|
|
61
|
+
searchable: _angular_core.InputSignal<boolean>;
|
|
62
|
+
/** Placeholder for the search box. @default 'Search…' */
|
|
63
|
+
searchPlaceholder: _angular_core.InputSignal<string>;
|
|
64
|
+
/** Text shown when a search yields no matches. @default 'No results found' */
|
|
65
|
+
noResultsText: _angular_core.InputSignal<string>;
|
|
66
|
+
/** Show a clear (×) control. @default false */
|
|
67
|
+
clearable: _angular_core.InputSignal<boolean>;
|
|
68
|
+
/** Disable the field. @default false */
|
|
69
|
+
disabled: _angular_core.InputSignal<boolean>;
|
|
70
|
+
/** Show a loading state. @default false */
|
|
71
|
+
loading: _angular_core.InputSignal<boolean>;
|
|
72
|
+
/** Mark the field as required. @default false */
|
|
73
|
+
required: _angular_core.InputSignal<boolean>;
|
|
74
|
+
/** Show an "optional" tag next to the label. @default false */
|
|
75
|
+
optionalTag: _angular_core.InputSignal<boolean>;
|
|
76
|
+
/** Max selectable options in multiple mode (0 = unlimited). @default 0 */
|
|
77
|
+
maxSelected: _angular_core.InputSignal<number>;
|
|
78
|
+
/** Explicit id for the control (for external <label for>). */
|
|
79
|
+
inputId: _angular_core.InputSignal<string>;
|
|
80
|
+
/**
|
|
81
|
+
* Accessible name for the trigger when there is no visible `label`.
|
|
82
|
+
* Use this instead of a native `aria-label` on the host element (which is
|
|
83
|
+
* not a labelable role and would be an ARIA violation). Falls back to the
|
|
84
|
+
* `placeholder` so the combobox always has an accessible name.
|
|
85
|
+
*/
|
|
86
|
+
ariaLabel: _angular_core.InputSignal<string>;
|
|
87
|
+
/** Extra CSS classes for the control. */
|
|
88
|
+
customClass: _angular_core.InputSignal<string>;
|
|
89
|
+
/** Emitted with the new selection (string or string[]). */
|
|
90
|
+
selectionChange: _angular_core.OutputEmitterRef<string | string[]>;
|
|
91
|
+
/** Emitted when the dropdown opens. */
|
|
92
|
+
dropdownOpen: _angular_core.OutputEmitterRef<void>;
|
|
93
|
+
/** Emitted when the dropdown closes. */
|
|
94
|
+
dropdownClose: _angular_core.OutputEmitterRef<void>;
|
|
95
|
+
/** Emitted with the search query whenever it changes (for remote filtering). */
|
|
96
|
+
searchChange: _angular_core.OutputEmitterRef<string>;
|
|
97
|
+
isOpen: _angular_core.WritableSignal<boolean>;
|
|
98
|
+
searchQuery: _angular_core.WritableSignal<string>;
|
|
99
|
+
activeIndex: _angular_core.WritableSignal<number>;
|
|
100
|
+
isFocused: _angular_core.WritableSignal<boolean>;
|
|
101
|
+
/** How many chips to render; 999 = uncapped (all visible). */
|
|
102
|
+
visibleChipCount: _angular_core.WritableSignal<number>;
|
|
103
|
+
readonly panelStyle: _angular_core.WritableSignal<Record<string, string>>;
|
|
104
|
+
/** Tracks disabled state set programmatically via formControl.disable(). */
|
|
105
|
+
private readonly _formDisabled;
|
|
106
|
+
/**
|
|
107
|
+
* Merged disabled state — true when either the [disabled] input or the
|
|
108
|
+
* parent FormControl is disabled. Use this everywhere instead of disabled().
|
|
109
|
+
*/
|
|
110
|
+
readonly resolvedDisabled: _angular_core.Signal<boolean>;
|
|
111
|
+
/** Stable unique fallback id so label + ARIA associations always work. */
|
|
112
|
+
private readonly _autoId;
|
|
113
|
+
/** Effective id used by the combobox, label and ARIA references. */
|
|
114
|
+
readonly resolvedId: _angular_core.Signal<string>;
|
|
115
|
+
/** id of the listbox popup (referenced by aria-controls). */
|
|
116
|
+
readonly listboxId: _angular_core.Signal<string>;
|
|
117
|
+
/** id of the visible label (referenced by aria-labelledby). */
|
|
118
|
+
readonly labelId: _angular_core.Signal<string>;
|
|
119
|
+
/** id of the hint/error description (referenced by aria-describedby). */
|
|
120
|
+
readonly describedById: _angular_core.Signal<string>;
|
|
121
|
+
/** True when a hint or error description is rendered. */
|
|
122
|
+
readonly hasDescription: _angular_core.Signal<boolean>;
|
|
123
|
+
/** DOM id for an option row — used by aria-activedescendant. */
|
|
124
|
+
optionDomId(value: string): string;
|
|
125
|
+
/** id of the currently keyboard-active option, or null. */
|
|
126
|
+
readonly activeDescendantId: _angular_core.Signal<string | null>;
|
|
127
|
+
private panelTpl?;
|
|
128
|
+
private searchRef;
|
|
129
|
+
private triggerRef;
|
|
130
|
+
private listRef;
|
|
131
|
+
private chipWrapperRef;
|
|
132
|
+
private host;
|
|
133
|
+
private appRef;
|
|
134
|
+
/** Container div appended to document.body while the panel is open. */
|
|
135
|
+
private portalEl;
|
|
136
|
+
/** Embedded view holding the panel template nodes. */
|
|
137
|
+
private portalView;
|
|
138
|
+
/** Capture-phase scroll handler — registered once, removed on destroy. */
|
|
139
|
+
private _boundScrollClose;
|
|
140
|
+
constructor();
|
|
141
|
+
private onChange;
|
|
142
|
+
private onTouched;
|
|
143
|
+
allOptions: _angular_core.Signal<SelectOption[]>;
|
|
144
|
+
filteredOptions: _angular_core.Signal<SelectOption[]>;
|
|
145
|
+
filteredGroups: _angular_core.Signal<SelectGroup[]>;
|
|
146
|
+
noResults: _angular_core.Signal<boolean>;
|
|
147
|
+
navigableOptions: _angular_core.Signal<SelectOption[]>;
|
|
148
|
+
selectedValues: _angular_core.Signal<string[]>;
|
|
149
|
+
selectedOptions: _angular_core.Signal<SelectOption[]>;
|
|
150
|
+
displayLabel: _angular_core.Signal<string>;
|
|
151
|
+
hasValue: _angular_core.Signal<boolean>;
|
|
152
|
+
showClear: _angular_core.Signal<boolean>;
|
|
153
|
+
visibleChips: _angular_core.Signal<SelectOption[]>;
|
|
154
|
+
overflowCount: _angular_core.Signal<number>;
|
|
155
|
+
maxReached: _angular_core.Signal<boolean>;
|
|
156
|
+
triggerText: _angular_core.Signal<string>;
|
|
157
|
+
labelSizeClass: _angular_core.Signal<string>;
|
|
158
|
+
triggerClasses: _angular_core.Signal<string>;
|
|
159
|
+
iconSizeClass: _angular_core.Signal<string>;
|
|
160
|
+
chevronSizeClass: _angular_core.Signal<string>;
|
|
161
|
+
chipTextClass: _angular_core.Signal<string>;
|
|
162
|
+
optionPadClass: _angular_core.Signal<string>;
|
|
163
|
+
optionTextClass: _angular_core.Signal<string>;
|
|
164
|
+
/**
|
|
165
|
+
* Static color-class map for option badge chips.
|
|
166
|
+
* `readonly` so the reference is stable; accessed directly in the template
|
|
167
|
+
* as `badgeColorMap[opt.badgeColor ?? 'gray']` — no method call needed.
|
|
168
|
+
*/
|
|
169
|
+
readonly badgeColorMap: Readonly<Record<string, string | undefined>>;
|
|
170
|
+
openDropdown(): void;
|
|
171
|
+
closeDropdown(): void;
|
|
172
|
+
toggleDropdown(): void;
|
|
173
|
+
ngOnDestroy(): void;
|
|
174
|
+
private destroyPortal;
|
|
175
|
+
onDocumentMousedown(e: MouseEvent): void;
|
|
176
|
+
onWindowScroll(e: Event): void;
|
|
177
|
+
onWindowResize(): void;
|
|
178
|
+
private computePanelPosition;
|
|
179
|
+
/**
|
|
180
|
+
* Measures the chip wrapper element to determine how many chips fit in one
|
|
181
|
+
* row, then updates `visibleChipCount` accordingly. Called after render via
|
|
182
|
+
* a `setTimeout` inside the `effect` so DOM positions are available.
|
|
183
|
+
*/
|
|
184
|
+
private measureVisibleChips;
|
|
185
|
+
onTriggerKeydown(e: KeyboardEvent): void;
|
|
186
|
+
onSearchKeydown(e: KeyboardEvent): void;
|
|
187
|
+
/** Updates the search query and notifies listeners (for remote filtering). */
|
|
188
|
+
setSearch(q: string): void;
|
|
189
|
+
private navigateList;
|
|
190
|
+
private selectActive;
|
|
191
|
+
private scrollActiveIntoView;
|
|
192
|
+
selectOption(opt: SelectOption): void;
|
|
193
|
+
removeChip(value: string, e: MouseEvent): void;
|
|
194
|
+
clearAll(e: MouseEvent): void;
|
|
195
|
+
/**
|
|
196
|
+
* The currently keyboard-active option, or `null` when nothing is active.
|
|
197
|
+
* Computed once per change-detection cycle so the template can do a cheap
|
|
198
|
+
* identity check (`opt === activeOption()`) instead of calling the O(n)
|
|
199
|
+
* `isActive(opt)` method for every option row.
|
|
200
|
+
*/
|
|
201
|
+
activeOption: _angular_core.Signal<SelectOption | null>;
|
|
202
|
+
isSelected(value: string): boolean;
|
|
203
|
+
isFloating: _angular_core.Signal<boolean>;
|
|
204
|
+
labelIsFloated: _angular_core.Signal<boolean>;
|
|
205
|
+
floatingLabelClasses: _angular_core.Signal<string>;
|
|
206
|
+
onFocus(): void;
|
|
207
|
+
onBlur(): void;
|
|
208
|
+
writeValue(v: string | string[]): void;
|
|
209
|
+
registerOnChange(fn: (v: string | string[]) => void): void;
|
|
210
|
+
registerOnTouched(fn: () => void): void;
|
|
211
|
+
setDisabledState(isDisabled: boolean): void;
|
|
212
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SvSelectDropdownComponent, never>;
|
|
213
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SvSelectDropdownComponent, "sv-select-dropdown", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "groups": { "alias": "groups"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; "isSignal": true; }; "noResultsText": { "alias": "noResultsText"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "optionalTag": { "alias": "optionalTag"; "required": false; "isSignal": true; }; "maxSelected": { "alias": "maxSelected"; "required": false; "isSignal": true; }; "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "customClass": { "alias": "customClass"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "selectionChange": "selectionChange"; "dropdownOpen": "dropdownOpen"; "dropdownClose": "dropdownClose"; "searchChange": "searchChange"; }, never, never, true, never>;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export { SvSelectDropdownComponent };
|
|
217
|
+
export type { SelectGroup, SelectOption, SelectSize, SelectVariant };
|