forge-select 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -15
- package/dist/index.cjs +667 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +178 -9
- package/dist/index.d.ts +178 -9
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +667 -63
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/styles/forge-select.css +37 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/emitter.ts","../src/i18n.ts","../src/native-select.ts","../src/option-renderer.ts","../src/remote.ts","../src/selection.ts","../src/ForgeSelect.ts"],"sourcesContent":["export { default } from \"./ForgeSelect\";\nexport { default as ForgeSelect } from \"./ForgeSelect\";\nexport type {\n AjaxConfig,\n DataItem,\n ForgeSelectEvent,\n ForgeSelectOptions,\n ForgeSelectPlugin,\n ForgeSelectValue,\n Option,\n OptionGroup,\n SetValueOptions,\n TemplateFn,\n} from \"./types\";\n","export type Handler = (...args: unknown[]) => void;\n\nexport class Emitter {\n private handlers = new Map<string, Set<Handler>>();\n\n on(event: string, handler: Handler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler: Handler): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n emit(event: string, ...args: unknown[]): void {\n const set = this.handlers.get(event);\n if (!set) return;\n for (const handler of [...set]) handler(...args);\n }\n\n clear(): void {\n this.handlers.clear();\n }\n}\n","export type Strings = Record<string, string>;\n\nconst locales: Record<string, Strings> = {\n en: {\n noResults: \"No results found\",\n loading: \"Loading…\",\n loadingMore: \"Loading more…\",\n errorLoading: \"Could not load options\",\n createOption: 'Create \"{query}\"',\n clearSelection: \"Clear selection\",\n removeItem: \"Remove {label}\",\n search: \"Search\",\n reorderHint: \"{label}. Press Alt+Left or Alt+Right to reorder.\",\n },\n vi: {\n noResults: \"Không tìm thấy kết quả\",\n loading: \"Đang tải…\",\n loadingMore: \"Đang tải thêm…\",\n errorLoading: \"Không thể tải tùy chọn\",\n createOption: 'Tạo \"{query}\"',\n clearSelection: \"Xóa lựa chọn\",\n removeItem: \"Xóa {label}\",\n search: \"Tìm kiếm\",\n reorderHint: \"{label}. Nhấn Alt+Trái hoặc Alt+Phải để sắp xếp lại.\",\n },\n};\n\nexport function getStrings(language: string | Strings): Strings {\n if (typeof language === \"string\") {\n return locales[language] ?? locales.en;\n }\n return { ...locales.en, ...language };\n}\n\nexport function format(template: string, vars: Record<string, string>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => vars[key] ?? match);\n}\n","import type { DataItem, Option } from \"./types\";\n\nexport function parseNativeOptions(select: HTMLSelectElement): DataItem[] {\n const data: DataItem[] = [];\n for (const child of Array.from(select.children)) {\n if (child instanceof HTMLOptGroupElement) {\n data.push({ label: child.label, options: Array.from(child.querySelectorAll(\"option\")).map(parseOption) });\n } else if (child instanceof HTMLOptionElement) {\n data.push(parseOption(child));\n }\n }\n return data;\n}\n\nfunction parseOption(option: HTMLOptionElement): Option {\n const groupDisabled = option.parentElement instanceof HTMLOptGroupElement && option.parentElement.disabled;\n return {\n value: option.value,\n label: option.textContent?.trim() ?? option.value,\n disabled: option.disabled || groupDisabled || undefined,\n };\n}\n","import type { Option, TemplateFn } from \"./types\";\n\nexport type OptionRenderVariant = \"row\" | \"inline\";\n\n/** Render one option without coupling presentation details to the select controller. */\nexport function renderOptionContent(\n container: HTMLElement,\n option: Option,\n template?: TemplateFn,\n variant: OptionRenderVariant = \"row\",\n): void {\n if (template) {\n const result = template(option);\n if (typeof result === \"string\") container.innerHTML = result;\n else container.append(result);\n return;\n }\n if (!option.avatar && !option.description) {\n container.textContent = option.label;\n return;\n }\n\n // Built-in rich rendering only uses textContent/attribute assignment.\n if (option.avatar) {\n const avatar = document.createElement(\"img\");\n avatar.className = variant === \"row\" ? \"forge-select__option-avatar\" : \"forge-select__inline-avatar\";\n avatar.src = option.avatar;\n avatar.alt = \"\";\n avatar.setAttribute(\"loading\", \"lazy\");\n avatar.setAttribute(\"decoding\", \"async\");\n container.append(avatar);\n }\n if (variant === \"row\" && option.description) {\n const body = document.createElement(\"span\");\n body.className = \"forge-select__option-body\";\n const label = document.createElement(\"span\");\n label.className = \"forge-select__option-label\";\n label.textContent = option.label;\n const description = document.createElement(\"span\");\n description.className = \"forge-select__option-desc\";\n description.textContent = option.description;\n body.append(label, description);\n container.append(body);\n } else {\n const label = document.createElement(\"span\");\n label.className = \"forge-select__option-label\";\n label.textContent = option.label;\n container.append(label);\n }\n}\n","import type { AjaxConfig, Option } from \"./types\";\n\nexport function buildUrl(ajax: AjaxConfig, query: string, page: number): string {\n if (typeof ajax.url === \"function\") return ajax.url(query, page);\n if (!ajax.params) return ajax.url;\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(ajax.params(query, page))) params.set(key, String(value));\n const separator = ajax.url.includes(\"?\") ? \"&\" : \"?\";\n return `${ajax.url}${separator}${params.toString()}`;\n}\n\nexport function normalizeRemoteResult(ajax: AjaxConfig, response: unknown): { options: Option[]; hasMore: boolean } {\n const result = ajax.transform ? ajax.transform(response) : (response as Option[]);\n if (Array.isArray(result)) return { options: result, hasMore: false };\n if (!result || !Array.isArray((result as { options?: unknown }).options)) {\n throw new Error(\n \"ForgeSelect: ajax.transform must return an array of options, or an object shaped like { options: Option[], hasMore?: boolean }.\",\n );\n }\n return { options: result.options, hasMore: ajax.pagination ? Boolean(result.hasMore) : false };\n}\n","import type { DataItem, Option, OptionGroup } from \"./types\";\n\nexport function isGroup(item: DataItem): item is OptionGroup {\n return (item as OptionGroup).options !== undefined;\n}\n\n// Disabled descendants are excluded from `navItems` (see buildRows in\n// ForgeSelect.ts) and so can never be toggled back off by the user through\n// the UI — cascading a parent's (de)selection onto them would strand them\n// permanently selected. Their own children remain independently selectable\n// (only the disabled node itself is skipped), matching buildRows' rendering.\nexport function collectDescendantValues(option: Option): string[] {\n if (!option.children) return [];\n const values: string[] = [];\n for (const child of option.children) {\n if (!child.disabled) values.push(child.value);\n values.push(...collectDescendantValues(child));\n }\n return values;\n}\n\nexport function computeCheckState(option: Option, selected: string[]): \"none\" | \"some\" | \"all\" {\n if (!option.children?.length) return selected.includes(option.value) ? \"all\" : \"none\";\n const states = option.children.filter((child) => !child.disabled).map((child) => computeCheckState(child, selected));\n if (states.length === 0) return \"none\";\n if (states.every((state) => state === \"all\")) return \"all\";\n if (states.every((state) => state === \"none\")) return \"none\";\n return \"some\";\n}\n\nexport function findOption(items: DataItem[], value: string): Option | undefined {\n const search = (options: Option[]): Option | undefined => {\n for (const option of options) {\n if (option.value === value) return option;\n const found = option.children ? search(option.children) : undefined;\n if (found) return found;\n }\n return undefined;\n };\n for (const item of items) {\n const found = search(isGroup(item) ? item.options : [item]);\n if (found) return found;\n }\n return undefined;\n}\n\nexport function syncTreeAncestors(items: DataItem[], selected: string[]): void {\n const sync = (option: Option): void => {\n if (!option.children?.length) return;\n for (const child of option.children) sync(child);\n const state = computeCheckState(option, selected);\n const index = selected.indexOf(option.value);\n if (state === \"all\" && index === -1) selected.push(option.value);\n else if (state !== \"all\" && index !== -1) selected.splice(index, 1);\n };\n for (const item of items) (isGroup(item) ? item.options : [item]).forEach(sync);\n}\n\nexport function collectValues(items: DataItem[]): Set<string> {\n const values = new Set<string>();\n const visit = (option: Option): void => {\n values.add(option.value);\n option.children?.forEach(visit);\n };\n for (const item of items) (isGroup(item) ? item.options : [item]).forEach(visit);\n return values;\n}\n\nexport function arraysEqual(a: string[], b: string[]): boolean {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n}\n","import { Emitter, type Handler } from \"./emitter\";\nimport { format, getStrings, type Strings } from \"./i18n\";\nimport { parseNativeOptions } from \"./native-select\";\nimport { renderOptionContent } from \"./option-renderer\";\nimport { buildUrl, normalizeRemoteResult } from \"./remote\";\nimport {\n arraysEqual,\n collectDescendantValues,\n collectValues,\n computeCheckState,\n findOption as findDataOption,\n isGroup,\n syncTreeAncestors as syncDataTreeAncestors,\n} from \"./selection\";\nimport type {\n AjaxConfig,\n DataItem,\n ForgeSelectEvent,\n ForgeSelectOptions,\n ForgeSelectPlugin,\n ForgeSelectValue,\n Option,\n SetValueOptions,\n TemplateFn,\n} from \"./types\";\n\ntype Row =\n | { kind: \"group\"; label: string }\n | { kind: \"option\"; option: Option; navIndex: number; depth: number; hasChildren: boolean }\n | { kind: \"create\"; navIndex: number }\n | { kind: \"empty\" }\n | { kind: \"error\" }\n | { kind: \"loading\" }\n | { kind: \"loading-more\" };\n\ntype NavItem = { kind: \"option\"; option: Option; parentValue?: string } | { kind: \"create\" };\n\ninterface ResolvedOptions {\n placeholder: string;\n searchable: boolean;\n multiple: boolean;\n clearable: boolean;\n allowCreate: boolean;\n sortable: boolean;\n theme: string;\n disabled: boolean;\n data?: DataItem[];\n ajax?: AjaxConfig;\n templateResult?: TemplateFn;\n templateSelection?: TemplateFn;\n virtualScroll: boolean | undefined;\n itemHeight: number;\n language: string | Record<string, string>;\n plugins: ForgeSelectPlugin[];\n}\n\nconst DEFAULT_ITEM_HEIGHT = 36;\nconst VIRTUAL_BUFFER = 5;\nconst VIRTUAL_THRESHOLD = 100;\nconst ROW_CACHE_LIMIT = 2000;\n\nlet uidCounter = 0;\n\nexport default class ForgeSelect {\n /** The original element ForgeSelect was mounted on. */\n readonly el: HTMLElement;\n\n private opts: ResolvedOptions;\n private strings: Strings;\n private data: DataItem[];\n private selected: string[] = [];\n private selectedOptions = new Map<string, Option>();\n private suppressNextTagClick = false;\n private emitter = new Emitter();\n private plugins: ForgeSelectPlugin[];\n\n private uid = `forge-select-${++uidCounter}`;\n private root!: HTMLDivElement;\n private control!: HTMLDivElement;\n private valueEl!: HTMLDivElement;\n private clearBtn!: HTMLButtonElement;\n private dropdown!: HTMLDivElement;\n private searchInput: HTMLInputElement | null = null;\n private list!: HTMLUListElement;\n private liveRegion!: HTMLDivElement;\n\n private isOpen = false;\n private isDisabled = false;\n private destroyed = false;\n private query = \"\";\n private rows: Row[] = [];\n private navItems: NavItem[] = [];\n private highlightedIndex = -1;\n private rowContentCache = new Map<string, Node>();\n private expandedValues = new Set<string>();\n\n private loading = false;\n private loadingMore = false;\n private page = 0;\n private hasMore = true;\n private ajaxTimer: ReturnType<typeof setTimeout> | null = null;\n private ajaxRequestId = 0;\n private ajaxController: AbortController | null = null;\n private remoteLoaded = false;\n private loadError: Error | null = null;\n private originalDisplay = \"\";\n private originalDisabled = false;\n private nativeSelect: HTMLSelectElement | null = null;\n private nativeForm: HTMLFormElement | null = null;\n private syncingNative = false;\n\n private onDocumentMouseDown = (event: MouseEvent): void => {\n if (!this.root.contains(event.target as Node)) this.close();\n };\n\n private onNativeChange = (): void => {\n if (!this.nativeSelect || this.destroyed || this.syncingNative) return;\n const values = Array.from(this.nativeSelect.selectedOptions, (option) => option.value);\n this.applyNativeValues(values);\n };\n\n private applyNativeValues(values: string[]): void {\n this.selected = [];\n for (const value of this.opts.multiple ? values : values.slice(0, 1)) this.selectValue(value, false);\n this.renderValue();\n if (this.isOpen) this.renderList();\n this.emitter.emit(\"change\", this.getValue());\n }\n\n private onFormReset = (): void => {\n if (!this.nativeSelect || this.destroyed) return;\n const defaults = Array.from(this.nativeSelect.options)\n .filter((option) => option.defaultSelected)\n .map((option) => option.value);\n this.applyNativeValues(defaults);\n };\n\n constructor(target: string | HTMLElement, options: ForgeSelectOptions = {}) {\n const el = typeof target === \"string\" ? document.querySelector<HTMLElement>(target) : target;\n if (!el) {\n throw new Error(`ForgeSelect: target element not found: ${String(target)}`);\n }\n this.el = el;\n\n const nativeSelect = el instanceof HTMLSelectElement ? el : null;\n this.nativeSelect = nativeSelect;\n this.nativeForm = nativeSelect?.form ?? null;\n this.originalDisplay = el.style.display;\n this.originalDisabled = nativeSelect?.disabled ?? false;\n this.opts = {\n placeholder: options.placeholder ?? \"\",\n searchable: options.searchable ?? true,\n multiple: options.multiple ?? nativeSelect?.multiple ?? false,\n clearable: options.clearable ?? false,\n allowCreate: options.allowCreate ?? false,\n sortable: options.sortable ?? false,\n theme: options.theme ?? \"default\",\n disabled: options.disabled ?? nativeSelect?.disabled ?? false,\n data: options.data,\n ajax: options.ajax,\n templateResult: options.templateResult,\n templateSelection: options.templateSelection,\n virtualScroll: options.virtualScroll,\n itemHeight: options.itemHeight ?? DEFAULT_ITEM_HEIGHT,\n language: options.language ?? \"en\",\n plugins: options.plugins ?? [],\n };\n this.strings = getStrings(this.opts.language);\n this.plugins = this.opts.plugins;\n\n this.data = this.opts.data ?? (nativeSelect ? parseNativeOptions(nativeSelect) : []);\n if (nativeSelect && !this.opts.data) {\n const nativeOptions = Array.from(nativeSelect.options);\n const hasIntentionalSelection =\n nativeSelect.multiple ||\n nativeSelect.selectedIndex > 0 ||\n nativeOptions.some((option) => option.defaultSelected);\n for (const option of nativeOptions) {\n if (hasIntentionalSelection && option.selected) this.selectValue(option.value, false);\n }\n }\n\n this.buildDom();\n this.renderValue();\n if (this.opts.disabled) this.disable();\n nativeSelect?.addEventListener(\"change\", this.onNativeChange);\n this.nativeForm?.addEventListener(\"reset\", this.onFormReset);\n\n for (const plugin of this.plugins) plugin.onInit?.(this);\n }\n\n // ---------------------------------------------------------------- public API\n\n open(): void {\n if (this.isOpen || this.isDisabled || this.destroyed) return;\n this.isOpen = true;\n this.dropdown.hidden = false;\n this.root.classList.add(\"forge-select--open\");\n this.control.setAttribute(\"aria-expanded\", \"true\");\n document.addEventListener(\"mousedown\", this.onDocumentMouseDown);\n\n if (this.opts.ajax && !this.remoteLoaded) {\n this.scheduleRemoteLoad(this.query, 0);\n }\n this.renderList();\n if (this.searchInput) this.searchInput.focus();\n\n this.emitter.emit(\"open\");\n for (const plugin of this.plugins) plugin.onOpen?.(this);\n }\n\n close(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.dropdown.hidden = true;\n this.root.classList.remove(\"forge-select--open\");\n this.control.setAttribute(\"aria-expanded\", \"false\");\n document.removeEventListener(\"mousedown\", this.onDocumentMouseDown);\n this.highlightedIndex = -1;\n if (this.searchInput) {\n this.searchInput.value = \"\";\n this.query = \"\";\n }\n\n this.emitter.emit(\"close\");\n for (const plugin of this.plugins) plugin.onClose?.(this);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.close();\n for (const plugin of this.plugins) plugin.onDestroy?.(this);\n this.destroyed = true;\n if (this.ajaxTimer) clearTimeout(this.ajaxTimer);\n this.ajaxController?.abort();\n this.nativeSelect?.removeEventListener(\"change\", this.onNativeChange);\n this.nativeForm?.removeEventListener(\"reset\", this.onFormReset);\n this.rowContentCache.clear();\n this.root.remove();\n this.el.style.display = this.originalDisplay;\n if (this.nativeSelect) this.nativeSelect.disabled = this.originalDisabled;\n this.emitter.clear();\n }\n\n getValue(): ForgeSelectValue {\n if (this.opts.multiple) return [...this.selected];\n return this.selected[0] ?? null;\n }\n\n setValue(value: ForgeSelectValue, options: SetValueOptions = {}): void {\n const values = value == null ? [] : Array.isArray(value) ? value : [value];\n const next = this.opts.multiple ? values : values.slice(0, 1);\n if (arraysEqual(next, this.selected)) return;\n this.selected = [];\n for (const v of next) this.selectValue(v, false);\n this.afterSelectionChange(options.emitChange ?? true);\n }\n\n enable(): void {\n this.isDisabled = false;\n this.root.classList.remove(\"forge-select--disabled\");\n this.control.tabIndex = 0;\n this.control.setAttribute(\"aria-disabled\", \"false\");\n if (this.nativeSelect) this.nativeSelect.disabled = false;\n }\n\n disable(): void {\n this.close();\n this.isDisabled = true;\n this.root.classList.add(\"forge-select--disabled\");\n this.control.tabIndex = -1;\n this.control.setAttribute(\"aria-disabled\", \"true\");\n if (this.nativeSelect) this.nativeSelect.disabled = true;\n }\n\n on(event: ForgeSelectEvent, handler: Handler): void {\n this.emitter.on(event, handler);\n }\n\n off(event: ForgeSelectEvent, handler: Handler): void {\n this.emitter.off(event, handler);\n }\n\n // ---------------------------------------------------------------- DOM setup\n\n /**\n * The original target (a hidden native <select> or a plain mount div) can\n * carry an accessible name via aria-label/aria-labelledby, or via a\n * <label for> pointing at its id — but once `this.el` is display:none it\n * drops out of the accessibility tree, so any such association silently\n * stops reaching assistive tech unless we forward it onto the visible,\n * interactive `this.control` ourselves.\n */\n private applyAccessibleName(): void {\n const ariaLabelledby = this.el.getAttribute(\"aria-labelledby\");\n const ariaLabel = this.el.getAttribute(\"aria-label\");\n if (ariaLabelledby) {\n this.control.setAttribute(\"aria-labelledby\", ariaLabelledby);\n } else if (ariaLabel) {\n this.control.setAttribute(\"aria-label\", ariaLabel);\n } else if (this.el.id) {\n const label = Array.from(document.getElementsByTagName(\"label\")).find((el) => el.htmlFor === this.el.id);\n if (label) {\n if (!label.id) label.id = `${this.uid}-label`;\n this.control.setAttribute(\"aria-labelledby\", label.id);\n }\n }\n }\n\n private buildDom(): void {\n this.root = document.createElement(\"div\");\n this.root.className = \"forge-select\";\n this.root.dataset.theme = this.opts.theme;\n this.root.style.setProperty(\"--fs-item-height\", `${this.opts.itemHeight}px`);\n if (this.opts.sortable && this.opts.multiple) this.root.classList.add(\"forge-select--sortable\");\n\n this.control = document.createElement(\"div\");\n this.control.className = \"forge-select__control\";\n this.control.setAttribute(\"role\", \"combobox\");\n this.control.setAttribute(\"aria-haspopup\", \"listbox\");\n this.control.setAttribute(\"aria-expanded\", \"false\");\n this.control.setAttribute(\"aria-controls\", `${this.uid}-list`);\n this.control.tabIndex = 0;\n this.applyAccessibleName();\n\n this.valueEl = document.createElement(\"div\");\n this.valueEl.className = \"forge-select__value\";\n\n this.clearBtn = document.createElement(\"button\");\n this.clearBtn.type = \"button\";\n this.clearBtn.className = \"forge-select__clear\";\n this.clearBtn.setAttribute(\"aria-label\", this.strings.clearSelection);\n this.clearBtn.textContent = \"×\";\n this.clearBtn.hidden = true;\n\n const arrow = document.createElement(\"span\");\n arrow.className = \"forge-select__arrow\";\n arrow.setAttribute(\"aria-hidden\", \"true\");\n\n this.control.append(this.valueEl, this.clearBtn, arrow);\n\n this.dropdown = document.createElement(\"div\");\n this.dropdown.className = \"forge-select__dropdown\";\n this.dropdown.hidden = true;\n\n if (this.opts.searchable) {\n this.searchInput = document.createElement(\"input\");\n this.searchInput.type = \"search\";\n this.searchInput.className = \"forge-select__search\";\n this.searchInput.setAttribute(\"aria-label\", this.strings.search);\n this.searchInput.setAttribute(\"aria-autocomplete\", \"list\");\n this.searchInput.setAttribute(\"aria-controls\", `${this.uid}-list`);\n this.dropdown.append(this.searchInput);\n }\n\n this.list = document.createElement(\"ul\");\n this.list.className = \"forge-select__list\";\n this.list.id = `${this.uid}-list`;\n this.list.setAttribute(\"role\", \"listbox\");\n if (this.opts.multiple) this.list.setAttribute(\"aria-multiselectable\", \"true\");\n this.dropdown.append(this.list);\n\n this.liveRegion = document.createElement(\"div\");\n this.liveRegion.className = \"forge-select__sr-only\";\n this.liveRegion.setAttribute(\"role\", \"status\");\n this.liveRegion.setAttribute(\"aria-live\", \"polite\");\n\n this.root.append(this.control, this.dropdown, this.liveRegion);\n this.el.style.display = \"none\";\n this.el.insertAdjacentElement(\"afterend\", this.root);\n\n this.bindEvents();\n }\n\n private bindEvents(): void {\n this.control.addEventListener(\"click\", (event) => {\n if (event.target === this.clearBtn) return;\n if (this.suppressNextTagClick) {\n this.suppressNextTagClick = false;\n return;\n }\n if (this.isDisabled) return;\n if (this.isOpen) this.close();\n else this.open();\n });\n\n this.control.addEventListener(\"keydown\", (event) => this.handleKeydown(event));\n\n this.clearBtn.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n this.clearSelection();\n });\n\n if (this.searchInput) {\n this.searchInput.addEventListener(\"input\", () => {\n this.query = this.searchInput!.value;\n this.highlightedIndex = -1;\n this.list.scrollTop = 0;\n this.emitter.emit(\"search\", this.query);\n if (this.opts.ajax) {\n this.scheduleRemoteLoad(this.query, this.opts.ajax.debounce ?? 250);\n } else {\n this.renderList();\n }\n });\n this.searchInput.addEventListener(\"keydown\", (event) => this.handleKeydown(event));\n }\n\n this.list.addEventListener(\"click\", (event) => {\n const target = event.target as HTMLElement;\n const twisty = target.closest<HTMLElement>(\"[data-twisty]\");\n if (twisty) {\n const value = twisty.dataset.twisty!;\n if (this.expandedValues.has(value)) this.expandedValues.delete(value);\n else this.expandedValues.add(value);\n this.renderList();\n return;\n }\n const li = target.closest<HTMLLIElement>(\"li[data-nav-index]\");\n if (!li) return;\n const navIndex = Number(li.dataset.navIndex);\n this.activateNavItem(navIndex);\n });\n\n this.list.addEventListener(\"scroll\", () => {\n if (this.usesVirtualScroll()) this.renderRows();\n this.maybeLoadNextPage();\n });\n }\n\n private handleKeydown(event: KeyboardEvent): void {\n if (this.isDisabled) return;\n switch (event.key) {\n case \"Enter\":\n event.preventDefault();\n if (!this.isOpen) this.open();\n else if (this.highlightedIndex >= 0) this.activateNavItem(this.highlightedIndex);\n break;\n case \" \":\n if (event.target === this.control) {\n event.preventDefault();\n if (!this.isOpen) this.open();\n }\n break;\n case \"ArrowDown\":\n event.preventDefault();\n if (!this.isOpen) this.open();\n else this.moveHighlight(1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (this.isOpen) this.moveHighlight(-1);\n break;\n case \"Escape\":\n if (this.isOpen) {\n event.preventDefault();\n this.close();\n this.control.focus();\n }\n break;\n case \"ArrowRight\":\n if (this.isOpen && this.navigateTree(\"right\")) event.preventDefault();\n break;\n case \"ArrowLeft\":\n if (this.isOpen && this.navigateTree(\"left\")) event.preventDefault();\n break;\n case \"Tab\":\n this.close();\n break;\n }\n }\n\n // ---------------------------------------------------------------- selection\n\n private selectValue(value: string, notify: boolean): void {\n if (this.selected.includes(value)) return;\n const option = this.findOption(value) ?? this.selectedOptions.get(value) ?? { value, label: value };\n this.selectedOptions.set(value, option);\n if (this.opts.multiple) {\n this.selected.push(value);\n // Selecting a tree node cascades to its descendants too; for a plain\n // option (no children) this is a no-op.\n for (const v of collectDescendantValues(option)) {\n if (!this.selected.includes(v)) this.selected.push(v);\n }\n this.syncTreeAncestors();\n } else {\n this.selected = [value];\n }\n if (notify) this.afterSelectionChange();\n }\n\n private deselectValue(value: string, notify: boolean): void {\n const index = this.selected.indexOf(value);\n if (index === -1) return;\n this.selected.splice(index, 1);\n if (this.opts.multiple) {\n const option = this.findOption(value) ?? this.selectedOptions.get(value);\n if (option) {\n for (const v of collectDescendantValues(option)) {\n const i = this.selected.indexOf(v);\n if (i !== -1) this.selected.splice(i, 1);\n }\n }\n this.syncTreeAncestors();\n }\n if (notify) this.afterSelectionChange();\n }\n\n /**\n * Keeps every tree parent's own membership in `selected` consistent with\n * its descendants (post-order, so parents see already-corrected children):\n * a parent counts as selected only when `computeCheckState` says \"all\".\n * No-op for data with no `children` anywhere.\n */\n private syncTreeAncestors(): void {\n syncDataTreeAncestors(this.data, this.selected);\n }\n\n private clearSelection(): void {\n if (this.selected.length === 0) return;\n this.selected = [];\n this.emitter.emit(\"clear\");\n this.afterSelectionChange();\n }\n\n private afterSelectionChange(emitChange = true): void {\n this.renderValue();\n this.syncNativeSelect(emitChange);\n if (this.isOpen) this.renderList();\n if (emitChange) this.emitter.emit(\"change\", this.getValue());\n }\n\n private syncNativeSelect(dispatchChange = true): void {\n if (!(this.el instanceof HTMLSelectElement)) return;\n const existing = new Set<string>();\n for (const option of Array.from(this.el.options)) {\n existing.add(option.value);\n option.selected = this.selected.includes(option.value);\n }\n for (const value of this.selected) {\n if (existing.has(value)) continue;\n const option = document.createElement(\"option\");\n option.value = value;\n option.textContent = this.selectedOptions.get(value)?.label ?? value;\n option.selected = true;\n this.el.append(option);\n }\n if (this.opts.sortable && this.opts.multiple) {\n // Re-appending in `this.selected` order moves each selected <option> to\n // the end in that relative order, so a real <select multiple> form\n // submission serializes values in the dragged order (unselected options\n // simply end up interleaved before them, which submission ignores).\n for (const value of this.selected) {\n const option = Array.from(this.el.options).find((o) => o.value === value);\n if (option) this.el.append(option);\n }\n }\n if (!dispatchChange) return;\n this.syncingNative = true;\n try {\n this.el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } finally {\n this.syncingNative = false;\n }\n }\n\n private findOption(value: string): Option | undefined {\n return findDataOption(this.data, value);\n }\n\n private createFromQuery(): void {\n const label = this.query.trim();\n if (!label) return;\n const option: Option = { value: label, label };\n this.data.push(option);\n if (this.searchInput) {\n this.searchInput.value = \"\";\n this.query = \"\";\n }\n this.selectValue(option.value, true);\n if (!this.opts.multiple) this.close();\n }\n\n private activateNavItem(navIndex: number): void {\n const item = this.navItems[navIndex];\n if (!item) return;\n if (item.kind === \"create\") {\n this.createFromQuery();\n return;\n }\n const { value } = item.option;\n if (this.opts.multiple) {\n if (this.selected.includes(value)) this.deselectValue(value, true);\n else this.selectValue(value, true);\n } else {\n this.selectValue(value, true);\n this.close();\n this.control.focus();\n }\n }\n\n // ---------------------------------------------------------------- rendering\n\n private renderValue(): void {\n this.valueEl.textContent = \"\";\n const hasValue = this.selected.length > 0;\n this.clearBtn.hidden = !(this.opts.clearable && hasValue);\n\n if (!hasValue) {\n const placeholder = document.createElement(\"span\");\n placeholder.className = \"forge-select__placeholder\";\n placeholder.textContent = this.opts.placeholder;\n this.valueEl.append(placeholder);\n return;\n }\n\n if (this.opts.multiple) {\n for (const value of this.selected) {\n const option = this.selectedOptions.get(value) ?? { value, label: value };\n const tag = document.createElement(\"span\");\n tag.className = \"forge-select__tag\";\n const label = document.createElement(\"span\");\n label.className = \"forge-select__tag-label\";\n renderOptionContent(label, option, this.opts.templateSelection, \"inline\");\n const remove = document.createElement(\"button\");\n remove.type = \"button\";\n remove.className = \"forge-select__tag-remove\";\n remove.setAttribute(\"aria-label\", format(this.strings.removeItem, { label: option.label }));\n remove.textContent = \"×\";\n remove.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (!this.isDisabled) this.deselectValue(value, true);\n });\n tag.append(label, remove);\n if (this.opts.sortable) {\n tag.dataset.value = value;\n tag.tabIndex = 0;\n tag.setAttribute(\"aria-roledescription\", \"draggable item\");\n tag.setAttribute(\"aria-label\", format(this.strings.reorderHint, { label: option.label }));\n tag.addEventListener(\"keydown\", (event) => this.handleTagKeydown(event, value));\n this.bindTagDrag(tag, value);\n }\n this.valueEl.append(tag);\n }\n } else {\n const option = this.selectedOptions.get(this.selected[0]) ?? {\n value: this.selected[0],\n label: this.selected[0],\n };\n const span = document.createElement(\"span\");\n span.className = \"forge-select__single-value\";\n renderOptionContent(span, option, this.opts.templateSelection, \"inline\");\n this.valueEl.append(span);\n }\n }\n\n /**\n * Pointer-based (mouse/touch/pen) reorder for a single tag. Only the real\n * dragged DOM node is moved during the gesture — a full renderValue()\n * mid-drag would destroy it — so the reordered `this.selected` is only\n * committed on release. The move/up listeners and pointer capture live on\n * the stable `this.valueEl` container rather than the tag itself: `tag`\n * gets repositioned via `insertBefore` during the drag, and browsers treat\n * that reparenting as detaching the node, which silently drops pointer\n * capture (and further move events) if it were captured on `tag`.\n */\n private bindTagDrag(tag: HTMLSpanElement, value: string): void {\n const DRAG_THRESHOLD = 4;\n let startX = 0;\n let dragging = false;\n let order: string[] = [];\n\n const onPointerMove = (event: PointerEvent): void => {\n if (!dragging) {\n if (Math.abs(event.clientX - startX) < DRAG_THRESHOLD) return;\n dragging = true;\n order = [...this.selected];\n if (typeof this.valueEl.setPointerCapture === \"function\") {\n this.valueEl.setPointerCapture(event.pointerId);\n }\n tag.classList.add(\"forge-select__tag--dragging\");\n }\n event.preventDefault();\n\n const draggedIndex = order.indexOf(value);\n const siblings = Array.from(this.valueEl.querySelectorAll<HTMLElement>(\".forge-select__tag\"));\n for (const sibling of siblings) {\n if (sibling === tag) continue;\n const siblingValue = sibling.dataset.value;\n if (!siblingValue) continue;\n const siblingIndex = order.indexOf(siblingValue);\n if (siblingIndex === -1) continue;\n const rect = sibling.getBoundingClientRect();\n const midX = rect.left + rect.width / 2;\n const movingRight = draggedIndex < siblingIndex;\n const crossed = movingRight ? event.clientX > midX : event.clientX < midX;\n if (!crossed) continue;\n order.splice(draggedIndex, 1);\n order.splice(siblingIndex, 0, value);\n if (movingRight) this.valueEl.insertBefore(tag, sibling.nextSibling);\n else this.valueEl.insertBefore(tag, sibling);\n break;\n }\n };\n\n const finishDrag = (event: PointerEvent): void => {\n this.valueEl.removeEventListener(\"pointermove\", onPointerMove);\n this.valueEl.removeEventListener(\"pointerup\", finishDrag);\n this.valueEl.removeEventListener(\"pointercancel\", finishDrag);\n if (!dragging) return;\n if (typeof this.valueEl.releasePointerCapture === \"function\") {\n this.valueEl.releasePointerCapture(event.pointerId);\n }\n tag.classList.remove(\"forge-select__tag--dragging\");\n this.selected = order;\n this.suppressNextTagClick = true;\n this.afterSelectionChange();\n };\n\n tag.addEventListener(\"pointerdown\", (event) => {\n if (this.isDisabled || event.button !== 0) return;\n if ((event.target as HTMLElement).closest(\".forge-select__tag-remove\")) return;\n startX = event.clientX;\n dragging = false;\n this.valueEl.addEventListener(\"pointermove\", onPointerMove);\n this.valueEl.addEventListener(\"pointerup\", finishDrag);\n this.valueEl.addEventListener(\"pointercancel\", finishDrag);\n });\n }\n\n /** Alt+Left/Alt+Right on a focused tag: the keyboard-operable equivalent of dragging. */\n private handleTagKeydown(event: KeyboardEvent, value: string): void {\n if (!event.altKey || (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\")) return;\n const index = this.selected.indexOf(value);\n const targetIndex = event.key === \"ArrowLeft\" ? index - 1 : index + 1;\n if (index === -1 || targetIndex < 0 || targetIndex >= this.selected.length) return;\n event.preventDefault();\n event.stopPropagation();\n const next = [...this.selected];\n [next[index], next[targetIndex]] = [next[targetIndex], next[index]];\n this.selected = next;\n this.afterSelectionChange();\n this.focusTagByValue(value);\n }\n\n private focusTagByValue(value: string): void {\n for (const tag of Array.from(this.valueEl.querySelectorAll<HTMLElement>(\".forge-select__tag\"))) {\n if (tag.dataset.value === value) {\n tag.focus();\n return;\n }\n }\n }\n\n private buildRows(): void {\n this.rows = [];\n this.navItems = [];\n const query = this.query.trim().toLowerCase();\n const matches = (option: Option): boolean =>\n query === \"\" ||\n option.label.toLowerCase().includes(query) ||\n (option.description?.toLowerCase().includes(query) ?? false);\n\n // A tree node is visible while searching if it matches, or any descendant\n // does (leaf options with no children just reduce to `matches()`).\n const subtreeMatches = (option: Option): boolean =>\n query === \"\" || matches(option) || (option.children ?? []).some(subtreeMatches);\n\n const pushOption = (option: Option, depth: number, parentValue?: string): void => {\n let navIndex = -1;\n if (!option.disabled) {\n navIndex = this.navItems.length;\n this.navItems.push({ kind: \"option\", option, parentValue });\n }\n const hasChildren = !!option.children && option.children.length > 0;\n this.rows.push({ kind: \"option\", option, navIndex, depth, hasChildren });\n if (hasChildren) {\n // Expanding is ephemeral while searching (never written to\n // expandedValues), so clearing the query restores manual state.\n const expanded = query !== \"\" || this.expandedValues.has(option.value);\n if (expanded) {\n for (const child of option.children!) {\n if (subtreeMatches(child)) pushOption(child, depth + 1, option.value);\n }\n }\n }\n };\n\n if (this.loading) {\n this.rows.push({ kind: \"loading\" });\n return;\n }\n if (this.loadError) {\n this.rows.push({ kind: \"error\" });\n return;\n }\n\n for (const item of this.data) {\n if (isGroup(item)) {\n const visible = item.options.filter(subtreeMatches);\n if (visible.length === 0) continue;\n this.rows.push({ kind: \"group\", label: item.label });\n visible.forEach((o) => pushOption(o, 0));\n } else if (subtreeMatches(item)) {\n pushOption(item, 0);\n }\n }\n\n if (this.opts.allowCreate && query !== \"\" && !this.hasExactMatch(query)) {\n const navIndex = this.navItems.length;\n this.navItems.push({ kind: \"create\" });\n this.rows.push({ kind: \"create\", navIndex });\n }\n\n if (this.rows.length === 0) this.rows.push({ kind: \"empty\" });\n else if (this.loadingMore) this.rows.push({ kind: \"loading-more\" });\n }\n\n private hasExactMatch(lowerQuery: string): boolean {\n const matchesExactly = (option: Option): boolean =>\n option.label.toLowerCase() === lowerQuery || (option.children ?? []).some(matchesExactly);\n for (const item of this.data) {\n const options = isGroup(item) ? item.options : [item];\n if (options.some(matchesExactly)) return true;\n }\n return false;\n }\n\n private usesVirtualScroll(): boolean {\n return this.opts.virtualScroll !== false && this.rows.length > VIRTUAL_THRESHOLD;\n }\n\n private renderList(): void {\n this.buildRows();\n this.renderRows();\n this.announceStatus();\n }\n\n private announceStatus(): void {\n const first = this.rows[0];\n const message =\n first?.kind === \"loading\"\n ? this.strings.loading\n : first?.kind === \"error\"\n ? this.strings.errorLoading\n : first?.kind === \"empty\"\n ? this.strings.noResults\n : \"\";\n if (this.liveRegion.textContent !== message) this.liveRegion.textContent = message;\n }\n\n private renderRows(): void {\n // Capture the scroll offset and viewport height BEFORE clearing the list:\n // removing the children collapses both scrollHeight (clamping scrollTop to 0)\n // and clientHeight (the list has no explicit height, only max-height, so an\n // empty list reports just its padding instead of the real box height).\n const scrollTop = this.list.scrollTop;\n const clientHeight = this.list.clientHeight;\n const virtual = this.usesVirtualScroll();\n this.list.textContent = \"\";\n\n const rowHeight = this.opts.itemHeight;\n let start = 0;\n let end = this.rows.length;\n if (virtual) {\n const viewport = clientHeight || rowHeight * 8;\n start = Math.max(0, Math.floor(scrollTop / rowHeight) - VIRTUAL_BUFFER);\n end = Math.min(this.rows.length, start + Math.ceil(viewport / rowHeight) + VIRTUAL_BUFFER * 2);\n\n const topSpacer = document.createElement(\"li\");\n topSpacer.className = \"forge-select__spacer\";\n topSpacer.setAttribute(\"aria-hidden\", \"true\");\n topSpacer.style.height = `${start * rowHeight}px`;\n this.list.append(topSpacer);\n }\n\n for (let i = start; i < end; i++) {\n this.list.append(this.renderRow(this.rows[i]));\n }\n\n if (virtual) {\n const bottomSpacer = document.createElement(\"li\");\n bottomSpacer.className = \"forge-select__spacer\";\n bottomSpacer.setAttribute(\"aria-hidden\", \"true\");\n bottomSpacer.style.height = `${(this.rows.length - end) * rowHeight}px`;\n this.list.append(bottomSpacer);\n\n // Restore the offset that clearing clamped away. The net scroll change\n // within this handler is zero, so this does not re-fire the scroll\n // listener; even if it did, the re-render is idempotent and settles.\n if (this.list.scrollTop !== scrollTop) {\n this.list.scrollTop = scrollTop;\n }\n }\n\n this.updateActiveDescendant();\n }\n\n private renderRow(row: Row): HTMLLIElement {\n const li = document.createElement(\"li\");\n switch (row.kind) {\n case \"group\":\n li.className = \"forge-select__group-label\";\n li.setAttribute(\"role\", \"presentation\");\n li.textContent = row.label;\n break;\n case \"empty\":\n li.className = \"forge-select__empty\";\n li.setAttribute(\"role\", \"option\");\n li.setAttribute(\"aria-disabled\", \"true\");\n li.setAttribute(\"aria-selected\", \"false\");\n li.textContent = this.strings.noResults;\n break;\n case \"error\":\n li.className = \"forge-select__error\";\n li.setAttribute(\"role\", \"option\");\n li.setAttribute(\"aria-disabled\", \"true\");\n li.setAttribute(\"aria-selected\", \"false\");\n li.textContent = this.strings.errorLoading;\n break;\n case \"loading\":\n li.className = \"forge-select__loading\";\n li.setAttribute(\"role\", \"option\");\n li.setAttribute(\"aria-disabled\", \"true\");\n li.setAttribute(\"aria-selected\", \"false\");\n li.textContent = this.strings.loading;\n break;\n case \"loading-more\":\n li.className = \"forge-select__loading-more\";\n li.setAttribute(\"aria-hidden\", \"true\");\n li.textContent = this.strings.loadingMore;\n break;\n case \"create\":\n li.className = \"forge-select__option forge-select__option--create\";\n li.setAttribute(\"role\", \"option\");\n li.id = `${this.uid}-nav-${row.navIndex}`;\n li.dataset.navIndex = String(row.navIndex);\n li.textContent = format(this.strings.createOption, { query: this.query.trim() });\n if (row.navIndex === this.highlightedIndex) li.classList.add(\"forge-select__option--highlighted\");\n break;\n case \"option\": {\n li.className = \"forge-select__option\";\n li.setAttribute(\"role\", \"option\");\n const isSelected = this.selected.includes(row.option.value);\n li.setAttribute(\"aria-selected\", String(isSelected));\n if (isSelected) li.classList.add(\"forge-select__option--selected\");\n if (this.opts.multiple && row.hasChildren && computeCheckState(row.option, this.selected) === \"some\") {\n li.classList.add(\"forge-select__option--indeterminate\");\n }\n if (row.depth > 0) {\n li.style.paddingLeft = `calc(12px + ${row.depth} * var(--fs-tree-indent, 18px))`;\n }\n if (row.option.disabled) {\n li.classList.add(\"forge-select__option--disabled\");\n li.setAttribute(\"aria-disabled\", \"true\");\n } else {\n li.id = `${this.uid}-nav-${row.navIndex}`;\n li.dataset.navIndex = String(row.navIndex);\n if (row.navIndex === this.highlightedIndex) li.classList.add(\"forge-select__option--highlighted\");\n }\n if (row.hasChildren) {\n const expanded = this.query !== \"\" || this.expandedValues.has(row.option.value);\n li.setAttribute(\"aria-expanded\", String(expanded));\n const twisty = document.createElement(\"span\");\n twisty.className = \"forge-select__twisty\";\n twisty.dataset.twisty = row.option.value;\n twisty.setAttribute(\"aria-hidden\", \"true\");\n twisty.textContent = expanded ? \"▼\" : \"▶\";\n li.append(twisty);\n }\n li.append(this.optionContent(row.option));\n break;\n }\n }\n return li;\n }\n\n /**\n * Rendered row content is cached per option value and cloned on each render,\n * so templates run once per option instead of once per scroll frame.\n * State classes (selected/highlighted/disabled) live on the <li>, keeping the\n * cached content state-free.\n */\n private optionContent(option: Option): Node {\n let cached = this.rowContentCache.get(option.value);\n if (!cached) {\n const holder = document.createElement(\"span\");\n holder.className = \"forge-select__option-content\";\n renderOptionContent(holder, option, this.opts.templateResult);\n if (this.rowContentCache.size >= ROW_CACHE_LIMIT) {\n // FIFO eviction keeps memory bounded on very large lists.\n const oldest = this.rowContentCache.keys().next().value as string;\n this.rowContentCache.delete(oldest);\n }\n this.rowContentCache.set(option.value, holder);\n cached = holder;\n }\n return cached.cloneNode(true);\n }\n\n private moveHighlight(delta: number): void {\n if (this.navItems.length === 0) return;\n const next =\n this.highlightedIndex === -1\n ? delta > 0\n ? 0\n : this.navItems.length - 1\n : (this.highlightedIndex + delta + this.navItems.length) % this.navItems.length;\n this.focusNavIndex(next);\n }\n\n private focusNavIndex(next: number): void {\n this.highlightedIndex = next;\n\n if (this.usesVirtualScroll()) {\n const rowIndex = this.rows.findIndex(\n (row) => (row.kind === \"option\" || row.kind === \"create\") && row.navIndex === next,\n );\n if (rowIndex >= 0) {\n const rowHeight = this.opts.itemHeight;\n const top = rowIndex * rowHeight;\n const viewport = this.list.clientHeight || rowHeight * 8;\n let target = this.list.scrollTop;\n if (top < target) target = top;\n else if (top + rowHeight > target + viewport) target = top + rowHeight - viewport;\n if (target !== this.list.scrollTop) this.list.scrollTop = target;\n }\n this.renderRows();\n } else {\n this.renderRows();\n const highlighted = this.list.querySelector<HTMLElement>(\".forge-select__option--highlighted\");\n highlighted?.scrollIntoView?.({ block: \"nearest\" });\n }\n }\n\n private navigateTree(direction: \"left\" | \"right\"): boolean {\n const item = this.navItems[this.highlightedIndex];\n if (!item || item.kind !== \"option\") return false;\n const { option, parentValue } = item;\n const hasChildren = !!option.children?.length;\n const expanded = this.query !== \"\" || this.expandedValues.has(option.value);\n\n if (direction === \"right\") {\n if (hasChildren && !expanded) {\n this.expandedValues.add(option.value);\n this.renderList();\n return true;\n }\n if (hasChildren) {\n const childIndex = this.navItems.findIndex((nav) => nav.kind === \"option\" && nav.parentValue === option.value);\n if (childIndex >= 0) {\n this.focusNavIndex(childIndex);\n return true;\n }\n }\n return false;\n }\n\n if (hasChildren && expanded && this.query === \"\") {\n this.expandedValues.delete(option.value);\n this.renderList();\n return true;\n }\n if (parentValue) {\n const parentIndex = this.navItems.findIndex((nav) => nav.kind === \"option\" && nav.option.value === parentValue);\n if (parentIndex >= 0) {\n this.focusNavIndex(parentIndex);\n return true;\n }\n }\n return false;\n }\n\n private updateActiveDescendant(): void {\n const target = this.searchInput ?? this.control;\n if (this.highlightedIndex >= 0) {\n target.setAttribute(\"aria-activedescendant\", `${this.uid}-nav-${this.highlightedIndex}`);\n } else {\n target.removeAttribute(\"aria-activedescendant\");\n }\n }\n\n // ---------------------------------------------------------------- remote data\n\n private scheduleRemoteLoad(query: string, delay: number): void {\n if (this.ajaxTimer) clearTimeout(this.ajaxTimer);\n const requestId = ++this.ajaxRequestId;\n this.ajaxController?.abort();\n this.ajaxController = null;\n this.page = 0;\n this.hasMore = true;\n this.loading = true;\n this.loadingMore = false;\n this.loadError = null;\n this.renderList();\n this.ajaxTimer = setTimeout(() => {\n this.ajaxTimer = null;\n void this.loadRemote(query, { requestId });\n }, delay);\n }\n\n /**\n * Fires on every list scroll. Only acts when pagination is opted into via\n * `ajax.pagination`; reads real scroll geometry rather than row counts so\n * it works whether or not virtual scrolling is active for this list.\n */\n private maybeLoadNextPage(): void {\n const ajax = this.opts.ajax;\n if (!ajax?.pagination || !this.hasMore || this.loading || this.loadingMore) return;\n const { scrollHeight, scrollTop, clientHeight } = this.list;\n const threshold = this.opts.itemHeight * 2;\n if (scrollHeight - scrollTop - clientHeight >= threshold) return;\n this.loadingMore = true;\n this.renderList();\n void this.loadRemote(this.query, { append: true });\n }\n\n private async loadRemote(\n query: string,\n { append = false, requestId }: { append?: boolean; requestId?: number } = {},\n ): Promise<void> {\n const ajax = this.opts.ajax!;\n const activeRequestId = requestId ?? ++this.ajaxRequestId;\n if (activeRequestId !== this.ajaxRequestId) return;\n this.ajaxController?.abort();\n const controller = new AbortController();\n this.ajaxController = controller;\n const page = append ? this.page + 1 : 0;\n try {\n const url = buildUrl(ajax, query, page);\n const response = await fetch(url, { signal: controller.signal });\n if (response.ok === false) throw new Error(`ForgeSelect: remote request failed with HTTP ${response.status}`);\n const json: unknown = await response.json();\n if (activeRequestId !== this.ajaxRequestId || this.destroyed) return;\n const { options, hasMore } = normalizeRemoteResult(ajax, json);\n\n if (append) {\n const existing = collectValues(this.data);\n this.data = [...this.data, ...options.filter((o) => !existing.has(o.value))];\n } else {\n this.data = options;\n this.rowContentCache.clear();\n }\n this.page = page;\n this.hasMore = hasMore;\n this.remoteLoaded = true;\n this.loadError = null;\n } catch (cause) {\n if (activeRequestId !== this.ajaxRequestId || this.destroyed || controller.signal.aborted) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n if (!append) {\n this.data = [];\n this.rowContentCache.clear();\n }\n this.hasMore = false;\n this.loadError = error;\n this.emitter.emit(\"error\", error);\n } finally {\n if (activeRequestId === this.ajaxRequestId && !this.destroyed) {\n this.ajaxController = null;\n this.loading = false;\n this.loadingMore = false;\n if (this.isOpen) this.renderList();\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/emitter.ts","../src/dropdown-position.ts","../src/i18n.ts","../src/native-select.ts","../src/option-renderer.ts","../src/remote.ts","../src/remote-cache.ts","../src/search.ts","../src/selection.ts","../src/ForgeSelect.ts"],"sourcesContent":["export { default } from \"./ForgeSelect\";\nexport { default as ForgeSelect } from \"./ForgeSelect\";\nexport type {\n AjaxConfig,\n DataItem,\n ForgeSelectEvent,\n ForgeSelectEventHandler,\n ForgeSelectEventMap,\n ForgeSelectOptions,\n ForgeSelectUpdateOptions,\n ForgeSelectPlugin,\n ForgeSelectValue,\n MaximumSelectionEvent,\n Option,\n OptionGroup,\n SetValueOptions,\n SetSearchQueryOptions,\n SearchField,\n SearchScorer,\n TemplateFn,\n} from \"./types\";\n","export type Handler = (...args: unknown[]) => void;\n\nexport class Emitter {\n private handlers = new Map<string, Set<Handler>>();\n\n on(event: string, handler: Handler): void {\n let set = this.handlers.get(event);\n if (!set) {\n set = new Set();\n this.handlers.set(event, set);\n }\n set.add(handler);\n }\n\n off(event: string, handler: Handler): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n emit(event: string, ...args: unknown[]): void {\n const set = this.handlers.get(event);\n if (!set) return;\n for (const handler of [...set]) handler(...args);\n }\n\n clear(): void {\n this.handlers.clear();\n }\n}\n","export interface DropdownPlacement {\n dropUp: boolean;\n top: number;\n}\n\n/** Pure geometry used by both inline and portalled dropdown positioning. */\nexport function computeDropdownPlacement(\n controlRect: Pick<DOMRect, \"top\" | \"bottom\">,\n dropdownHeight: number,\n viewportHeight: number,\n gap = 4,\n): DropdownPlacement {\n const spaceBelow = viewportHeight - controlRect.bottom;\n const spaceAbove = controlRect.top;\n const dropUp = dropdownHeight > spaceBelow && spaceAbove > spaceBelow;\n return {\n dropUp,\n top: dropUp ? controlRect.top - dropdownHeight - gap : controlRect.bottom + gap,\n };\n}\n","export type Strings = Record<string, string>;\n\nconst locales: Record<string, Strings> = {\n en: {\n noResults: \"No results found\",\n loading: \"Loading…\",\n loadingMore: \"Loading more…\",\n errorLoading: \"Could not load options\",\n createOption: 'Create \"{query}\"',\n clearSelection: \"Clear selection\",\n removeItem: \"Remove {label}\",\n search: \"Search\",\n reorderHint: \"{label}. Press Alt+Left or Alt+Right to reorder.\",\n minSearchLength: \"Type {count} or more characters to search\",\n maximumSelected: \"Maximum of {count} selections reached\",\n },\n vi: {\n noResults: \"Không tìm thấy kết quả\",\n loading: \"Đang tải…\",\n loadingMore: \"Đang tải thêm…\",\n errorLoading: \"Không thể tải tùy chọn\",\n createOption: 'Tạo \"{query}\"',\n clearSelection: \"Xóa lựa chọn\",\n removeItem: \"Xóa {label}\",\n search: \"Tìm kiếm\",\n reorderHint: \"{label}. Nhấn Alt+Trái hoặc Alt+Phải để sắp xếp lại.\",\n minSearchLength: \"Nhập thêm {count} ký tự để tìm kiếm\",\n maximumSelected: \"Đã đạt tối đa {count} lựa chọn\",\n },\n};\n\nexport function getStrings(language: string | Strings): Strings {\n if (typeof language === \"string\") {\n return locales[language] ?? locales.en;\n }\n return { ...locales.en, ...language };\n}\n\nexport function format(template: string, vars: Record<string, string>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) => vars[key] ?? match);\n}\n","import type { DataItem, Option } from \"./types\";\n\nexport function parseNativeOptions(select: HTMLSelectElement): DataItem[] {\n const data: DataItem[] = [];\n for (const child of Array.from(select.children)) {\n if (child instanceof HTMLOptGroupElement) {\n data.push({ label: child.label, options: Array.from(child.querySelectorAll(\"option\")).map(parseOption) });\n } else if (child instanceof HTMLOptionElement) {\n data.push(parseOption(child));\n }\n }\n return data;\n}\n\nfunction parseOption(option: HTMLOptionElement): Option {\n const groupDisabled = option.parentElement instanceof HTMLOptGroupElement && option.parentElement.disabled;\n return {\n value: option.value,\n label: option.textContent?.trim() ?? option.value,\n disabled: option.disabled || groupDisabled || undefined,\n };\n}\n","import type { Option, TemplateFn } from \"./types\";\n\nexport type OptionRenderVariant = \"row\" | \"inline\";\n\n/** Render one option without coupling presentation details to the select controller. */\nexport function renderOptionContent(\n container: HTMLElement,\n option: Option,\n template?: TemplateFn,\n variant: OptionRenderVariant = \"row\",\n): void {\n if (template) {\n const result = template(option);\n if (typeof result === \"string\") container.innerHTML = result;\n else container.append(result);\n return;\n }\n if (!option.avatar && !option.description) {\n container.textContent = option.label;\n return;\n }\n\n // Built-in rich rendering only uses textContent/attribute assignment.\n if (option.avatar) {\n const avatar = document.createElement(\"img\");\n avatar.className = variant === \"row\" ? \"forge-select__option-avatar\" : \"forge-select__inline-avatar\";\n avatar.src = option.avatar;\n avatar.alt = \"\";\n avatar.setAttribute(\"loading\", \"lazy\");\n avatar.setAttribute(\"decoding\", \"async\");\n container.append(avatar);\n }\n if (variant === \"row\" && option.description) {\n const body = document.createElement(\"span\");\n body.className = \"forge-select__option-body\";\n const label = document.createElement(\"span\");\n label.className = \"forge-select__option-label\";\n label.textContent = option.label;\n const description = document.createElement(\"span\");\n description.className = \"forge-select__option-desc\";\n description.textContent = option.description;\n body.append(label, description);\n container.append(body);\n } else {\n const label = document.createElement(\"span\");\n label.className = \"forge-select__option-label\";\n label.textContent = option.label;\n container.append(label);\n }\n}\n","import type { AjaxConfig, Option } from \"./types\";\n\nexport function buildUrl(ajax: AjaxConfig, query: string, page: number): string {\n if (!ajax.url) throw new Error(\"ForgeSelect: ajax requires either url or request.\");\n if (typeof ajax.url === \"function\") return ajax.url(query, page);\n if (!ajax.params) return ajax.url;\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(ajax.params(query, page))) params.set(key, String(value));\n const separator = ajax.url.includes(\"?\") ? \"&\" : \"?\";\n return `${ajax.url}${separator}${params.toString()}`;\n}\n\nexport function normalizeRemoteResult(ajax: AjaxConfig, response: unknown): { options: Option[]; hasMore: boolean } {\n const result = ajax.transform ? ajax.transform(response) : (response as Option[]);\n if (Array.isArray(result)) return { options: result, hasMore: false };\n if (!result || !Array.isArray((result as { options?: unknown }).options)) {\n throw new Error(\n \"ForgeSelect: ajax.transform must return an array of options, or an object shaped like { options: Option[], hasMore?: boolean }.\",\n );\n }\n return { options: result.options, hasMore: ajax.pagination ? Boolean(result.hasMore) : false };\n}\n","export interface RemoteCacheEntry<T> {\n value: T;\n expiresAt: number;\n}\n\nexport class RemoteCache<T> {\n private entries = new Map<string, RemoteCacheEntry<T>>();\n\n get(key: string, now = Date.now()): T | undefined {\n const entry = this.entries.get(key);\n if (!entry) return undefined;\n if (entry.expiresAt <= now) {\n this.entries.delete(key);\n return undefined;\n }\n return entry.value;\n }\n\n set(key: string, value: T, ttl: number, now = Date.now()): void {\n if (ttl > 0) this.entries.set(key, { value, expiresAt: now + ttl });\n }\n\n clear(): void {\n this.entries.clear();\n }\n}\n","import type { Option, SearchField, SearchScorer } from \"./types\";\n\nexport interface SearchConfig {\n fields: SearchField[];\n tokenSearch: boolean;\n accentInsensitive: boolean;\n scorer?: SearchScorer;\n}\n\nexport function normalizeSearchText(value: string, accentInsensitive = true): string {\n const lower = value.toLocaleLowerCase();\n return accentInsensitive\n ? lower\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/đ/g, \"d\")\n : lower;\n}\n\nexport function getSearchField(option: Option, field: SearchField): string {\n if (field === \"label\") return option.label;\n if (field === \"description\") return option.description ?? \"\";\n const path = field.slice(5).split(\".\");\n let value: unknown = option.meta;\n for (const key of path) {\n if (!value || typeof value !== \"object\") return \"\";\n value = (value as Record<string, unknown>)[key];\n }\n return value == null ? \"\" : String(value);\n}\n\nexport function scoreOption(option: Option, query: string, config: SearchConfig): number {\n const normalizedQuery = normalizeSearchText(query.trim(), config.accentInsensitive);\n if (!normalizedQuery) return 1;\n if (config.scorer) return config.scorer(option, query.trim(), normalizedQuery);\n const haystacks = config.fields.map((field) =>\n normalizeSearchText(getSearchField(option, field), config.accentInsensitive),\n );\n const tokens = config.tokenSearch ? normalizedQuery.split(/\\s+/).filter(Boolean) : [normalizedQuery];\n if (!tokens.every((token) => haystacks.some((field) => field.includes(token)))) return 0;\n const label = haystacks[config.fields.indexOf(\"label\")];\n if (label === normalizedQuery) return 4;\n if (label?.startsWith(normalizedQuery)) return 3;\n if (label?.includes(normalizedQuery)) return 2;\n return 1;\n}\n\nexport class SearchIndex {\n private cache = new WeakMap<Option, Map<string, string[]>>();\n\n clear(): void {\n this.cache = new WeakMap();\n }\n\n score(option: Option, query: string, config: SearchConfig): number {\n const normalizedQuery = normalizeSearchText(query.trim(), config.accentInsensitive);\n if (!normalizedQuery) return 1;\n if (config.scorer) return config.scorer(option, query.trim(), normalizedQuery);\n const key = `${config.accentInsensitive ? \"1\" : \"0\"}:${config.fields.join(\"\\u0000\")}`;\n let variants = this.cache.get(option);\n if (!variants) {\n variants = new Map();\n this.cache.set(option, variants);\n }\n let haystacks = variants.get(key);\n if (!haystacks) {\n haystacks = config.fields.map((field) =>\n normalizeSearchText(getSearchField(option, field), config.accentInsensitive),\n );\n variants.set(key, haystacks);\n }\n const tokens = config.tokenSearch ? normalizedQuery.split(/\\s+/).filter(Boolean) : [normalizedQuery];\n if (!tokens.every((token) => haystacks.some((field) => field.includes(token)))) return 0;\n const label = haystacks[config.fields.indexOf(\"label\")];\n if (label === normalizedQuery) return 4;\n if (label?.startsWith(normalizedQuery)) return 3;\n if (label?.includes(normalizedQuery)) return 2;\n return 1;\n }\n}\n\nexport function findNormalizedRanges(label: string, query: string, accentInsensitive = true): Array<[number, number]> {\n const tokens = normalizeSearchText(query.trim(), accentInsensitive).split(/\\s+/).filter(Boolean);\n if (!tokens.length) return [];\n const normalized = normalizeSearchText(label, accentInsensitive);\n const ranges: Array<[number, number]> = [];\n for (const token of tokens) {\n const index = normalized.indexOf(token);\n if (index >= 0) ranges.push([index, index + token.length]);\n }\n return ranges.sort((a, b) => a[0] - b[0]);\n}\n","import type { DataItem, Option, OptionGroup } from \"./types\";\n\nexport function isGroup(item: DataItem): item is OptionGroup {\n return (item as OptionGroup).options !== undefined;\n}\n\nexport type IsDisabled = (option: Option) => boolean;\nconst defaultIsDisabled: IsDisabled = (option) => !!option.disabled;\n\n// Disabled descendants are excluded from `navItems` (see buildRows in\n// ForgeSelect.ts) and so can never be toggled back off by the user through\n// the UI — cascading a parent's (de)selection onto them would strand them\n// permanently selected. Their own children remain independently selectable\n// (only the disabled node itself is skipped), matching buildRows' rendering.\n// `isDisabled` defaults to the static `option.disabled` check so callers that\n// don't pass one keep today's exact behavior; ForgeSelect.ts passes a\n// predicate that also folds in the dynamic `isOptionDisabled` callback.\nexport function collectDescendantValues(option: Option, isDisabled: IsDisabled = defaultIsDisabled): string[] {\n if (!option.children) return [];\n const values: string[] = [];\n for (const child of option.children) {\n if (!isDisabled(child)) values.push(child.value);\n values.push(...collectDescendantValues(child, isDisabled));\n }\n return values;\n}\n\nexport function computeCheckState(\n option: Option,\n selected: string[],\n isDisabled: IsDisabled = defaultIsDisabled,\n): \"none\" | \"some\" | \"all\" {\n if (!option.children?.length) return selected.includes(option.value) ? \"all\" : \"none\";\n const states = option.children\n .filter((child) => !isDisabled(child))\n .map((child) => computeCheckState(child, selected, isDisabled));\n if (states.length === 0) return \"none\";\n if (states.every((state) => state === \"all\")) return \"all\";\n if (states.every((state) => state === \"none\")) return \"none\";\n return \"some\";\n}\n\nexport function findOption(items: DataItem[], value: string): Option | undefined {\n const search = (options: Option[]): Option | undefined => {\n for (const option of options) {\n if (option.value === value) return option;\n const found = option.children ? search(option.children) : undefined;\n if (found) return found;\n }\n return undefined;\n };\n for (const item of items) {\n const found = search(isGroup(item) ? item.options : [item]);\n if (found) return found;\n }\n return undefined;\n}\n\nexport function syncTreeAncestors(\n items: DataItem[],\n selected: string[],\n isDisabled: IsDisabled = defaultIsDisabled,\n): void {\n const sync = (option: Option): void => {\n if (!option.children?.length) return;\n for (const child of option.children) sync(child);\n const state = computeCheckState(option, selected, isDisabled);\n const index = selected.indexOf(option.value);\n if (state === \"all\" && index === -1) selected.push(option.value);\n else if (state !== \"all\" && index !== -1) selected.splice(index, 1);\n };\n for (const item of items) (isGroup(item) ? item.options : [item]).forEach(sync);\n}\n\nexport function collectValues(items: DataItem[]): Set<string> {\n const values = new Set<string>();\n const visit = (option: Option): void => {\n values.add(option.value);\n option.children?.forEach(visit);\n };\n for (const item of items) (isGroup(item) ? item.options : [item]).forEach(visit);\n return values;\n}\n\nexport function arraysEqual(a: string[], b: string[]): boolean {\n return a.length === b.length && a.every((value, index) => value === b[index]);\n}\n","import { Emitter, type Handler } from \"./emitter\";\nimport { computeDropdownPlacement } from \"./dropdown-position\";\nimport { format, getStrings, type Strings } from \"./i18n\";\nimport { parseNativeOptions } from \"./native-select\";\nimport { renderOptionContent } from \"./option-renderer\";\nimport { buildUrl, normalizeRemoteResult } from \"./remote\";\nimport { RemoteCache } from \"./remote-cache\";\nimport { findNormalizedRanges, normalizeSearchText, SearchIndex } from \"./search\";\nimport {\n arraysEqual,\n collectDescendantValues,\n collectValues,\n computeCheckState,\n findOption as findDataOption,\n isGroup,\n syncTreeAncestors as syncDataTreeAncestors,\n} from \"./selection\";\nimport type {\n AjaxConfig,\n DataItem,\n ForgeSelectEvent,\n ForgeSelectEventHandler,\n ForgeSelectOptions,\n ForgeSelectUpdateOptions,\n ForgeSelectPlugin,\n ForgeSelectValue,\n Option,\n SetValueOptions,\n SetSearchQueryOptions,\n SearchField,\n SearchScorer,\n TemplateFn,\n} from \"./types\";\n\ntype Row =\n | { kind: \"group\"; label: string }\n | { kind: \"option\"; option: Option; navIndex: number; depth: number; hasChildren: boolean }\n | { kind: \"create\"; navIndex: number }\n | { kind: \"empty\" }\n | { kind: \"error\" }\n | { kind: \"loading\" }\n | { kind: \"loading-more\" }\n | { kind: \"min-length\" };\n\ntype NavItem = { kind: \"option\"; option: Option; parentValue?: string } | { kind: \"create\" };\ntype TagCreation = { option: Option; created: boolean };\n\ninterface ResolvedOptions {\n placeholder: string;\n searchable: boolean;\n multiple: boolean;\n clearable: boolean;\n allowCreate: boolean;\n sortable: boolean;\n closeOnSelect: boolean;\n maxSelections?: number;\n theme: string;\n disabled: boolean;\n required: boolean;\n data?: DataItem[];\n ajax?: AjaxConfig;\n templateResult?: TemplateFn;\n templateSelection?: TemplateFn;\n filterOption?: (option: Option, query: string) => boolean;\n searchFields: SearchField[];\n tokenSearch: boolean;\n accentInsensitive: boolean;\n searchScorer?: SearchScorer;\n highlightSearch: boolean;\n minSearchLength: number;\n isOptionDisabled?: (option: Option) => boolean;\n minResultsForSearch: number;\n virtualScroll: boolean | undefined;\n itemHeight: number;\n variableItemHeight: boolean;\n language: string | Record<string, string>;\n plugins: ForgeSelectPlugin[];\n openOnFocus: boolean;\n dropdownParent?: HTMLElement | string;\n}\n\nconst DEFAULT_ITEM_HEIGHT = 36;\nconst VIRTUAL_BUFFER = 5;\nconst VIRTUAL_THRESHOLD = 100;\nconst ROW_CACHE_LIMIT = 2000;\n\nlet uidCounter = 0;\n\nexport default class ForgeSelect {\n /** The original element ForgeSelect was mounted on. */\n readonly el: HTMLElement;\n\n private opts: ResolvedOptions;\n private strings: Strings;\n private data: DataItem[];\n private selected: string[] = [];\n private selectedOptions = new Map<string, Option>();\n private suppressNextTagClick = false;\n private emitter = new Emitter();\n private plugins: ForgeSelectPlugin[];\n\n private uid = `forge-select-${++uidCounter}`;\n private root!: HTMLDivElement;\n private control!: HTMLDivElement;\n private valueEl!: HTMLDivElement;\n private clearBtn!: HTMLButtonElement;\n private dropdown!: HTMLDivElement;\n private searchInput: HTMLInputElement | null = null;\n private list!: HTMLUListElement;\n private liveRegion!: HTMLDivElement;\n private portalHost: HTMLDivElement | null = null;\n\n private isOpen = false;\n private isDisabled = false;\n private destroyed = false;\n private query = \"\";\n private rows: Row[] = [];\n private navItems: NavItem[] = [];\n private highlightedIndex = -1;\n private rowContentCache = new Map<string, Node>();\n private rowHeightCache = new Map<string, number>();\n private searchIndex = new SearchIndex();\n private expandedValues = new Set<string>();\n\n private loading = false;\n private loadingMore = false;\n private page = 0;\n private hasMore = true;\n private ajaxTimer: ReturnType<typeof setTimeout> | null = null;\n private ajaxRequestId = 0;\n private ajaxController: AbortController | null = null;\n private remoteLoaded = false;\n private remoteCache = new RemoteCache<{ options: Option[]; hasMore: boolean }>();\n private loadError: Error | null = null;\n private originalDisplay = \"\";\n private originalDisabled = false;\n private nativeSelect: HTMLSelectElement | null = null;\n private nativeForm: HTMLFormElement | null = null;\n private syncingNative = false;\n\n /** Combines the static `disabled` field with the dynamic `isOptionDisabled` callback. */\n private isOptionDisabled = (option: Option): boolean =>\n option.disabled === true || (this.opts.isOptionDisabled?.(option) ?? false);\n\n private pointerDownOnControl = false;\n\n private onDocumentMouseDown = (event: MouseEvent): void => {\n const target = event.target as Node;\n if (!this.root.contains(target) && !this.portalHost?.contains(target)) this.close();\n };\n\n private onWindowResize = (): void => {\n this.positionDropdown();\n };\n\n private onAncestorScroll = (): void => {\n if (this.portalHost) this.positionDropdown();\n };\n\n private onNativeInvalid = (event: Event): void => {\n event.preventDefault();\n this.control.classList.add(\"forge-select__control--invalid\");\n this.control.setAttribute(\"aria-invalid\", \"true\");\n if (!this.isOpen) this.open();\n this.control.focus();\n this.emitter.emit(\"invalid\", this.nativeSelect?.validationMessage ?? \"\");\n };\n\n private onNativeChange = (): void => {\n if (!this.nativeSelect || this.destroyed || this.syncingNative) return;\n const values = Array.from(this.nativeSelect.selectedOptions, (option) => option.value);\n this.applyNativeValues(values);\n };\n\n private applyNativeValues(values: string[]): void {\n this.selected = [];\n for (const value of this.opts.multiple ? values : values.slice(0, 1)) this.selectValue(value, false);\n this.renderValue();\n if (this.isOpen) this.renderList();\n this.emitter.emit(\"change\", this.getValue());\n }\n\n private onFormReset = (): void => {\n if (!this.nativeSelect || this.destroyed) return;\n const defaults = Array.from(this.nativeSelect.options)\n .filter((option) => option.defaultSelected)\n .map((option) => option.value);\n this.applyNativeValues(defaults);\n };\n\n constructor(target: string | HTMLElement, options: ForgeSelectOptions = {}) {\n const el = typeof target === \"string\" ? document.querySelector<HTMLElement>(target) : target;\n if (!el) {\n throw new Error(`ForgeSelect: target element not found: ${String(target)}`);\n }\n this.el = el;\n\n const nativeSelect = el instanceof HTMLSelectElement ? el : null;\n this.nativeSelect = nativeSelect;\n this.nativeForm = nativeSelect?.form ?? null;\n this.originalDisplay = el.style.display;\n this.originalDisabled = nativeSelect?.disabled ?? false;\n this.opts = {\n placeholder: options.placeholder ?? \"\",\n searchable: options.searchable ?? true,\n multiple: options.multiple ?? nativeSelect?.multiple ?? false,\n clearable: options.clearable ?? false,\n allowCreate: options.allowCreate ?? false,\n sortable: options.sortable ?? false,\n closeOnSelect: options.closeOnSelect ?? false,\n maxSelections:\n options.maxSelections == null || !Number.isFinite(options.maxSelections)\n ? undefined\n : Math.max(0, Math.floor(options.maxSelections)),\n theme: options.theme ?? \"default\",\n disabled: options.disabled ?? nativeSelect?.disabled ?? false,\n required: options.required ?? nativeSelect?.required ?? false,\n data: options.data,\n ajax: options.ajax,\n templateResult: options.templateResult,\n templateSelection: options.templateSelection,\n filterOption: options.filterOption,\n searchFields: options.searchFields ?? [\"label\", \"description\"],\n tokenSearch: options.tokenSearch ?? true,\n accentInsensitive: options.accentInsensitive ?? true,\n searchScorer: options.searchScorer,\n highlightSearch: options.highlightSearch ?? false,\n minSearchLength: Math.max(0, Math.floor(options.minSearchLength ?? 0)),\n minResultsForSearch: Math.max(0, Math.floor(options.minResultsForSearch ?? 0)),\n isOptionDisabled: options.isOptionDisabled,\n virtualScroll: options.virtualScroll,\n itemHeight: typeof options.itemHeight === \"number\" ? Math.max(1, options.itemHeight) : DEFAULT_ITEM_HEIGHT,\n variableItemHeight: options.itemHeight === \"auto\",\n language: options.language ?? \"en\",\n plugins: options.plugins ?? [],\n openOnFocus: options.openOnFocus ?? false,\n dropdownParent: options.dropdownParent,\n };\n this.strings = getStrings(this.opts.language);\n this.plugins = this.opts.plugins;\n if (nativeSelect) nativeSelect.required = this.opts.required;\n\n this.data = this.opts.data ?? (nativeSelect ? parseNativeOptions(nativeSelect) : []);\n if (nativeSelect && !this.opts.data) {\n const nativeOptions = Array.from(nativeSelect.options);\n const hasIntentionalSelection =\n nativeSelect.multiple ||\n nativeSelect.selectedIndex > 0 ||\n nativeOptions.some((option) => option.defaultSelected);\n for (const option of nativeOptions) {\n if (hasIntentionalSelection && option.selected) this.selectValue(option.value, false);\n }\n }\n\n this.buildDom();\n this.renderValue();\n if (this.opts.disabled) this.disable();\n nativeSelect?.addEventListener(\"change\", this.onNativeChange);\n nativeSelect?.addEventListener(\"invalid\", this.onNativeInvalid);\n this.nativeForm?.addEventListener(\"reset\", this.onFormReset);\n\n for (const plugin of this.plugins) plugin.onInit?.(this);\n for (const query of this.opts.ajax?.prefetch ?? []) void this.prefetchRemote(query);\n }\n\n // ---------------------------------------------------------------- public API\n\n open(): void {\n if (this.isOpen || this.isDisabled || this.destroyed) return;\n this.isOpen = true;\n this.dropdown.hidden = false;\n this.root.classList.add(\"forge-select--open\");\n this.control.setAttribute(\"aria-expanded\", \"true\");\n document.addEventListener(\"mousedown\", this.onDocumentMouseDown);\n\n if (this.opts.ajax && (this.opts.ajax.loadOnOpen ?? true) && !this.remoteLoaded) {\n this.scheduleRemoteLoad(this.query, 0);\n }\n this.renderList();\n this.positionDropdown();\n window.addEventListener(\"resize\", this.onWindowResize);\n document.addEventListener(\"scroll\", this.onAncestorScroll, true);\n if (this.searchInput && !this.searchInput.hidden) this.searchInput.focus();\n\n this.emitter.emit(\"open\");\n for (const plugin of this.plugins) plugin.onOpen?.(this);\n }\n\n close(): void {\n if (!this.isOpen) return;\n this.isOpen = false;\n this.dropdown.hidden = true;\n this.root.classList.remove(\"forge-select--open\");\n this.root.classList.remove(\"forge-select--drop-up\");\n this.control.setAttribute(\"aria-expanded\", \"false\");\n document.removeEventListener(\"mousedown\", this.onDocumentMouseDown);\n window.removeEventListener(\"resize\", this.onWindowResize);\n document.removeEventListener(\"scroll\", this.onAncestorScroll, true);\n this.highlightedIndex = -1;\n if (this.searchInput) {\n this.searchInput.value = \"\";\n this.query = \"\";\n }\n\n this.emitter.emit(\"close\");\n for (const plugin of this.plugins) plugin.onClose?.(this);\n }\n\n /**\n * Flips the dropdown above the control when there isn't enough room below\n * but there is above. Recomputed on open() and on window resize — the\n * dropdown is positioned absolutely inside the relatively-positioned root,\n * so it already tracks the control correctly on page scroll without\n * needing a scroll listener.\n */\n private positionDropdown(): void {\n const controlRect = this.control.getBoundingClientRect();\n const placement = computeDropdownPlacement(controlRect, this.dropdown.offsetHeight, window.innerHeight);\n this.root.classList.toggle(\"forge-select--drop-up\", placement.dropUp);\n if (this.portalHost) {\n this.portalHost.style.top = `${placement.top}px`;\n this.portalHost.style.left = `${controlRect.left}px`;\n this.portalHost.style.width = `${controlRect.width}px`;\n }\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.close();\n for (const plugin of this.plugins) plugin.onDestroy?.(this);\n this.destroyed = true;\n if (this.ajaxTimer) clearTimeout(this.ajaxTimer);\n this.ajaxController?.abort();\n this.nativeSelect?.removeEventListener(\"change\", this.onNativeChange);\n this.nativeSelect?.removeEventListener(\"invalid\", this.onNativeInvalid);\n this.nativeForm?.removeEventListener(\"reset\", this.onFormReset);\n this.rowContentCache.clear();\n this.rowHeightCache.clear();\n this.searchIndex.clear();\n this.portalHost?.remove();\n this.root.remove();\n this.el.style.display = this.originalDisplay;\n if (this.nativeSelect) this.nativeSelect.disabled = this.originalDisabled;\n this.emitter.clear();\n }\n\n getValue(): ForgeSelectValue {\n if (this.opts.multiple) return [...this.selected];\n return this.selected[0] ?? null;\n }\n\n getSearchQuery(): string {\n return this.query;\n }\n\n setSearchQuery(query: string, options: SetSearchQueryOptions = {}): void {\n this.applySearchQuery(query, options.emitSearch ?? true);\n }\n\n isDropdownOpen(): boolean {\n return this.isOpen;\n }\n\n updateOptions(options: ForgeSelectUpdateOptions): void {\n if (options.data) this.setData(options.data);\n if (\"ajax\" in options && options.ajax !== this.opts.ajax) {\n this.opts.ajax = options.ajax;\n this.remoteLoaded = false;\n this.clearRemoteCache();\n }\n if (options.placeholder !== undefined) this.opts.placeholder = options.placeholder;\n if (options.clearable !== undefined) this.opts.clearable = options.clearable;\n if (options.allowCreate !== undefined) this.opts.allowCreate = options.allowCreate;\n if (options.sortable !== undefined) this.opts.sortable = options.sortable;\n if (options.closeOnSelect !== undefined) this.opts.closeOnSelect = options.closeOnSelect;\n if (\"maxSelections\" in options)\n this.opts.maxSelections =\n options.maxSelections == null || !Number.isFinite(options.maxSelections)\n ? undefined\n : Math.max(0, Math.floor(options.maxSelections));\n if (options.theme !== undefined) {\n this.opts.theme = options.theme;\n this.root.dataset.theme = options.theme;\n if (this.portalHost) this.portalHost.dataset.theme = options.theme;\n }\n if (options.required !== undefined) {\n this.opts.required = options.required;\n if (options.required) this.control.setAttribute(\"aria-required\", \"true\");\n else this.control.removeAttribute(\"aria-required\");\n if (this.nativeSelect) this.nativeSelect.required = options.required;\n }\n if (options.templateResult !== undefined) this.opts.templateResult = options.templateResult;\n if (options.templateSelection !== undefined) this.opts.templateSelection = options.templateSelection;\n if (options.filterOption !== undefined) this.opts.filterOption = options.filterOption;\n if (options.searchFields !== undefined) this.opts.searchFields = options.searchFields;\n if (options.tokenSearch !== undefined) this.opts.tokenSearch = options.tokenSearch;\n if (options.accentInsensitive !== undefined) this.opts.accentInsensitive = options.accentInsensitive;\n if (options.searchScorer !== undefined) this.opts.searchScorer = options.searchScorer;\n if (options.highlightSearch !== undefined) this.opts.highlightSearch = options.highlightSearch;\n if (options.minSearchLength !== undefined)\n this.opts.minSearchLength = Math.max(0, Math.floor(options.minSearchLength));\n if (options.minResultsForSearch !== undefined)\n this.opts.minResultsForSearch = Math.max(0, Math.floor(options.minResultsForSearch));\n if (options.isOptionDisabled !== undefined) this.opts.isOptionDisabled = options.isOptionDisabled;\n if (options.virtualScroll !== undefined) this.opts.virtualScroll = options.virtualScroll;\n if (options.itemHeight !== undefined) {\n this.opts.variableItemHeight = options.itemHeight === \"auto\";\n if (typeof options.itemHeight === \"number\") this.opts.itemHeight = Math.max(1, options.itemHeight);\n this.root.style.setProperty(\"--fs-item-height\", `${this.opts.itemHeight}px`);\n this.portalHost?.style.setProperty(\"--fs-item-height\", `${this.opts.itemHeight}px`);\n }\n if (options.language !== undefined) {\n this.opts.language = options.language;\n this.strings = getStrings(options.language);\n this.clearBtn.setAttribute(\"aria-label\", this.strings.clearSelection);\n this.searchInput?.setAttribute(\"aria-label\", this.strings.search);\n }\n if (options.openOnFocus !== undefined) this.opts.openOnFocus = options.openOnFocus;\n if (options.disabled !== undefined) {\n if (options.disabled) this.disable();\n else this.enable();\n }\n this.root.classList.toggle(\"forge-select--sortable\", this.opts.sortable && this.opts.multiple);\n this.updateSearchVisibility();\n this.rowContentCache.clear();\n this.searchIndex.clear();\n this.renderValue();\n if (this.isOpen) this.renderList();\n }\n\n validate(): boolean {\n const valid =\n (!this.opts.required || this.selected.length > 0) && (this.control.dataset.validationMessage ?? \"\") === \"\";\n this.control.classList.toggle(\"forge-select__control--invalid\", !valid);\n this.control.setAttribute(\"aria-invalid\", String(!valid));\n return valid;\n }\n\n setCustomValidity(message: string): void {\n this.nativeSelect?.setCustomValidity(message);\n this.control.dataset.validationMessage = message;\n }\n\n reportValidity(): boolean {\n const valid = this.validate() && (this.nativeSelect?.checkValidity() ?? true);\n if (!valid) {\n const message = this.nativeSelect?.validationMessage ?? this.control.dataset.validationMessage ?? \"\";\n if (this.nativeSelect) return this.nativeSelect.reportValidity();\n this.emitter.emit(\"invalid\", message);\n }\n return valid;\n }\n\n reload(): void {\n if (!this.opts.ajax) return;\n this.clearRemoteCache();\n this.remoteLoaded = false;\n this.scheduleRemoteLoad(this.query, 0);\n }\n\n clearRemoteCache(): void {\n this.remoteCache.clear();\n }\n\n setValue(value: ForgeSelectValue, options: SetValueOptions = {}): void {\n const values = value == null ? [] : Array.isArray(value) ? value : [value];\n const next = this.opts.multiple ? values : values.slice(0, 1);\n if (arraysEqual(next, this.selected)) return;\n this.selected = [];\n for (const v of next) this.selectValue(v, false);\n this.afterSelectionChange(options.emitChange ?? true);\n }\n\n /**\n * Replaces the option list after construction. An open dropdown re-renders\n * immediately; a selection whose value isn't in the new data stays\n * selected (rendered via the already-selected option's own label/avatar,\n * the same fallback used for values selected from a stale ajax page).\n */\n setData(data: DataItem[]): void {\n if (this.ajaxTimer) {\n clearTimeout(this.ajaxTimer);\n this.ajaxTimer = null;\n }\n this.ajaxController?.abort();\n this.ajaxController = null;\n this.ajaxRequestId += 1;\n this.setLoading(false);\n this.loadingMore = false;\n this.loadError = null;\n this.remoteLoaded = true;\n this.page = 0;\n this.hasMore = false;\n this.data = data;\n this.opts.data = data;\n this.updateSearchVisibility();\n this.rowContentCache.clear();\n this.searchIndex.clear();\n this.highlightedIndex = -1;\n if (this.isOpen) this.renderList();\n }\n\n /**\n * Multi-select only: selects every currently non-disabled option, including\n * nested tree descendants and options inside groups. If `maxSelections` is\n * set, stops once the cap is reached rather than exceeding it. A no-op for\n * single-select.\n */\n selectAll(): void {\n if (!this.opts.multiple) return;\n this.selected = [];\n for (const value of this.allSelectableValues()) {\n const option = this.findOption(value);\n if (option && this.canSelectOption(option)) this.selectValue(value, false);\n }\n this.afterSelectionChange();\n }\n\n /** Clears every selection. Equivalent to `setValue(null)`. */\n clearAll(): void {\n this.clearSelection();\n }\n\n enable(): void {\n this.isDisabled = false;\n this.root.classList.remove(\"forge-select--disabled\");\n this.control.tabIndex = 0;\n this.control.setAttribute(\"aria-disabled\", \"false\");\n if (this.nativeSelect) this.nativeSelect.disabled = false;\n }\n\n disable(): void {\n this.close();\n this.isDisabled = true;\n this.root.classList.add(\"forge-select--disabled\");\n this.control.tabIndex = -1;\n this.control.setAttribute(\"aria-disabled\", \"true\");\n if (this.nativeSelect) this.nativeSelect.disabled = true;\n }\n\n on<E extends ForgeSelectEvent>(event: E, handler: ForgeSelectEventHandler<E>): void {\n this.emitter.on(event, handler as Handler);\n }\n\n off<E extends ForgeSelectEvent>(event: E, handler: ForgeSelectEventHandler<E>): void {\n this.emitter.off(event, handler as Handler);\n }\n\n // ---------------------------------------------------------------- DOM setup\n\n /**\n * The original target (a hidden native <select> or a plain mount div) can\n * carry an accessible name via aria-label/aria-labelledby, or via a\n * <label for> pointing at its id — but once `this.el` is display:none it\n * drops out of the accessibility tree, so any such association silently\n * stops reaching assistive tech unless we forward it onto the visible,\n * interactive `this.control` ourselves.\n */\n private applyAccessibleName(): void {\n const ariaLabelledby = this.el.getAttribute(\"aria-labelledby\");\n const ariaLabel = this.el.getAttribute(\"aria-label\");\n if (ariaLabelledby) {\n this.control.setAttribute(\"aria-labelledby\", ariaLabelledby);\n } else if (ariaLabel) {\n this.control.setAttribute(\"aria-label\", ariaLabel);\n } else if (this.el.id) {\n const label = Array.from(document.getElementsByTagName(\"label\")).find((el) => el.htmlFor === this.el.id);\n if (label) {\n if (!label.id) label.id = `${this.uid}-label`;\n this.control.setAttribute(\"aria-labelledby\", label.id);\n }\n }\n }\n\n private shouldShowSearch(): boolean {\n return (\n this.opts.searchable && (this.opts.ajax != null || collectValues(this.data).size >= this.opts.minResultsForSearch)\n );\n }\n\n private updateSearchVisibility(): void {\n if (!this.searchInput) return;\n this.searchInput.hidden = !this.shouldShowSearch();\n if (this.searchInput.hidden) {\n this.searchInput.value = \"\";\n this.query = \"\";\n }\n }\n\n private buildDom(): void {\n const portalParent =\n typeof this.opts.dropdownParent === \"string\"\n ? document.querySelector<HTMLElement>(this.opts.dropdownParent)\n : this.opts.dropdownParent;\n if (this.opts.dropdownParent && !portalParent) {\n throw new Error(`ForgeSelect: dropdown parent not found: ${String(this.opts.dropdownParent)}`);\n }\n this.root = document.createElement(\"div\");\n this.root.className = \"forge-select\";\n this.root.dataset.theme = this.opts.theme;\n this.root.style.setProperty(\"--fs-item-height\", `${this.opts.itemHeight}px`);\n if (this.opts.sortable && this.opts.multiple) this.root.classList.add(\"forge-select--sortable\");\n\n this.control = document.createElement(\"div\");\n this.control.className = \"forge-select__control\";\n this.control.setAttribute(\"role\", \"combobox\");\n this.control.setAttribute(\"aria-haspopup\", \"listbox\");\n this.control.setAttribute(\"aria-expanded\", \"false\");\n this.control.setAttribute(\"aria-controls\", `${this.uid}-list`);\n if (this.opts.required) this.control.setAttribute(\"aria-required\", \"true\");\n this.control.tabIndex = 0;\n this.applyAccessibleName();\n\n this.valueEl = document.createElement(\"div\");\n this.valueEl.className = \"forge-select__value\";\n\n this.clearBtn = document.createElement(\"button\");\n this.clearBtn.type = \"button\";\n this.clearBtn.className = \"forge-select__clear\";\n this.clearBtn.setAttribute(\"aria-label\", this.strings.clearSelection);\n this.clearBtn.textContent = \"×\";\n this.clearBtn.hidden = true;\n\n const arrow = document.createElement(\"span\");\n arrow.className = \"forge-select__arrow\";\n arrow.setAttribute(\"aria-hidden\", \"true\");\n\n this.control.append(this.valueEl, this.clearBtn, arrow);\n\n this.dropdown = document.createElement(\"div\");\n this.dropdown.className = \"forge-select__dropdown\";\n this.dropdown.hidden = true;\n\n if (this.opts.searchable) {\n this.searchInput = document.createElement(\"input\");\n this.searchInput.type = \"search\";\n this.searchInput.className = \"forge-select__search\";\n this.searchInput.setAttribute(\"aria-label\", this.strings.search);\n this.searchInput.setAttribute(\"aria-autocomplete\", \"list\");\n this.searchInput.setAttribute(\"aria-controls\", `${this.uid}-list`);\n this.searchInput.hidden = !this.shouldShowSearch();\n this.dropdown.append(this.searchInput);\n }\n\n this.list = document.createElement(\"ul\");\n this.list.className = \"forge-select__list\";\n this.list.id = `${this.uid}-list`;\n this.list.setAttribute(\"role\", \"listbox\");\n if (this.opts.multiple) this.list.setAttribute(\"aria-multiselectable\", \"true\");\n this.dropdown.append(this.list);\n\n this.liveRegion = document.createElement(\"div\");\n this.liveRegion.className = \"forge-select__sr-only\";\n this.liveRegion.setAttribute(\"role\", \"status\");\n this.liveRegion.setAttribute(\"aria-live\", \"polite\");\n\n this.root.append(this.control, this.liveRegion);\n if (!portalParent) this.root.append(this.dropdown);\n this.el.style.display = \"none\";\n this.el.insertAdjacentElement(\"afterend\", this.root);\n\n if (portalParent) {\n this.portalHost = document.createElement(\"div\");\n this.portalHost.className = \"forge-select forge-select--portal-host\";\n this.portalHost.dataset.theme = this.opts.theme;\n this.portalHost.style.setProperty(\"--fs-item-height\", `${this.opts.itemHeight}px`);\n this.portalHost.append(this.dropdown);\n portalParent.append(this.portalHost);\n }\n\n this.bindEvents();\n }\n\n private bindEvents(): void {\n this.control.addEventListener(\"click\", (event) => {\n if (event.target === this.clearBtn) return;\n if (this.suppressNextTagClick) {\n this.suppressNextTagClick = false;\n return;\n }\n if (this.isDisabled) return;\n if (this.isOpen) this.close();\n else this.open();\n });\n\n this.control.addEventListener(\"keydown\", (event) => this.handleKeydown(event));\n\n // A mouse click fires mousedown -> focus -> click, in that order. Without\n // tracking pointerDownOnControl, openOnFocus would open the dropdown\n // during the focus phase, and the click handler above would then\n // immediately close it again via its own open/close toggle. Tracking\n // whether a mousedown preceded this focus distinguishes \"focused via\n // mouse click\" (skip auto-open, let the click handler's toggle run) from\n // \"focused via keyboard Tab\" (auto-open).\n this.control.addEventListener(\"mousedown\", () => {\n this.pointerDownOnControl = true;\n });\n this.control.addEventListener(\"focus\", () => {\n if (this.opts.openOnFocus && !this.pointerDownOnControl && !this.isOpen && !this.isDisabled) {\n this.open();\n }\n this.pointerDownOnControl = false;\n });\n\n this.clearBtn.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n this.clearSelection();\n });\n\n if (this.searchInput) {\n this.searchInput.addEventListener(\"input\", () => {\n this.applySearchQuery(this.searchInput!.value, true);\n });\n this.searchInput.addEventListener(\"keydown\", (event) => this.handleKeydown(event));\n this.searchInput.addEventListener(\"paste\", (event) => {\n if (!this.opts.multiple || !this.opts.allowCreate) return;\n const text = event.clipboardData?.getData(\"text\") ?? \"\";\n const labels = text\n .split(/[,\\n]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n if (labels.length < 2) return;\n event.preventDefault();\n const created: TagCreation[] = [];\n for (const label of labels) {\n const result = this.createTag(label);\n if (result) created.push(result);\n }\n if (created.length === 0) return;\n this.searchInput!.value = \"\";\n this.query = \"\";\n this.afterSelectionChange();\n for (const result of created) {\n if (result.created) this.emitter.emit(\"create\", result.option);\n this.emitter.emit(\"select\", result.option);\n }\n if (this.opts.closeOnSelect) this.close();\n else this.renderList();\n });\n }\n\n this.list.addEventListener(\"click\", (event) => {\n const target = event.target as HTMLElement;\n const twisty = target.closest<HTMLElement>(\"[data-twisty]\");\n if (twisty) {\n const value = twisty.dataset.twisty!;\n if (this.expandedValues.has(value)) this.expandedValues.delete(value);\n else this.expandedValues.add(value);\n this.renderList();\n return;\n }\n const li = target.closest<HTMLLIElement>(\"li[data-nav-index]\");\n if (!li) {\n const optionRow = target.closest<HTMLLIElement>(\"li[data-option-value]\");\n const option = optionRow ? this.findOption(optionRow.dataset.optionValue!) : undefined;\n if (option && this.hasReachedMaximum() && !this.selected.includes(option.value)) this.announceMaximum(option);\n return;\n }\n const navIndex = Number(li.dataset.navIndex);\n this.activateNavItem(navIndex);\n });\n\n this.list.addEventListener(\"scroll\", () => {\n if (this.usesVirtualScroll()) this.renderRows();\n this.maybeLoadNextPage();\n });\n }\n\n private applySearchQuery(query: string, emitSearch: boolean): void {\n this.query = query;\n if (this.searchInput && this.searchInput.value !== query) this.searchInput.value = query;\n this.highlightedIndex = -1;\n this.list.scrollTop = 0;\n this.rowContentCache.clear();\n if (emitSearch) this.emitter.emit(\"search\", query);\n const trimmed = query.trim();\n const belowMinLength = trimmed !== \"\" && trimmed.length < this.opts.minSearchLength;\n if (this.opts.ajax && !belowMinLength) {\n this.scheduleRemoteLoad(query, this.opts.ajax.debounce ?? 250);\n return;\n }\n if (belowMinLength) {\n if (this.ajaxTimer) {\n clearTimeout(this.ajaxTimer);\n this.ajaxTimer = null;\n }\n this.ajaxController?.abort();\n this.setLoading(false);\n }\n this.renderList();\n }\n\n private handleKeydown(event: KeyboardEvent): void {\n if (this.isDisabled) return;\n switch (event.key) {\n case \"Enter\":\n event.preventDefault();\n if (!this.isOpen) this.open();\n else if (this.highlightedIndex >= 0) this.activateNavItem(this.highlightedIndex);\n break;\n case \" \":\n if (event.target === this.control) {\n event.preventDefault();\n if (!this.isOpen) this.open();\n }\n break;\n case \"ArrowDown\":\n event.preventDefault();\n if (!this.isOpen) this.open();\n else this.moveHighlight(1);\n break;\n case \"ArrowUp\":\n event.preventDefault();\n if (this.isOpen) this.moveHighlight(-1);\n break;\n case \"Escape\":\n if (this.isOpen) {\n event.preventDefault();\n this.close();\n this.control.focus();\n }\n break;\n case \"ArrowRight\":\n if (this.isOpen && this.navigateTree(\"right\")) event.preventDefault();\n break;\n case \"ArrowLeft\":\n if (this.isOpen && this.navigateTree(\"left\")) event.preventDefault();\n break;\n case \"Tab\":\n this.close();\n break;\n }\n }\n\n // ---------------------------------------------------------------- selection\n\n private canSelectOption(option: Option): boolean {\n if (this.opts.maxSelections == null) return true;\n const projected = [...this.selected];\n if (!projected.includes(option.value)) projected.push(option.value);\n for (const value of collectDescendantValues(option, this.isOptionDisabled)) {\n if (!projected.includes(value)) projected.push(value);\n }\n syncDataTreeAncestors(this.data, projected, this.isOptionDisabled);\n return projected.length <= this.opts.maxSelections;\n }\n\n private hasReachedMaximum(): boolean {\n return this.opts.maxSelections != null && this.selected.length >= this.opts.maxSelections;\n }\n\n private announceMaximum(option: Option): void {\n const limit = this.opts.maxSelections;\n if (limit == null) return;\n this.liveRegion.textContent = format(this.strings.maximumSelected, { count: String(limit) });\n this.emitter.emit(\"maximum\", { limit, option });\n }\n\n private selectValue(value: string, notify: boolean): void {\n if (this.selected.includes(value)) return;\n const option = this.findOption(value) ?? this.selectedOptions.get(value) ?? { value, label: value };\n this.selectedOptions.set(value, option);\n if (this.opts.multiple) {\n this.selected.push(value);\n // Selecting a tree node cascades to its descendants too; for a plain\n // option (no children) this is a no-op.\n for (const v of collectDescendantValues(option, this.isOptionDisabled)) {\n if (!this.selected.includes(v)) this.selected.push(v);\n }\n this.syncTreeAncestors();\n } else {\n this.selected = [value];\n }\n if (notify) {\n this.afterSelectionChange();\n this.emitter.emit(\"select\", option);\n }\n }\n\n private deselectValue(value: string, notify: boolean): void {\n const index = this.selected.indexOf(value);\n if (index === -1) return;\n const option = this.findOption(value) ?? this.selectedOptions.get(value);\n this.selected.splice(index, 1);\n if (this.opts.multiple) {\n if (option) {\n for (const v of collectDescendantValues(option, this.isOptionDisabled)) {\n const i = this.selected.indexOf(v);\n if (i !== -1) this.selected.splice(i, 1);\n }\n }\n this.syncTreeAncestors();\n }\n if (notify) {\n this.afterSelectionChange();\n this.emitter.emit(\"unselect\", option ?? { value, label: value });\n }\n }\n\n /**\n * Keeps every tree parent's own membership in `selected` consistent with\n * its descendants (post-order, so parents see already-corrected children):\n * a parent counts as selected only when `computeCheckState` says \"all\".\n * No-op for data with no `children` anywhere.\n */\n private syncTreeAncestors(): void {\n syncDataTreeAncestors(this.data, this.selected, this.isOptionDisabled);\n }\n\n private clearSelection(): void {\n if (this.selected.length === 0) return;\n this.selected = [];\n this.emitter.emit(\"clear\");\n this.afterSelectionChange();\n }\n\n private allSelectableValues(): string[] {\n const values: string[] = [];\n const visit = (option: Option): void => {\n if (!this.isOptionDisabled(option)) values.push(option.value);\n option.children?.forEach(visit);\n };\n for (const item of this.data) (isGroup(item) ? item.options : [item]).forEach(visit);\n return values;\n }\n\n private afterSelectionChange(emitChange = true): void {\n this.renderValue();\n this.syncNativeSelect(emitChange);\n if (!this.opts.required || this.selected.length > 0) {\n this.control.classList.remove(\"forge-select__control--invalid\");\n this.control.removeAttribute(\"aria-invalid\");\n }\n if (this.isOpen) this.renderList();\n if (emitChange) this.emitter.emit(\"change\", this.getValue());\n }\n\n private syncNativeSelect(dispatchChange = true): void {\n if (!(this.el instanceof HTMLSelectElement)) return;\n const existing = new Set<string>();\n for (const option of Array.from(this.el.options)) {\n existing.add(option.value);\n option.selected = this.selected.includes(option.value);\n }\n for (const value of this.selected) {\n if (existing.has(value)) continue;\n const option = document.createElement(\"option\");\n option.value = value;\n option.textContent = this.selectedOptions.get(value)?.label ?? value;\n option.selected = true;\n this.el.append(option);\n }\n if (this.opts.sortable && this.opts.multiple) {\n // Re-appending in `this.selected` order moves each selected <option> to\n // the end in that relative order, so a real <select multiple> form\n // submission serializes values in the dragged order (unselected options\n // simply end up interleaved before them, which submission ignores).\n for (const value of this.selected) {\n const option = Array.from(this.el.options).find((o) => o.value === value);\n if (option) this.el.append(option);\n }\n }\n if (!dispatchChange) return;\n this.syncingNative = true;\n try {\n this.el.dispatchEvent(new Event(\"change\", { bubbles: true }));\n } finally {\n this.syncingNative = false;\n }\n }\n\n private findOption(value: string): Option | undefined {\n return findDataOption(this.data, value);\n }\n\n private findOptionByLabel(label: string): Option | undefined {\n const lower = label.toLowerCase();\n const search = (options: Option[]): Option | undefined => {\n for (const option of options) {\n if (option.label.toLowerCase() === lower) return option;\n const found = option.children ? search(option.children) : undefined;\n if (found) return found;\n }\n return undefined;\n };\n for (const item of this.data) {\n const found = search(isGroup(item) ? item.options : [item]);\n if (found) return found;\n }\n return undefined;\n }\n\n /** Selects an existing option matching `label` exactly, or creates and selects a new one. */\n private createTag(label: string): TagCreation | undefined {\n const trimmed = label.trim();\n if (!trimmed) return undefined;\n const existing = this.findOptionByLabel(trimmed);\n if (existing) {\n if (this.selected.includes(existing.value)) return undefined;\n if (this.opts.multiple && !this.canSelectOption(existing)) {\n this.announceMaximum(existing);\n return undefined;\n }\n this.selectValue(existing.value, false);\n return { option: existing, created: false };\n }\n const option: Option = { value: trimmed, label: trimmed };\n if (this.opts.multiple && !this.canSelectOption(option)) {\n this.announceMaximum(option);\n return undefined;\n }\n this.data.push(option);\n this.selectValue(option.value, false);\n return { option, created: true };\n }\n\n private createFromQuery(): void {\n const label = this.query.trim();\n if (!label) return;\n const result = this.createTag(label);\n if (!result) return;\n if (this.searchInput) {\n this.searchInput.value = \"\";\n this.query = \"\";\n }\n this.afterSelectionChange();\n if (result.created) this.emitter.emit(\"create\", result.option);\n this.emitter.emit(\"select\", result.option);\n if (!this.opts.multiple || this.opts.closeOnSelect) this.close();\n }\n\n private activateNavItem(navIndex: number): void {\n const item = this.navItems[navIndex];\n if (!item) return;\n if (item.kind === \"create\") {\n this.createFromQuery();\n return;\n }\n const { value } = item.option;\n if (this.opts.multiple) {\n let changed = false;\n if (this.selected.includes(value)) {\n this.deselectValue(value, true);\n changed = true;\n } else if (this.canSelectOption(item.option)) {\n this.selectValue(value, true);\n changed = true;\n } else {\n this.announceMaximum(item.option);\n }\n if (changed && this.opts.closeOnSelect) this.close();\n } else {\n this.selectValue(value, true);\n this.close();\n this.control.focus();\n }\n }\n\n // ---------------------------------------------------------------- rendering\n\n private renderValue(): void {\n this.valueEl.textContent = \"\";\n const hasValue = this.selected.length > 0;\n this.clearBtn.hidden = !(this.opts.clearable && hasValue);\n\n if (!hasValue) {\n const placeholder = document.createElement(\"span\");\n placeholder.className = \"forge-select__placeholder\";\n placeholder.textContent = this.opts.placeholder;\n this.valueEl.append(placeholder);\n return;\n }\n\n if (this.opts.multiple) {\n for (const value of this.selected) {\n const option = this.selectedOptions.get(value) ?? { value, label: value };\n const tag = document.createElement(\"span\");\n tag.className = \"forge-select__tag\";\n const label = document.createElement(\"span\");\n label.className = \"forge-select__tag-label\";\n renderOptionContent(label, option, this.opts.templateSelection, \"inline\");\n const remove = document.createElement(\"button\");\n remove.type = \"button\";\n remove.className = \"forge-select__tag-remove\";\n remove.setAttribute(\"aria-label\", format(this.strings.removeItem, { label: option.label }));\n remove.textContent = \"×\";\n remove.addEventListener(\"click\", (event) => {\n event.stopPropagation();\n if (!this.isDisabled) this.deselectValue(value, true);\n });\n tag.append(label, remove);\n if (this.opts.sortable) {\n tag.dataset.value = value;\n tag.tabIndex = 0;\n tag.setAttribute(\"aria-roledescription\", \"draggable item\");\n tag.setAttribute(\"aria-label\", format(this.strings.reorderHint, { label: option.label }));\n tag.addEventListener(\"keydown\", (event) => this.handleTagKeydown(event, value));\n this.bindTagDrag(tag, value);\n }\n this.valueEl.append(tag);\n }\n } else {\n const option = this.selectedOptions.get(this.selected[0]) ?? {\n value: this.selected[0],\n label: this.selected[0],\n };\n const span = document.createElement(\"span\");\n span.className = \"forge-select__single-value\";\n renderOptionContent(span, option, this.opts.templateSelection, \"inline\");\n this.valueEl.append(span);\n }\n }\n\n /**\n * Pointer-based (mouse/touch/pen) reorder for a single tag. Only the real\n * dragged DOM node is moved during the gesture — a full renderValue()\n * mid-drag would destroy it — so the reordered `this.selected` is only\n * committed on release. The move/up listeners and pointer capture live on\n * the stable `this.valueEl` container rather than the tag itself: `tag`\n * gets repositioned via `insertBefore` during the drag, and browsers treat\n * that reparenting as detaching the node, which silently drops pointer\n * capture (and further move events) if it were captured on `tag`.\n */\n private bindTagDrag(tag: HTMLSpanElement, value: string): void {\n const DRAG_THRESHOLD = 4;\n let startX = 0;\n let dragging = false;\n let order: string[] = [];\n\n const onPointerMove = (event: PointerEvent): void => {\n if (!dragging) {\n if (Math.abs(event.clientX - startX) < DRAG_THRESHOLD) return;\n dragging = true;\n order = [...this.selected];\n if (typeof this.valueEl.setPointerCapture === \"function\") {\n this.valueEl.setPointerCapture(event.pointerId);\n }\n tag.classList.add(\"forge-select__tag--dragging\");\n }\n event.preventDefault();\n\n const draggedIndex = order.indexOf(value);\n const siblings = Array.from(this.valueEl.querySelectorAll<HTMLElement>(\".forge-select__tag\"));\n for (const sibling of siblings) {\n if (sibling === tag) continue;\n const siblingValue = sibling.dataset.value;\n if (!siblingValue) continue;\n const siblingIndex = order.indexOf(siblingValue);\n if (siblingIndex === -1) continue;\n const rect = sibling.getBoundingClientRect();\n const midX = rect.left + rect.width / 2;\n const movingRight = draggedIndex < siblingIndex;\n const crossed = movingRight ? event.clientX > midX : event.clientX < midX;\n if (!crossed) continue;\n order.splice(draggedIndex, 1);\n order.splice(siblingIndex, 0, value);\n if (movingRight) this.valueEl.insertBefore(tag, sibling.nextSibling);\n else this.valueEl.insertBefore(tag, sibling);\n break;\n }\n };\n\n const finishDrag = (event: PointerEvent): void => {\n this.valueEl.removeEventListener(\"pointermove\", onPointerMove);\n this.valueEl.removeEventListener(\"pointerup\", finishDrag);\n this.valueEl.removeEventListener(\"pointercancel\", finishDrag);\n if (!dragging) return;\n if (typeof this.valueEl.releasePointerCapture === \"function\") {\n this.valueEl.releasePointerCapture(event.pointerId);\n }\n tag.classList.remove(\"forge-select__tag--dragging\");\n this.selected = order;\n this.suppressNextTagClick = true;\n this.afterSelectionChange();\n this.emitter.emit(\"reorder\", [...this.selected]);\n };\n\n tag.addEventListener(\"pointerdown\", (event) => {\n if (this.isDisabled || event.button !== 0) return;\n if ((event.target as HTMLElement).closest(\".forge-select__tag-remove\")) return;\n startX = event.clientX;\n dragging = false;\n this.valueEl.addEventListener(\"pointermove\", onPointerMove);\n this.valueEl.addEventListener(\"pointerup\", finishDrag);\n this.valueEl.addEventListener(\"pointercancel\", finishDrag);\n });\n }\n\n /** Alt+Left/Alt+Right on a focused tag: the keyboard-operable equivalent of dragging. */\n private handleTagKeydown(event: KeyboardEvent, value: string): void {\n if (!event.altKey || (event.key !== \"ArrowLeft\" && event.key !== \"ArrowRight\")) return;\n const index = this.selected.indexOf(value);\n const targetIndex = event.key === \"ArrowLeft\" ? index - 1 : index + 1;\n if (index === -1 || targetIndex < 0 || targetIndex >= this.selected.length) return;\n event.preventDefault();\n event.stopPropagation();\n const next = [...this.selected];\n [next[index], next[targetIndex]] = [next[targetIndex], next[index]];\n this.selected = next;\n this.afterSelectionChange();\n this.emitter.emit(\"reorder\", [...this.selected]);\n this.focusTagByValue(value);\n }\n\n private focusTagByValue(value: string): void {\n for (const tag of Array.from(this.valueEl.querySelectorAll<HTMLElement>(\".forge-select__tag\"))) {\n if (tag.dataset.value === value) {\n tag.focus();\n return;\n }\n }\n }\n\n private buildRows(): void {\n this.rows = [];\n this.navItems = [];\n const trimmedQuery = this.query.trim();\n const query = normalizeSearchText(trimmedQuery, this.opts.accentInsensitive);\n const matches = (option: Option): boolean =>\n query === \"\" ||\n (this.opts.filterOption\n ? this.opts.filterOption(option, trimmedQuery)\n : this.searchIndex.score(option, trimmedQuery, {\n fields: this.opts.searchFields,\n tokenSearch: this.opts.tokenSearch,\n accentInsensitive: this.opts.accentInsensitive,\n scorer: this.opts.searchScorer,\n }) > 0);\n\n // A tree node is visible while searching if it matches, or any descendant\n // does (leaf options with no children just reduce to `matches()`).\n const subtreeMatches = (option: Option): boolean =>\n query === \"\" || matches(option) || (option.children ?? []).some(subtreeMatches);\n\n const pushOption = (option: Option, depth: number, parentValue?: string): void => {\n let navIndex = -1;\n const interactionDisabled =\n this.isOptionDisabled(option) || (this.hasReachedMaximum() && !this.selected.includes(option.value));\n if (!interactionDisabled) {\n navIndex = this.navItems.length;\n this.navItems.push({ kind: \"option\", option, parentValue });\n }\n const hasChildren = !!option.children && option.children.length > 0;\n this.rows.push({ kind: \"option\", option, navIndex, depth, hasChildren });\n if (hasChildren) {\n // Expanding is ephemeral while searching (never written to\n // expandedValues), so clearing the query restores manual state.\n const expanded = query !== \"\" || this.expandedValues.has(option.value);\n if (expanded) {\n for (const child of option.children!) {\n if (subtreeMatches(child)) pushOption(child, depth + 1, option.value);\n }\n }\n }\n };\n\n if (trimmedQuery !== \"\" && trimmedQuery.length < this.opts.minSearchLength) {\n this.rows.push({ kind: \"min-length\" });\n return;\n }\n if (this.loading) {\n this.rows.push({ kind: \"loading\" });\n return;\n }\n if (this.loadError) {\n this.rows.push({ kind: \"error\" });\n return;\n }\n\n for (const item of this.data) {\n if (isGroup(item)) {\n const visible = item.options.filter(subtreeMatches);\n if (visible.length === 0) continue;\n this.rows.push({ kind: \"group\", label: item.label });\n visible.forEach((o) => pushOption(o, 0));\n } else if (subtreeMatches(item)) {\n pushOption(item, 0);\n }\n }\n\n if (this.opts.allowCreate && query !== \"\" && !this.hasExactMatch(query)) {\n const navIndex = this.navItems.length;\n this.navItems.push({ kind: \"create\" });\n this.rows.push({ kind: \"create\", navIndex });\n }\n\n if (this.rows.length === 0) this.rows.push({ kind: \"empty\" });\n else if (this.loadingMore) this.rows.push({ kind: \"loading-more\" });\n }\n\n private hasExactMatch(lowerQuery: string): boolean {\n return !!this.findOptionByLabel(lowerQuery);\n }\n\n private usesVirtualScroll(): boolean {\n return this.opts.virtualScroll !== false && this.rows.length > VIRTUAL_THRESHOLD;\n }\n\n private rowKey(row: Row, index: number): string {\n if (row.kind === \"option\") return `option:${row.option.value}`;\n if (row.kind === \"group\") return `group:${row.label}:${index}`;\n return `${row.kind}:${index}`;\n }\n\n private measuredRowHeight(index: number): number {\n return this.opts.variableItemHeight\n ? (this.rowHeightCache.get(this.rowKey(this.rows[index], index)) ?? this.opts.itemHeight)\n : this.opts.itemHeight;\n }\n\n private rowOffset(index: number): number {\n if (!this.opts.variableItemHeight) return index * this.opts.itemHeight;\n let offset = 0;\n for (let i = 0; i < index; i += 1) offset += this.measuredRowHeight(i);\n return offset;\n }\n\n private rowOffsets(): number[] {\n const offsets = [0];\n for (let i = 0; i < this.rows.length; i += 1) offsets.push(offsets[i] + this.measuredRowHeight(i));\n return offsets;\n }\n\n private renderList(): void {\n this.buildRows();\n this.renderRows();\n this.announceStatus();\n }\n\n private announceStatus(): void {\n const first = this.rows[0];\n const message = this.hasReachedMaximum()\n ? format(this.strings.maximumSelected, { count: String(this.opts.maxSelections) })\n : first?.kind === \"loading\"\n ? this.strings.loading\n : first?.kind === \"error\"\n ? this.strings.errorLoading\n : first?.kind === \"empty\"\n ? this.strings.noResults\n : first?.kind === \"min-length\"\n ? format(this.strings.minSearchLength, { count: String(this.opts.minSearchLength) })\n : \"\";\n if (this.liveRegion.textContent !== message) this.liveRegion.textContent = message;\n }\n\n private renderRows(): void {\n // Capture the scroll offset and viewport height BEFORE clearing the list:\n // removing the children collapses both scrollHeight (clamping scrollTop to 0)\n // and clientHeight (the list has no explicit height, only max-height, so an\n // empty list reports just its padding instead of the real box height).\n const scrollTop = this.list.scrollTop;\n const clientHeight = this.list.clientHeight;\n const virtual = this.usesVirtualScroll();\n this.list.textContent = \"\";\n\n const rowHeight = this.opts.itemHeight;\n const offsets = this.opts.variableItemHeight ? this.rowOffsets() : null;\n let start = 0;\n let end = this.rows.length;\n if (virtual) {\n const viewport = clientHeight || rowHeight * 8;\n if (this.opts.variableItemHeight) {\n while (start < this.rows.length && offsets![start + 1] < scrollTop) start += 1;\n start = Math.max(0, start - VIRTUAL_BUFFER);\n end = start;\n const target = scrollTop + viewport + VIRTUAL_BUFFER * rowHeight;\n while (end < this.rows.length && offsets![end] < target) end += 1;\n } else {\n start = Math.max(0, Math.floor(scrollTop / rowHeight) - VIRTUAL_BUFFER);\n end = Math.min(this.rows.length, start + Math.ceil(viewport / rowHeight) + VIRTUAL_BUFFER * 2);\n }\n\n const topSpacer = document.createElement(\"li\");\n topSpacer.className = \"forge-select__spacer\";\n topSpacer.setAttribute(\"aria-hidden\", \"true\");\n topSpacer.style.height = `${offsets?.[start] ?? this.rowOffset(start)}px`;\n this.list.append(topSpacer);\n }\n\n for (let i = start; i < end; i++) {\n const element = this.renderRow(this.rows[i]);\n this.list.append(element);\n if (this.opts.variableItemHeight) {\n const measured = element.getBoundingClientRect().height || element.offsetHeight;\n if (measured > 0) this.rowHeightCache.set(this.rowKey(this.rows[i], i), measured);\n }\n }\n\n if (virtual) {\n const bottomSpacer = document.createElement(\"li\");\n bottomSpacer.className = \"forge-select__spacer\";\n bottomSpacer.setAttribute(\"aria-hidden\", \"true\");\n bottomSpacer.style.height = `${offsets ? offsets[this.rows.length] - offsets[end] : this.rowOffset(this.rows.length) - this.rowOffset(end)}px`;\n this.list.append(bottomSpacer);\n\n // Restore the offset that clearing clamped away. The net scroll change\n // within this handler is zero, so this does not re-fire the scroll\n // listener; even if it did, the re-render is idempotent and settles.\n if (this.list.scrollTop !== scrollTop) {\n this.list.scrollTop = scrollTop;\n }\n }\n\n this.updateActiveDescendant();\n }\n\n private renderRow(row: Row): HTMLLIElement {\n const li = document.createElement(\"li\");\n switch (row.kind) {\n case \"group\":\n li.className = \"forge-select__group-label\";\n li.setAttribute(\"role\", \"presentation\");\n li.textContent = row.label;\n break;\n case \"empty\":\n li.className = \"forge-select__empty\";\n li.setAttribute(\"role\", \"option\");\n li.setAttribute(\"aria-disabled\", \"true\");\n li.setAttribute(\"aria-selected\", \"false\");\n li.textContent = this.strings.noResults;\n break;\n case \"min-length\":\n li.className = \"forge-select__min-length\";\n li.setAttribute(\"role\", \"option\");\n li.setAttribute(\"aria-disabled\", \"true\");\n li.setAttribute(\"aria-selected\", \"false\");\n li.textContent = format(this.strings.minSearchLength, { count: String(this.opts.minSearchLength) });\n break;\n case \"error\":\n li.className = \"forge-select__error\";\n li.setAttribute(\"role\", \"option\");\n li.setAttribute(\"aria-disabled\", \"true\");\n li.setAttribute(\"aria-selected\", \"false\");\n li.textContent = this.strings.errorLoading;\n break;\n case \"loading\":\n li.className = \"forge-select__loading\";\n li.setAttribute(\"role\", \"option\");\n li.setAttribute(\"aria-disabled\", \"true\");\n li.setAttribute(\"aria-selected\", \"false\");\n li.textContent = this.strings.loading;\n break;\n case \"loading-more\":\n li.className = \"forge-select__loading-more\";\n li.setAttribute(\"aria-hidden\", \"true\");\n li.textContent = this.strings.loadingMore;\n break;\n case \"create\":\n li.className = \"forge-select__option forge-select__option--create\";\n li.setAttribute(\"role\", \"option\");\n li.id = `${this.uid}-nav-${row.navIndex}`;\n li.dataset.navIndex = String(row.navIndex);\n li.textContent = format(this.strings.createOption, { query: this.query.trim() });\n if (row.navIndex === this.highlightedIndex) li.classList.add(\"forge-select__option--highlighted\");\n break;\n case \"option\": {\n li.className = \"forge-select__option\";\n li.dataset.optionValue = row.option.value;\n if (row.option.className) li.classList.add(...row.option.className.trim().split(/\\s+/).filter(Boolean));\n li.setAttribute(\"role\", \"option\");\n const isSelected = this.selected.includes(row.option.value);\n li.setAttribute(\"aria-selected\", String(isSelected));\n if (isSelected) li.classList.add(\"forge-select__option--selected\");\n if (\n this.opts.multiple &&\n row.hasChildren &&\n computeCheckState(row.option, this.selected, this.isOptionDisabled) === \"some\"\n ) {\n li.classList.add(\"forge-select__option--indeterminate\");\n li.dataset.selectionState = \"mixed\";\n }\n if (row.depth > 0) {\n li.style.paddingLeft = `calc(12px + ${row.depth} * var(--fs-tree-indent, 18px))`;\n }\n if (\n this.isOptionDisabled(row.option) ||\n (this.hasReachedMaximum() && !this.selected.includes(row.option.value))\n ) {\n li.classList.add(\"forge-select__option--disabled\");\n li.setAttribute(\"aria-disabled\", \"true\");\n } else {\n li.id = `${this.uid}-nav-${row.navIndex}`;\n li.dataset.navIndex = String(row.navIndex);\n if (row.navIndex === this.highlightedIndex) li.classList.add(\"forge-select__option--highlighted\");\n }\n if (row.hasChildren) {\n const expanded = this.query !== \"\" || this.expandedValues.has(row.option.value);\n li.setAttribute(\"aria-expanded\", String(expanded));\n const twisty = document.createElement(\"span\");\n twisty.className = \"forge-select__twisty\";\n twisty.dataset.twisty = row.option.value;\n twisty.setAttribute(\"aria-hidden\", \"true\");\n twisty.textContent = expanded ? \"▼\" : \"▶\";\n li.append(twisty);\n }\n li.append(this.optionContent(row.option));\n break;\n }\n }\n return li;\n }\n\n /**\n * Rendered row content is cached per option value and cloned on each render,\n * so templates run once per option instead of once per scroll frame.\n * State classes (selected/highlighted/disabled) live on the <li>, keeping the\n * cached content state-free.\n */\n private optionContent(option: Option): Node {\n if (this.opts.highlightSearch && this.query.trim() && !this.opts.templateResult) {\n const holder = document.createElement(\"span\");\n holder.className = \"forge-select__option-content\";\n renderOptionContent(holder, option, undefined);\n const label = holder.querySelector<HTMLElement>(\".forge-select__option-label\") ?? holder;\n const ranges = findNormalizedRanges(option.label, this.query, this.opts.accentInsensitive);\n if (ranges.length) {\n label.textContent = \"\";\n let cursor = 0;\n for (const [start, end] of ranges) {\n if (start < cursor) continue;\n label.append(document.createTextNode(option.label.slice(cursor, start)));\n const mark = document.createElement(\"mark\");\n mark.className = \"forge-select__match\";\n mark.textContent = option.label.slice(start, end);\n label.append(mark);\n cursor = end;\n }\n label.append(document.createTextNode(option.label.slice(cursor)));\n }\n return holder;\n }\n let cached = this.rowContentCache.get(option.value);\n if (!cached) {\n const holder = document.createElement(\"span\");\n holder.className = \"forge-select__option-content\";\n renderOptionContent(holder, option, this.opts.templateResult);\n if (this.rowContentCache.size >= ROW_CACHE_LIMIT) {\n // FIFO eviction keeps memory bounded on very large lists.\n const oldest = this.rowContentCache.keys().next().value as string;\n this.rowContentCache.delete(oldest);\n }\n this.rowContentCache.set(option.value, holder);\n cached = holder;\n }\n return cached.cloneNode(true);\n }\n\n private moveHighlight(delta: number): void {\n if (this.navItems.length === 0) return;\n const next =\n this.highlightedIndex === -1\n ? delta > 0\n ? 0\n : this.navItems.length - 1\n : (this.highlightedIndex + delta + this.navItems.length) % this.navItems.length;\n this.focusNavIndex(next);\n }\n\n private focusNavIndex(next: number): void {\n this.highlightedIndex = next;\n\n if (this.usesVirtualScroll()) {\n const rowIndex = this.rows.findIndex(\n (row) => (row.kind === \"option\" || row.kind === \"create\") && row.navIndex === next,\n );\n if (rowIndex >= 0) {\n const rowHeight = this.measuredRowHeight(rowIndex);\n const top = this.rowOffset(rowIndex);\n const viewport = this.list.clientHeight || rowHeight * 8;\n let target = this.list.scrollTop;\n if (top < target) target = top;\n else if (top + rowHeight > target + viewport) target = top + rowHeight - viewport;\n if (target !== this.list.scrollTop) this.list.scrollTop = target;\n }\n this.renderRows();\n } else {\n this.renderRows();\n const highlighted = this.list.querySelector<HTMLElement>(\".forge-select__option--highlighted\");\n highlighted?.scrollIntoView?.({ block: \"nearest\" });\n }\n }\n\n private navigateTree(direction: \"left\" | \"right\"): boolean {\n const item = this.navItems[this.highlightedIndex];\n if (!item || item.kind !== \"option\") return false;\n const { option, parentValue } = item;\n const hasChildren = !!option.children?.length;\n const expanded = this.query !== \"\" || this.expandedValues.has(option.value);\n\n if (direction === \"right\") {\n if (hasChildren && !expanded) {\n this.expandedValues.add(option.value);\n this.renderList();\n return true;\n }\n if (hasChildren) {\n const childIndex = this.navItems.findIndex((nav) => nav.kind === \"option\" && nav.parentValue === option.value);\n if (childIndex >= 0) {\n this.focusNavIndex(childIndex);\n return true;\n }\n }\n return false;\n }\n\n if (hasChildren && expanded && this.query === \"\") {\n this.expandedValues.delete(option.value);\n this.renderList();\n return true;\n }\n if (parentValue) {\n const parentIndex = this.navItems.findIndex((nav) => nav.kind === \"option\" && nav.option.value === parentValue);\n if (parentIndex >= 0) {\n this.focusNavIndex(parentIndex);\n return true;\n }\n }\n return false;\n }\n\n private updateActiveDescendant(): void {\n const target = this.searchInput ?? this.control;\n if (this.highlightedIndex >= 0) {\n target.setAttribute(\"aria-activedescendant\", `${this.uid}-nav-${this.highlightedIndex}`);\n } else {\n target.removeAttribute(\"aria-activedescendant\");\n }\n }\n\n // ---------------------------------------------------------------- remote data\n\n private scheduleRemoteLoad(query: string, delay: number): void {\n if (this.ajaxTimer) clearTimeout(this.ajaxTimer);\n const requestId = ++this.ajaxRequestId;\n this.ajaxController?.abort();\n this.ajaxController = null;\n this.page = 0;\n this.hasMore = true;\n this.setLoading(true);\n this.loadingMore = false;\n this.loadError = null;\n this.renderList();\n this.ajaxTimer = setTimeout(() => {\n this.ajaxTimer = null;\n void this.loadRemote(query, { requestId });\n }, delay);\n }\n\n private setLoading(loading: boolean): void {\n if (this.loading === loading) return;\n this.loading = loading;\n this.emitter.emit(\"loading\", loading);\n }\n\n private remoteCacheKey(query: string, page: number): string {\n return `${query}\\u0000${page}`;\n }\n\n private async requestRemote(query: string, page: number, signal: AbortSignal): Promise<unknown> {\n const ajax = this.opts.ajax!;\n const attempts = Math.max(0, Math.floor(ajax.retry ?? 0)) + 1;\n let lastError: unknown;\n for (let attempt = 0; attempt < attempts; attempt += 1) {\n try {\n if (ajax.request) return await ajax.request(query, page, signal);\n const response = await fetch(buildUrl(ajax, query, page), { signal });\n if (response.ok === false) throw new Error(`ForgeSelect: remote request failed with HTTP ${response.status}`);\n return await response.json();\n } catch (error) {\n lastError = error;\n if (signal.aborted || attempt === attempts - 1) throw error;\n const delay = Math.max(0, ajax.retryDelay ?? 250) * 2 ** attempt;\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, delay);\n signal.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(new DOMException(\"Aborted\", \"AbortError\"));\n },\n { once: true },\n );\n });\n }\n }\n throw lastError;\n }\n\n private async prefetchRemote(query: string): Promise<void> {\n const ajax = this.opts.ajax;\n if (!ajax || (ajax.cacheTtl ?? 30000) <= 0) return;\n const key = this.remoteCacheKey(query, 0);\n if (this.remoteCache.get(key)) return;\n const controller = new AbortController();\n try {\n const json = await this.requestRemote(query, 0, controller.signal);\n this.remoteCache.set(key, normalizeRemoteResult(ajax, json), ajax.cacheTtl ?? 30000);\n } catch {\n // Prefetch is intentionally best-effort and must not surface UI errors.\n }\n }\n\n /**\n * Fires on every list scroll. Only acts when pagination is opted into via\n * `ajax.pagination`; reads real scroll geometry rather than row counts so\n * it works whether or not virtual scrolling is active for this list.\n */\n private maybeLoadNextPage(): void {\n const ajax = this.opts.ajax;\n if (!ajax?.pagination || !this.hasMore || this.loading || this.loadingMore) return;\n const { scrollHeight, scrollTop, clientHeight } = this.list;\n const threshold = this.opts.itemHeight * 2;\n if (scrollHeight - scrollTop - clientHeight >= threshold) return;\n this.loadingMore = true;\n this.renderList();\n void this.loadRemote(this.query, { append: true });\n }\n\n private async loadRemote(\n query: string,\n { append = false, requestId }: { append?: boolean; requestId?: number } = {},\n ): Promise<void> {\n const ajax = this.opts.ajax!;\n const activeRequestId = requestId ?? ++this.ajaxRequestId;\n if (activeRequestId !== this.ajaxRequestId) return;\n this.ajaxController?.abort();\n const controller = new AbortController();\n this.ajaxController = controller;\n const page = append ? this.page + 1 : 0;\n try {\n const key = this.remoteCacheKey(query, page);\n let result = this.remoteCache.get(key);\n if (!result) {\n const json = await this.requestRemote(query, page, controller.signal);\n result = normalizeRemoteResult(ajax, json);\n this.remoteCache.set(key, result, ajax.cacheTtl ?? 30000);\n }\n if (activeRequestId !== this.ajaxRequestId || this.destroyed) return;\n const { options, hasMore } = result;\n\n if (append) {\n const existing = collectValues(this.data);\n this.data = [...this.data, ...options.filter((o) => !existing.has(o.value))];\n } else {\n this.data = options;\n this.rowContentCache.clear();\n }\n this.page = page;\n this.hasMore = hasMore;\n this.remoteLoaded = true;\n this.loadError = null;\n } catch (cause) {\n if (activeRequestId !== this.ajaxRequestId || this.destroyed || controller.signal.aborted) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n if (!append) {\n this.data = [];\n this.rowContentCache.clear();\n }\n this.hasMore = false;\n this.loadError = error;\n this.emitter.emit(\"error\", error);\n } finally {\n if (activeRequestId === this.ajaxRequestId && !this.destroyed) {\n this.ajaxController = null;\n this.setLoading(false);\n this.loadingMore = false;\n if (this.isOpen) this.renderList();\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|