forge-select 0.4.0 → 0.6.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/dist/index.d.cts CHANGED
@@ -32,6 +32,16 @@ interface AjaxConfig {
32
32
  params?: (query: string, page: number) => Record<string, unknown>;
33
33
  /** Debounce in milliseconds. Default 250. */
34
34
  debounce?: number;
35
+ /** Load the initial empty query when the dropdown opens. Default true. */
36
+ loadOnOpen?: boolean;
37
+ /** Cache successful pages for this many milliseconds. Set 0 to disable. Default 30000. */
38
+ cacheTtl?: number;
39
+ /** Number of retries after a failed request. Default 0. */
40
+ retry?: number;
41
+ /** Base delay for exponential retry backoff. Default 250ms. */
42
+ retryDelay?: number;
43
+ /** Queries to warm in the background after construction. */
44
+ prefetch?: string[];
35
45
  /**
36
46
  * Opt in to loading additional pages as the user scrolls near the bottom
37
47
  * of the dropdown, instead of only reloading on search. Default false.
@@ -55,6 +65,8 @@ interface ForgeSelectPlugin {
55
65
  onDestroy?(select: ForgeSelect): void;
56
66
  }
57
67
  type TemplateFn = (option: Option) => string | Node;
68
+ type SearchField = "label" | "description" | `meta.${string}`;
69
+ type SearchScorer = (option: Option, query: string, normalizedQuery: string) => number;
58
70
  interface ForgeSelectOptions {
59
71
  placeholder?: string;
60
72
  searchable?: boolean;
@@ -100,6 +112,16 @@ interface ForgeSelectOptions {
100
112
  * substring match. Receives the trimmed (not lowercased) query.
101
113
  */
102
114
  filterOption?: (option: Option, query: string) => boolean;
115
+ /** Fields used by built-in search. Default: label and description. */
116
+ searchFields?: SearchField[];
117
+ /** Split the query into tokens which may match across fields. Default true. */
118
+ tokenSearch?: boolean;
119
+ /** Match text without case or diacritics. Default true. */
120
+ accentInsensitive?: boolean;
121
+ /** Optional relevance scorer. Values <= 0 exclude an option. */
122
+ searchScorer?: SearchScorer;
123
+ /** Highlight built-in label matches with <mark>. Default false. */
124
+ highlightSearch?: boolean;
103
125
  /**
104
126
  * Hides results (showing a hint row instead) until the trimmed search
105
127
  * query reaches this length. Also delays ajax requests until the
@@ -122,8 +144,8 @@ interface ForgeSelectOptions {
122
144
  * once the list exceeds ~100 rows.
123
145
  */
124
146
  virtualScroll?: boolean;
125
- /** Row height in px used by the virtual scroller. Default 36; raise for rich items. */
126
- itemHeight?: number;
147
+ /** Row height in px, or "auto" to measure variable-height rows. Default 36. */
148
+ itemHeight?: number | "auto";
127
149
  language?: string | Record<string, string>;
128
150
  plugins?: ForgeSelectPlugin[];
129
151
  /**
@@ -143,6 +165,12 @@ interface SetValueOptions {
143
165
  /** Emit Forge Select's `change` event after updating. Default true. */
144
166
  emitChange?: boolean;
145
167
  }
168
+ interface SetSearchQueryOptions {
169
+ /** Emit the `search` event. Default true. */
170
+ emitSearch?: boolean;
171
+ }
172
+ /** Runtime-updateable options. Structural mode/plugin/portal changes still require remounting. */
173
+ type ForgeSelectUpdateOptions = Omit<Partial<ForgeSelectOptions>, "multiple" | "searchable" | "plugins" | "dropdownParent">;
146
174
  interface MaximumSelectionEvent {
147
175
  limit: number;
148
176
  option: Option;
@@ -154,6 +182,8 @@ interface ForgeSelectEventMap {
154
182
  search: string;
155
183
  clear: void;
156
184
  error: Error;
185
+ loading: boolean;
186
+ invalid: string;
157
187
  select: Option;
158
188
  unselect: Option;
159
189
  create: Option;
@@ -191,7 +221,14 @@ declare class ForgeSelect {
191
221
  private rows;
192
222
  private navItems;
193
223
  private highlightedIndex;
224
+ private typeaheadBuffer;
225
+ private typeaheadTimer;
194
226
  private rowContentCache;
227
+ private rowHeightCache;
228
+ private rowOffsetsCache;
229
+ private scrollRafId;
230
+ private ancestorScrollRafId;
231
+ private searchIndex;
195
232
  private expandedValues;
196
233
  private loading;
197
234
  private loadingMore;
@@ -201,6 +238,7 @@ declare class ForgeSelect {
201
238
  private ajaxRequestId;
202
239
  private ajaxController;
203
240
  private remoteLoaded;
241
+ private remoteCache;
204
242
  private loadError;
205
243
  private originalDisplay;
206
244
  private originalDisabled;
@@ -230,6 +268,15 @@ declare class ForgeSelect {
230
268
  private positionDropdown;
231
269
  destroy(): void;
232
270
  getValue(): ForgeSelectValue;
271
+ getSearchQuery(): string;
272
+ setSearchQuery(query: string, options?: SetSearchQueryOptions): void;
273
+ isDropdownOpen(): boolean;
274
+ updateOptions(options: ForgeSelectUpdateOptions): void;
275
+ validate(): boolean;
276
+ setCustomValidity(message: string): void;
277
+ reportValidity(): boolean;
278
+ reload(): void;
279
+ clearRemoteCache(): void;
233
280
  setValue(value: ForgeSelectValue, options?: SetValueOptions): void;
234
281
  /**
235
282
  * Replaces the option list after construction. An open dropdown re-renders
@@ -264,7 +311,14 @@ declare class ForgeSelect {
264
311
  private updateSearchVisibility;
265
312
  private buildDom;
266
313
  private bindEvents;
314
+ private applySearchQuery;
267
315
  private handleKeydown;
316
+ /**
317
+ * Jumps the highlight to the next nav item (wrapping) whose label starts
318
+ * with the accumulated buffer, matching native <select> typeahead: rapid
319
+ * distinct keystrokes narrow the prefix, a pause resets it.
320
+ */
321
+ private handleTypeahead;
268
322
  private canSelectOption;
269
323
  private hasReachedMaximum;
270
324
  private announceMaximum;
@@ -305,6 +359,10 @@ declare class ForgeSelect {
305
359
  private buildRows;
306
360
  private hasExactMatch;
307
361
  private usesVirtualScroll;
362
+ private rowKey;
363
+ private measuredRowHeight;
364
+ private rowOffset;
365
+ private rowOffsets;
308
366
  private renderList;
309
367
  private announceStatus;
310
368
  private renderRows;
@@ -321,6 +379,10 @@ declare class ForgeSelect {
321
379
  private navigateTree;
322
380
  private updateActiveDescendant;
323
381
  private scheduleRemoteLoad;
382
+ private setLoading;
383
+ private remoteCacheKey;
384
+ private requestRemote;
385
+ private prefetchRemote;
324
386
  /**
325
387
  * Fires on every list scroll. Only acts when pagination is opted into via
326
388
  * `ajax.pagination`; reads real scroll geometry rather than row counts so
@@ -330,4 +392,4 @@ declare class ForgeSelect {
330
392
  private loadRemote;
331
393
  }
332
394
 
333
- export { type AjaxConfig, type DataItem, ForgeSelect, type ForgeSelectEvent, type ForgeSelectEventHandler, type ForgeSelectEventMap, type ForgeSelectOptions, type ForgeSelectPlugin, type ForgeSelectValue, type MaximumSelectionEvent, type Option, type OptionGroup, type SetValueOptions, type TemplateFn, ForgeSelect as default };
395
+ export { type AjaxConfig, type DataItem, ForgeSelect, type ForgeSelectEvent, type ForgeSelectEventHandler, type ForgeSelectEventMap, type ForgeSelectOptions, type ForgeSelectPlugin, type ForgeSelectUpdateOptions, type ForgeSelectValue, type MaximumSelectionEvent, type Option, type OptionGroup, type SearchField, type SearchScorer, type SetSearchQueryOptions, type SetValueOptions, type TemplateFn, ForgeSelect as default };
package/dist/index.d.ts CHANGED
@@ -32,6 +32,16 @@ interface AjaxConfig {
32
32
  params?: (query: string, page: number) => Record<string, unknown>;
33
33
  /** Debounce in milliseconds. Default 250. */
34
34
  debounce?: number;
35
+ /** Load the initial empty query when the dropdown opens. Default true. */
36
+ loadOnOpen?: boolean;
37
+ /** Cache successful pages for this many milliseconds. Set 0 to disable. Default 30000. */
38
+ cacheTtl?: number;
39
+ /** Number of retries after a failed request. Default 0. */
40
+ retry?: number;
41
+ /** Base delay for exponential retry backoff. Default 250ms. */
42
+ retryDelay?: number;
43
+ /** Queries to warm in the background after construction. */
44
+ prefetch?: string[];
35
45
  /**
36
46
  * Opt in to loading additional pages as the user scrolls near the bottom
37
47
  * of the dropdown, instead of only reloading on search. Default false.
@@ -55,6 +65,8 @@ interface ForgeSelectPlugin {
55
65
  onDestroy?(select: ForgeSelect): void;
56
66
  }
57
67
  type TemplateFn = (option: Option) => string | Node;
68
+ type SearchField = "label" | "description" | `meta.${string}`;
69
+ type SearchScorer = (option: Option, query: string, normalizedQuery: string) => number;
58
70
  interface ForgeSelectOptions {
59
71
  placeholder?: string;
60
72
  searchable?: boolean;
@@ -100,6 +112,16 @@ interface ForgeSelectOptions {
100
112
  * substring match. Receives the trimmed (not lowercased) query.
101
113
  */
102
114
  filterOption?: (option: Option, query: string) => boolean;
115
+ /** Fields used by built-in search. Default: label and description. */
116
+ searchFields?: SearchField[];
117
+ /** Split the query into tokens which may match across fields. Default true. */
118
+ tokenSearch?: boolean;
119
+ /** Match text without case or diacritics. Default true. */
120
+ accentInsensitive?: boolean;
121
+ /** Optional relevance scorer. Values <= 0 exclude an option. */
122
+ searchScorer?: SearchScorer;
123
+ /** Highlight built-in label matches with <mark>. Default false. */
124
+ highlightSearch?: boolean;
103
125
  /**
104
126
  * Hides results (showing a hint row instead) until the trimmed search
105
127
  * query reaches this length. Also delays ajax requests until the
@@ -122,8 +144,8 @@ interface ForgeSelectOptions {
122
144
  * once the list exceeds ~100 rows.
123
145
  */
124
146
  virtualScroll?: boolean;
125
- /** Row height in px used by the virtual scroller. Default 36; raise for rich items. */
126
- itemHeight?: number;
147
+ /** Row height in px, or "auto" to measure variable-height rows. Default 36. */
148
+ itemHeight?: number | "auto";
127
149
  language?: string | Record<string, string>;
128
150
  plugins?: ForgeSelectPlugin[];
129
151
  /**
@@ -143,6 +165,12 @@ interface SetValueOptions {
143
165
  /** Emit Forge Select's `change` event after updating. Default true. */
144
166
  emitChange?: boolean;
145
167
  }
168
+ interface SetSearchQueryOptions {
169
+ /** Emit the `search` event. Default true. */
170
+ emitSearch?: boolean;
171
+ }
172
+ /** Runtime-updateable options. Structural mode/plugin/portal changes still require remounting. */
173
+ type ForgeSelectUpdateOptions = Omit<Partial<ForgeSelectOptions>, "multiple" | "searchable" | "plugins" | "dropdownParent">;
146
174
  interface MaximumSelectionEvent {
147
175
  limit: number;
148
176
  option: Option;
@@ -154,6 +182,8 @@ interface ForgeSelectEventMap {
154
182
  search: string;
155
183
  clear: void;
156
184
  error: Error;
185
+ loading: boolean;
186
+ invalid: string;
157
187
  select: Option;
158
188
  unselect: Option;
159
189
  create: Option;
@@ -191,7 +221,14 @@ declare class ForgeSelect {
191
221
  private rows;
192
222
  private navItems;
193
223
  private highlightedIndex;
224
+ private typeaheadBuffer;
225
+ private typeaheadTimer;
194
226
  private rowContentCache;
227
+ private rowHeightCache;
228
+ private rowOffsetsCache;
229
+ private scrollRafId;
230
+ private ancestorScrollRafId;
231
+ private searchIndex;
195
232
  private expandedValues;
196
233
  private loading;
197
234
  private loadingMore;
@@ -201,6 +238,7 @@ declare class ForgeSelect {
201
238
  private ajaxRequestId;
202
239
  private ajaxController;
203
240
  private remoteLoaded;
241
+ private remoteCache;
204
242
  private loadError;
205
243
  private originalDisplay;
206
244
  private originalDisabled;
@@ -230,6 +268,15 @@ declare class ForgeSelect {
230
268
  private positionDropdown;
231
269
  destroy(): void;
232
270
  getValue(): ForgeSelectValue;
271
+ getSearchQuery(): string;
272
+ setSearchQuery(query: string, options?: SetSearchQueryOptions): void;
273
+ isDropdownOpen(): boolean;
274
+ updateOptions(options: ForgeSelectUpdateOptions): void;
275
+ validate(): boolean;
276
+ setCustomValidity(message: string): void;
277
+ reportValidity(): boolean;
278
+ reload(): void;
279
+ clearRemoteCache(): void;
233
280
  setValue(value: ForgeSelectValue, options?: SetValueOptions): void;
234
281
  /**
235
282
  * Replaces the option list after construction. An open dropdown re-renders
@@ -264,7 +311,14 @@ declare class ForgeSelect {
264
311
  private updateSearchVisibility;
265
312
  private buildDom;
266
313
  private bindEvents;
314
+ private applySearchQuery;
267
315
  private handleKeydown;
316
+ /**
317
+ * Jumps the highlight to the next nav item (wrapping) whose label starts
318
+ * with the accumulated buffer, matching native <select> typeahead: rapid
319
+ * distinct keystrokes narrow the prefix, a pause resets it.
320
+ */
321
+ private handleTypeahead;
268
322
  private canSelectOption;
269
323
  private hasReachedMaximum;
270
324
  private announceMaximum;
@@ -305,6 +359,10 @@ declare class ForgeSelect {
305
359
  private buildRows;
306
360
  private hasExactMatch;
307
361
  private usesVirtualScroll;
362
+ private rowKey;
363
+ private measuredRowHeight;
364
+ private rowOffset;
365
+ private rowOffsets;
308
366
  private renderList;
309
367
  private announceStatus;
310
368
  private renderRows;
@@ -321,6 +379,10 @@ declare class ForgeSelect {
321
379
  private navigateTree;
322
380
  private updateActiveDescendant;
323
381
  private scheduleRemoteLoad;
382
+ private setLoading;
383
+ private remoteCacheKey;
384
+ private requestRemote;
385
+ private prefetchRemote;
324
386
  /**
325
387
  * Fires on every list scroll. Only acts when pagination is opted into via
326
388
  * `ajax.pagination`; reads real scroll geometry rather than row counts so
@@ -330,4 +392,4 @@ declare class ForgeSelect {
330
392
  private loadRemote;
331
393
  }
332
394
 
333
- export { type AjaxConfig, type DataItem, ForgeSelect, type ForgeSelectEvent, type ForgeSelectEventHandler, type ForgeSelectEventMap, type ForgeSelectOptions, type ForgeSelectPlugin, type ForgeSelectValue, type MaximumSelectionEvent, type Option, type OptionGroup, type SetValueOptions, type TemplateFn, ForgeSelect as default };
395
+ export { type AjaxConfig, type DataItem, ForgeSelect, type ForgeSelectEvent, type ForgeSelectEventHandler, type ForgeSelectEventMap, type ForgeSelectOptions, type ForgeSelectPlugin, type ForgeSelectUpdateOptions, type ForgeSelectValue, type MaximumSelectionEvent, type Option, type OptionGroup, type SearchField, type SearchScorer, type SetSearchQueryOptions, type SetValueOptions, type TemplateFn, ForgeSelect as default };
@@ -1,2 +1,2 @@
1
- "use strict";var ForgeSelectBundle=(()=>{var E=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var B=(o,t)=>{for(var e in t)E(o,e,{get:t[e],enumerable:!0})},$=(o,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of j(t))!P.call(o,i)&&i!==e&&E(o,i,{get:()=>t[i],enumerable:!(s=F(t,i))||s.enumerable});return o};var U=o=>$(E({},"__esModule",{value:!0}),o);var W={};B(W,{ForgeSelect:()=>f,default:()=>f});var b=class{constructor(){this.handlers=new Map}on(t,e){let s=this.handlers.get(t);s||(s=new Set,this.handlers.set(t,s)),s.add(e)}off(t,e){this.handlers.get(t)?.delete(e)}emit(t,...e){let s=this.handlers.get(t);if(s)for(let i of[...s])i(...e)}clear(){this.handlers.clear()}};function D(o,t,e,s=4){let i=e-o.bottom,r=o.top,n=t>i&&r>i;return{dropUp:n,top:n?o.top-t-s:o.bottom+s}}var O={en:{noResults:"No results found",loading:"Loading\u2026",loadingMore:"Loading more\u2026",errorLoading:"Could not load options",createOption:'Create "{query}"',clearSelection:"Clear selection",removeItem:"Remove {label}",search:"Search",reorderHint:"{label}. Press Alt+Left or Alt+Right to reorder.",minSearchLength:"Type {count} or more characters to search",maximumSelected:"Maximum of {count} selections reached"},vi:{noResults:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3",loading:"\u0110ang t\u1EA3i\u2026",loadingMore:"\u0110ang t\u1EA3i th\xEAm\u2026",errorLoading:"Kh\xF4ng th\u1EC3 t\u1EA3i t\xF9y ch\u1ECDn",createOption:'T\u1EA1o "{query}"',clearSelection:"X\xF3a l\u1EF1a ch\u1ECDn",removeItem:"X\xF3a {label}",search:"T\xECm ki\u1EBFm",reorderHint:"{label}. Nh\u1EA5n Alt+Tr\xE1i ho\u1EB7c Alt+Ph\u1EA3i \u0111\u1EC3 s\u1EAFp x\u1EBFp l\u1EA1i.",minSearchLength:"Nh\u1EADp th\xEAm {count} k\xFD t\u1EF1 \u0111\u1EC3 t\xECm ki\u1EBFm",maximumSelected:"\u0110\xE3 \u0111\u1EA1t t\u1ED1i \u0111a {count} l\u1EF1a ch\u1ECDn"}};function _(o){return typeof o=="string"?O[o]??O.en:{...O.en,...o}}function u(o,t){return o.replace(/\{(\w+)\}/g,(e,s)=>t[s]??e)}function H(o){let t=[];for(let e of Array.from(o.children))e instanceof HTMLOptGroupElement?t.push({label:e.label,options:Array.from(e.querySelectorAll("option")).map(M)}):e instanceof HTMLOptionElement&&t.push(M(e));return t}function M(o){let t=o.parentElement instanceof HTMLOptGroupElement&&o.parentElement.disabled;return{value:o.value,label:o.textContent?.trim()??o.value,disabled:o.disabled||t||void 0}}function x(o,t,e,s="row"){if(e){let i=e(t);typeof i=="string"?o.innerHTML=i:o.append(i);return}if(!t.avatar&&!t.description){o.textContent=t.label;return}if(t.avatar){let i=document.createElement("img");i.className=s==="row"?"forge-select__option-avatar":"forge-select__inline-avatar",i.src=t.avatar,i.alt="",i.setAttribute("loading","lazy"),i.setAttribute("decoding","async"),o.append(i)}if(s==="row"&&t.description){let i=document.createElement("span");i.className="forge-select__option-body";let r=document.createElement("span");r.className="forge-select__option-label",r.textContent=t.label;let n=document.createElement("span");n.className="forge-select__option-desc",n.textContent=t.description,i.append(r,n),o.append(i)}else{let i=document.createElement("span");i.className="forge-select__option-label",i.textContent=t.label,o.append(i)}}function R(o,t,e){if(!o.url)throw new Error("ForgeSelect: ajax requires either url or request.");if(typeof o.url=="function")return o.url(t,e);if(!o.params)return o.url;let s=new URLSearchParams;for(let[r,n]of Object.entries(o.params(t,e)))s.set(r,String(n));let i=o.url.includes("?")?"&":"?";return`${o.url}${i}${s.toString()}`}function k(o,t){let e=o.transform?o.transform(t):t;if(Array.isArray(e))return{options:e,hasMore:!1};if(!e||!Array.isArray(e.options))throw new Error("ForgeSelect: ajax.transform must return an array of options, or an object shaped like { options: Option[], hasMore?: boolean }.");return{options:e.options,hasMore:o.pagination?!!e.hasMore:!1}}function p(o){return o.options!==void 0}var w=o=>!!o.disabled;function v(o,t=w){if(!o.children)return[];let e=[];for(let s of o.children)t(s)||e.push(s.value),e.push(...v(s,t));return e}function y(o,t,e=w){if(!o.children?.length)return t.includes(o.value)?"all":"none";let s=o.children.filter(i=>!e(i)).map(i=>y(i,t,e));return s.length===0?"none":s.every(i=>i==="all")?"all":s.every(i=>i==="none")?"none":"some"}function N(o,t){let e=s=>{for(let i of s){if(i.value===t)return i;let r=i.children?e(i.children):void 0;if(r)return r}};for(let s of o){let i=e(p(s)?s.options:[s]);if(i)return i}}function L(o,t,e=w){let s=i=>{if(!i.children?.length)return;for(let a of i.children)s(a);let r=y(i,t,e),n=t.indexOf(i.value);r==="all"&&n===-1?t.push(i.value):r!=="all"&&n!==-1&&t.splice(n,1)};for(let i of o)(p(i)?i.options:[i]).forEach(s)}function I(o){let t=new Set,e=s=>{t.add(s.value),s.children?.forEach(e)};for(let s of o)(p(s)?s.options:[s]).forEach(e);return t}function V(o,t){return o.length===t.length&&o.every((e,s)=>e===t[s])}var G=36,q=5,z=100,K=2e3,X=0,f=class{constructor(t,e={}){this.selected=[];this.selectedOptions=new Map;this.suppressNextTagClick=!1;this.emitter=new b;this.uid=`forge-select-${++X}`;this.searchInput=null;this.portalHost=null;this.isOpen=!1;this.isDisabled=!1;this.destroyed=!1;this.query="";this.rows=[];this.navItems=[];this.highlightedIndex=-1;this.rowContentCache=new Map;this.expandedValues=new Set;this.loading=!1;this.loadingMore=!1;this.page=0;this.hasMore=!0;this.ajaxTimer=null;this.ajaxRequestId=0;this.ajaxController=null;this.remoteLoaded=!1;this.loadError=null;this.originalDisplay="";this.originalDisabled=!1;this.nativeSelect=null;this.nativeForm=null;this.syncingNative=!1;this.isOptionDisabled=t=>t.disabled===!0||(this.opts.isOptionDisabled?.(t)??!1);this.pointerDownOnControl=!1;this.onDocumentMouseDown=t=>{let e=t.target;!this.root.contains(e)&&!this.portalHost?.contains(e)&&this.close()};this.onWindowResize=()=>{this.positionDropdown()};this.onAncestorScroll=()=>{this.portalHost&&this.positionDropdown()};this.onNativeInvalid=t=>{t.preventDefault(),this.control.classList.add("forge-select__control--invalid"),this.control.setAttribute("aria-invalid","true"),this.isOpen||this.open(),this.control.focus()};this.onNativeChange=()=>{if(!this.nativeSelect||this.destroyed||this.syncingNative)return;let t=Array.from(this.nativeSelect.selectedOptions,e=>e.value);this.applyNativeValues(t)};this.onFormReset=()=>{if(!this.nativeSelect||this.destroyed)return;let t=Array.from(this.nativeSelect.options).filter(e=>e.defaultSelected).map(e=>e.value);this.applyNativeValues(t)};let s=typeof t=="string"?document.querySelector(t):t;if(!s)throw new Error(`ForgeSelect: target element not found: ${String(t)}`);this.el=s;let i=s instanceof HTMLSelectElement?s:null;if(this.nativeSelect=i,this.nativeForm=i?.form??null,this.originalDisplay=s.style.display,this.originalDisabled=i?.disabled??!1,this.opts={placeholder:e.placeholder??"",searchable:e.searchable??!0,multiple:e.multiple??i?.multiple??!1,clearable:e.clearable??!1,allowCreate:e.allowCreate??!1,sortable:e.sortable??!1,closeOnSelect:e.closeOnSelect??!1,maxSelections:e.maxSelections==null||!Number.isFinite(e.maxSelections)?void 0:Math.max(0,Math.floor(e.maxSelections)),theme:e.theme??"default",disabled:e.disabled??i?.disabled??!1,required:e.required??i?.required??!1,data:e.data,ajax:e.ajax,templateResult:e.templateResult,templateSelection:e.templateSelection,filterOption:e.filterOption,minSearchLength:Math.max(0,Math.floor(e.minSearchLength??0)),minResultsForSearch:Math.max(0,Math.floor(e.minResultsForSearch??0)),isOptionDisabled:e.isOptionDisabled,virtualScroll:e.virtualScroll,itemHeight:e.itemHeight??G,language:e.language??"en",plugins:e.plugins??[],openOnFocus:e.openOnFocus??!1,dropdownParent:e.dropdownParent},this.strings=_(this.opts.language),this.plugins=this.opts.plugins,i&&(i.required=this.opts.required),this.data=this.opts.data??(i?H(i):[]),i&&!this.opts.data){let r=Array.from(i.options),n=i.multiple||i.selectedIndex>0||r.some(a=>a.defaultSelected);for(let a of r)n&&a.selected&&this.selectValue(a.value,!1)}this.buildDom(),this.renderValue(),this.opts.disabled&&this.disable(),i?.addEventListener("change",this.onNativeChange),i?.addEventListener("invalid",this.onNativeInvalid),this.nativeForm?.addEventListener("reset",this.onFormReset);for(let r of this.plugins)r.onInit?.(this)}applyNativeValues(t){this.selected=[];for(let e of this.opts.multiple?t:t.slice(0,1))this.selectValue(e,!1);this.renderValue(),this.isOpen&&this.renderList(),this.emitter.emit("change",this.getValue())}open(){if(!(this.isOpen||this.isDisabled||this.destroyed)){this.isOpen=!0,this.dropdown.hidden=!1,this.root.classList.add("forge-select--open"),this.control.setAttribute("aria-expanded","true"),document.addEventListener("mousedown",this.onDocumentMouseDown),this.opts.ajax&&!this.remoteLoaded&&this.scheduleRemoteLoad(this.query,0),this.renderList(),this.positionDropdown(),window.addEventListener("resize",this.onWindowResize),document.addEventListener("scroll",this.onAncestorScroll,!0),this.searchInput&&!this.searchInput.hidden&&this.searchInput.focus(),this.emitter.emit("open");for(let t of this.plugins)t.onOpen?.(this)}}close(){if(this.isOpen){this.isOpen=!1,this.dropdown.hidden=!0,this.root.classList.remove("forge-select--open"),this.root.classList.remove("forge-select--drop-up"),this.control.setAttribute("aria-expanded","false"),document.removeEventListener("mousedown",this.onDocumentMouseDown),window.removeEventListener("resize",this.onWindowResize),document.removeEventListener("scroll",this.onAncestorScroll,!0),this.highlightedIndex=-1,this.searchInput&&(this.searchInput.value="",this.query=""),this.emitter.emit("close");for(let t of this.plugins)t.onClose?.(this)}}positionDropdown(){let t=this.control.getBoundingClientRect(),e=D(t,this.dropdown.offsetHeight,window.innerHeight);this.root.classList.toggle("forge-select--drop-up",e.dropUp),this.portalHost&&(this.portalHost.style.top=`${e.top}px`,this.portalHost.style.left=`${t.left}px`,this.portalHost.style.width=`${t.width}px`)}destroy(){if(!this.destroyed){this.close();for(let t of this.plugins)t.onDestroy?.(this);this.destroyed=!0,this.ajaxTimer&&clearTimeout(this.ajaxTimer),this.ajaxController?.abort(),this.nativeSelect?.removeEventListener("change",this.onNativeChange),this.nativeSelect?.removeEventListener("invalid",this.onNativeInvalid),this.nativeForm?.removeEventListener("reset",this.onFormReset),this.rowContentCache.clear(),this.portalHost?.remove(),this.root.remove(),this.el.style.display=this.originalDisplay,this.nativeSelect&&(this.nativeSelect.disabled=this.originalDisabled),this.emitter.clear()}}getValue(){return this.opts.multiple?[...this.selected]:this.selected[0]??null}setValue(t,e={}){let s=t==null?[]:Array.isArray(t)?t:[t],i=this.opts.multiple?s:s.slice(0,1);if(!V(i,this.selected)){this.selected=[];for(let r of i)this.selectValue(r,!1);this.afterSelectionChange(e.emitChange??!0)}}setData(t){this.ajaxTimer&&(clearTimeout(this.ajaxTimer),this.ajaxTimer=null),this.ajaxController?.abort(),this.ajaxController=null,this.ajaxRequestId+=1,this.loading=!1,this.loadingMore=!1,this.loadError=null,this.remoteLoaded=!0,this.page=0,this.hasMore=!1,this.data=t,this.opts.data=t,this.updateSearchVisibility(),this.rowContentCache.clear(),this.highlightedIndex=-1,this.isOpen&&this.renderList()}selectAll(){if(this.opts.multiple){this.selected=[];for(let t of this.allSelectableValues()){let e=this.findOption(t);e&&this.canSelectOption(e)&&this.selectValue(t,!1)}this.afterSelectionChange()}}clearAll(){this.clearSelection()}enable(){this.isDisabled=!1,this.root.classList.remove("forge-select--disabled"),this.control.tabIndex=0,this.control.setAttribute("aria-disabled","false"),this.nativeSelect&&(this.nativeSelect.disabled=!1)}disable(){this.close(),this.isDisabled=!0,this.root.classList.add("forge-select--disabled"),this.control.tabIndex=-1,this.control.setAttribute("aria-disabled","true"),this.nativeSelect&&(this.nativeSelect.disabled=!0)}on(t,e){this.emitter.on(t,e)}off(t,e){this.emitter.off(t,e)}applyAccessibleName(){let t=this.el.getAttribute("aria-labelledby"),e=this.el.getAttribute("aria-label");if(t)this.control.setAttribute("aria-labelledby",t);else if(e)this.control.setAttribute("aria-label",e);else if(this.el.id){let s=Array.from(document.getElementsByTagName("label")).find(i=>i.htmlFor===this.el.id);s&&(s.id||(s.id=`${this.uid}-label`),this.control.setAttribute("aria-labelledby",s.id))}}shouldShowSearch(){return this.opts.searchable&&(this.opts.ajax!=null||I(this.data).size>=this.opts.minResultsForSearch)}updateSearchVisibility(){this.searchInput&&(this.searchInput.hidden=!this.shouldShowSearch(),this.searchInput.hidden&&(this.searchInput.value="",this.query=""))}buildDom(){let t=typeof this.opts.dropdownParent=="string"?document.querySelector(this.opts.dropdownParent):this.opts.dropdownParent;if(this.opts.dropdownParent&&!t)throw new Error(`ForgeSelect: dropdown parent not found: ${String(this.opts.dropdownParent)}`);this.root=document.createElement("div"),this.root.className="forge-select",this.root.dataset.theme=this.opts.theme,this.root.style.setProperty("--fs-item-height",`${this.opts.itemHeight}px`),this.opts.sortable&&this.opts.multiple&&this.root.classList.add("forge-select--sortable"),this.control=document.createElement("div"),this.control.className="forge-select__control",this.control.setAttribute("role","combobox"),this.control.setAttribute("aria-haspopup","listbox"),this.control.setAttribute("aria-expanded","false"),this.control.setAttribute("aria-controls",`${this.uid}-list`),this.opts.required&&this.control.setAttribute("aria-required","true"),this.control.tabIndex=0,this.applyAccessibleName(),this.valueEl=document.createElement("div"),this.valueEl.className="forge-select__value",this.clearBtn=document.createElement("button"),this.clearBtn.type="button",this.clearBtn.className="forge-select__clear",this.clearBtn.setAttribute("aria-label",this.strings.clearSelection),this.clearBtn.textContent="\xD7",this.clearBtn.hidden=!0;let e=document.createElement("span");e.className="forge-select__arrow",e.setAttribute("aria-hidden","true"),this.control.append(this.valueEl,this.clearBtn,e),this.dropdown=document.createElement("div"),this.dropdown.className="forge-select__dropdown",this.dropdown.hidden=!0,this.opts.searchable&&(this.searchInput=document.createElement("input"),this.searchInput.type="search",this.searchInput.className="forge-select__search",this.searchInput.setAttribute("aria-label",this.strings.search),this.searchInput.setAttribute("aria-autocomplete","list"),this.searchInput.setAttribute("aria-controls",`${this.uid}-list`),this.searchInput.hidden=!this.shouldShowSearch(),this.dropdown.append(this.searchInput)),this.list=document.createElement("ul"),this.list.className="forge-select__list",this.list.id=`${this.uid}-list`,this.list.setAttribute("role","listbox"),this.opts.multiple&&this.list.setAttribute("aria-multiselectable","true"),this.dropdown.append(this.list),this.liveRegion=document.createElement("div"),this.liveRegion.className="forge-select__sr-only",this.liveRegion.setAttribute("role","status"),this.liveRegion.setAttribute("aria-live","polite"),this.root.append(this.control,this.liveRegion),t||this.root.append(this.dropdown),this.el.style.display="none",this.el.insertAdjacentElement("afterend",this.root),t&&(this.portalHost=document.createElement("div"),this.portalHost.className="forge-select forge-select--portal-host",this.portalHost.dataset.theme=this.opts.theme,this.portalHost.style.setProperty("--fs-item-height",`${this.opts.itemHeight}px`),this.portalHost.append(this.dropdown),t.append(this.portalHost)),this.bindEvents()}bindEvents(){this.control.addEventListener("click",t=>{if(t.target!==this.clearBtn){if(this.suppressNextTagClick){this.suppressNextTagClick=!1;return}this.isDisabled||(this.isOpen?this.close():this.open())}}),this.control.addEventListener("keydown",t=>this.handleKeydown(t)),this.control.addEventListener("mousedown",()=>{this.pointerDownOnControl=!0}),this.control.addEventListener("focus",()=>{this.opts.openOnFocus&&!this.pointerDownOnControl&&!this.isOpen&&!this.isDisabled&&this.open(),this.pointerDownOnControl=!1}),this.clearBtn.addEventListener("click",t=>{t.stopPropagation(),this.clearSelection()}),this.searchInput&&(this.searchInput.addEventListener("input",()=>{this.query=this.searchInput.value,this.highlightedIndex=-1,this.list.scrollTop=0,this.emitter.emit("search",this.query);let t=this.query.trim(),e=t!==""&&t.length<this.opts.minSearchLength;this.opts.ajax&&!e?this.scheduleRemoteLoad(this.query,this.opts.ajax.debounce??250):(e&&(this.ajaxTimer&&(clearTimeout(this.ajaxTimer),this.ajaxTimer=null),this.ajaxController?.abort(),this.loading=!1),this.renderList())}),this.searchInput.addEventListener("keydown",t=>this.handleKeydown(t)),this.searchInput.addEventListener("paste",t=>{if(!this.opts.multiple||!this.opts.allowCreate)return;let s=(t.clipboardData?.getData("text")??"").split(/[,\n]+/).map(r=>r.trim()).filter(Boolean);if(s.length<2)return;t.preventDefault();let i=[];for(let r of s){let n=this.createTag(r);n&&i.push(n)}if(i.length!==0){this.searchInput.value="",this.query="",this.afterSelectionChange();for(let r of i)r.created&&this.emitter.emit("create",r.option),this.emitter.emit("select",r.option);this.opts.closeOnSelect?this.close():this.renderList()}})),this.list.addEventListener("click",t=>{let e=t.target,s=e.closest("[data-twisty]");if(s){let n=s.dataset.twisty;this.expandedValues.has(n)?this.expandedValues.delete(n):this.expandedValues.add(n),this.renderList();return}let i=e.closest("li[data-nav-index]");if(!i){let n=e.closest("li[data-option-value]"),a=n?this.findOption(n.dataset.optionValue):void 0;a&&this.hasReachedMaximum()&&!this.selected.includes(a.value)&&this.announceMaximum(a);return}let r=Number(i.dataset.navIndex);this.activateNavItem(r)}),this.list.addEventListener("scroll",()=>{this.usesVirtualScroll()&&this.renderRows(),this.maybeLoadNextPage()})}handleKeydown(t){if(!this.isDisabled)switch(t.key){case"Enter":t.preventDefault(),this.isOpen?this.highlightedIndex>=0&&this.activateNavItem(this.highlightedIndex):this.open();break;case" ":t.target===this.control&&(t.preventDefault(),this.isOpen||this.open());break;case"ArrowDown":t.preventDefault(),this.isOpen?this.moveHighlight(1):this.open();break;case"ArrowUp":t.preventDefault(),this.isOpen&&this.moveHighlight(-1);break;case"Escape":this.isOpen&&(t.preventDefault(),this.close(),this.control.focus());break;case"ArrowRight":this.isOpen&&this.navigateTree("right")&&t.preventDefault();break;case"ArrowLeft":this.isOpen&&this.navigateTree("left")&&t.preventDefault();break;case"Tab":this.close();break}}canSelectOption(t){if(this.opts.maxSelections==null)return!0;let e=[...this.selected];e.includes(t.value)||e.push(t.value);for(let s of v(t,this.isOptionDisabled))e.includes(s)||e.push(s);return L(this.data,e,this.isOptionDisabled),e.length<=this.opts.maxSelections}hasReachedMaximum(){return this.opts.maxSelections!=null&&this.selected.length>=this.opts.maxSelections}announceMaximum(t){let e=this.opts.maxSelections;e!=null&&(this.liveRegion.textContent=u(this.strings.maximumSelected,{count:String(e)}),this.emitter.emit("maximum",{limit:e,option:t}))}selectValue(t,e){if(this.selected.includes(t))return;let s=this.findOption(t)??this.selectedOptions.get(t)??{value:t,label:t};if(this.selectedOptions.set(t,s),this.opts.multiple){this.selected.push(t);for(let i of v(s,this.isOptionDisabled))this.selected.includes(i)||this.selected.push(i);this.syncTreeAncestors()}else this.selected=[t];e&&(this.afterSelectionChange(),this.emitter.emit("select",s))}deselectValue(t,e){let s=this.selected.indexOf(t);if(s===-1)return;let i=this.findOption(t)??this.selectedOptions.get(t);if(this.selected.splice(s,1),this.opts.multiple){if(i)for(let r of v(i,this.isOptionDisabled)){let n=this.selected.indexOf(r);n!==-1&&this.selected.splice(n,1)}this.syncTreeAncestors()}e&&(this.afterSelectionChange(),this.emitter.emit("unselect",i??{value:t,label:t}))}syncTreeAncestors(){L(this.data,this.selected,this.isOptionDisabled)}clearSelection(){this.selected.length!==0&&(this.selected=[],this.emitter.emit("clear"),this.afterSelectionChange())}allSelectableValues(){let t=[],e=s=>{this.isOptionDisabled(s)||t.push(s.value),s.children?.forEach(e)};for(let s of this.data)(p(s)?s.options:[s]).forEach(e);return t}afterSelectionChange(t=!0){this.renderValue(),this.syncNativeSelect(t),(!this.opts.required||this.selected.length>0)&&(this.control.classList.remove("forge-select__control--invalid"),this.control.removeAttribute("aria-invalid")),this.isOpen&&this.renderList(),t&&this.emitter.emit("change",this.getValue())}syncNativeSelect(t=!0){if(!(this.el instanceof HTMLSelectElement))return;let e=new Set;for(let s of Array.from(this.el.options))e.add(s.value),s.selected=this.selected.includes(s.value);for(let s of this.selected){if(e.has(s))continue;let i=document.createElement("option");i.value=s,i.textContent=this.selectedOptions.get(s)?.label??s,i.selected=!0,this.el.append(i)}if(this.opts.sortable&&this.opts.multiple)for(let s of this.selected){let i=Array.from(this.el.options).find(r=>r.value===s);i&&this.el.append(i)}if(t){this.syncingNative=!0;try{this.el.dispatchEvent(new Event("change",{bubbles:!0}))}finally{this.syncingNative=!1}}}findOption(t){return N(this.data,t)}findOptionByLabel(t){let e=t.toLowerCase(),s=i=>{for(let r of i){if(r.label.toLowerCase()===e)return r;let n=r.children?s(r.children):void 0;if(n)return n}};for(let i of this.data){let r=s(p(i)?i.options:[i]);if(r)return r}}createTag(t){let e=t.trim();if(!e)return;let s=this.findOptionByLabel(e);if(s){if(this.selected.includes(s.value))return;if(this.opts.multiple&&!this.canSelectOption(s)){this.announceMaximum(s);return}return this.selectValue(s.value,!1),{option:s,created:!1}}let i={value:e,label:e};if(this.opts.multiple&&!this.canSelectOption(i)){this.announceMaximum(i);return}return this.data.push(i),this.selectValue(i.value,!1),{option:i,created:!0}}createFromQuery(){let t=this.query.trim();if(!t)return;let e=this.createTag(t);e&&(this.searchInput&&(this.searchInput.value="",this.query=""),this.afterSelectionChange(),e.created&&this.emitter.emit("create",e.option),this.emitter.emit("select",e.option),(!this.opts.multiple||this.opts.closeOnSelect)&&this.close())}activateNavItem(t){let e=this.navItems[t];if(!e)return;if(e.kind==="create"){this.createFromQuery();return}let{value:s}=e.option;if(this.opts.multiple){let i=!1;this.selected.includes(s)?(this.deselectValue(s,!0),i=!0):this.canSelectOption(e.option)?(this.selectValue(s,!0),i=!0):this.announceMaximum(e.option),i&&this.opts.closeOnSelect&&this.close()}else this.selectValue(s,!0),this.close(),this.control.focus()}renderValue(){this.valueEl.textContent="";let t=this.selected.length>0;if(this.clearBtn.hidden=!(this.opts.clearable&&t),!t){let e=document.createElement("span");e.className="forge-select__placeholder",e.textContent=this.opts.placeholder,this.valueEl.append(e);return}if(this.opts.multiple)for(let e of this.selected){let s=this.selectedOptions.get(e)??{value:e,label:e},i=document.createElement("span");i.className="forge-select__tag";let r=document.createElement("span");r.className="forge-select__tag-label",x(r,s,this.opts.templateSelection,"inline");let n=document.createElement("button");n.type="button",n.className="forge-select__tag-remove",n.setAttribute("aria-label",u(this.strings.removeItem,{label:s.label})),n.textContent="\xD7",n.addEventListener("click",a=>{a.stopPropagation(),this.isDisabled||this.deselectValue(e,!0)}),i.append(r,n),this.opts.sortable&&(i.dataset.value=e,i.tabIndex=0,i.setAttribute("aria-roledescription","draggable item"),i.setAttribute("aria-label",u(this.strings.reorderHint,{label:s.label})),i.addEventListener("keydown",a=>this.handleTagKeydown(a,e)),this.bindTagDrag(i,e)),this.valueEl.append(i)}else{let e=this.selectedOptions.get(this.selected[0])??{value:this.selected[0],label:this.selected[0]},s=document.createElement("span");s.className="forge-select__single-value",x(s,e,this.opts.templateSelection,"inline"),this.valueEl.append(s)}}bindTagDrag(t,e){let i=0,r=!1,n=[],a=h=>{if(!r){if(Math.abs(h.clientX-i)<4)return;r=!0,n=[...this.selected],typeof this.valueEl.setPointerCapture=="function"&&this.valueEl.setPointerCapture(h.pointerId),t.classList.add("forge-select__tag--dragging")}h.preventDefault();let m=n.indexOf(e),d=Array.from(this.valueEl.querySelectorAll(".forge-select__tag"));for(let c of d){if(c===t)continue;let g=c.dataset.value;if(!g)continue;let S=n.indexOf(g);if(S===-1)continue;let C=c.getBoundingClientRect(),A=C.left+C.width/2,T=m<S;if(T?h.clientX>A:h.clientX<A){n.splice(m,1),n.splice(S,0,e),T?this.valueEl.insertBefore(t,c.nextSibling):this.valueEl.insertBefore(t,c);break}}},l=h=>{this.valueEl.removeEventListener("pointermove",a),this.valueEl.removeEventListener("pointerup",l),this.valueEl.removeEventListener("pointercancel",l),r&&(typeof this.valueEl.releasePointerCapture=="function"&&this.valueEl.releasePointerCapture(h.pointerId),t.classList.remove("forge-select__tag--dragging"),this.selected=n,this.suppressNextTagClick=!0,this.afterSelectionChange(),this.emitter.emit("reorder",[...this.selected]))};t.addEventListener("pointerdown",h=>{this.isDisabled||h.button!==0||h.target.closest(".forge-select__tag-remove")||(i=h.clientX,r=!1,this.valueEl.addEventListener("pointermove",a),this.valueEl.addEventListener("pointerup",l),this.valueEl.addEventListener("pointercancel",l))})}handleTagKeydown(t,e){if(!t.altKey||t.key!=="ArrowLeft"&&t.key!=="ArrowRight")return;let s=this.selected.indexOf(e),i=t.key==="ArrowLeft"?s-1:s+1;if(s===-1||i<0||i>=this.selected.length)return;t.preventDefault(),t.stopPropagation();let r=[...this.selected];[r[s],r[i]]=[r[i],r[s]],this.selected=r,this.afterSelectionChange(),this.emitter.emit("reorder",[...this.selected]),this.focusTagByValue(e)}focusTagByValue(t){for(let e of Array.from(this.valueEl.querySelectorAll(".forge-select__tag")))if(e.dataset.value===t){e.focus();return}}buildRows(){this.rows=[],this.navItems=[];let t=this.query.trim(),e=t.toLowerCase(),s=n=>e===""||(this.opts.filterOption?this.opts.filterOption(n,t):n.label.toLowerCase().includes(e)||(n.description?.toLowerCase().includes(e)??!1)),i=n=>e===""||s(n)||(n.children??[]).some(i),r=(n,a,l)=>{let h=-1;this.isOptionDisabled(n)||this.hasReachedMaximum()&&!this.selected.includes(n.value)||(h=this.navItems.length,this.navItems.push({kind:"option",option:n,parentValue:l}));let d=!!n.children&&n.children.length>0;if(this.rows.push({kind:"option",option:n,navIndex:h,depth:a,hasChildren:d}),d&&(e!==""||this.expandedValues.has(n.value)))for(let g of n.children)i(g)&&r(g,a+1,n.value)};if(t!==""&&t.length<this.opts.minSearchLength){this.rows.push({kind:"min-length"});return}if(this.loading){this.rows.push({kind:"loading"});return}if(this.loadError){this.rows.push({kind:"error"});return}for(let n of this.data)if(p(n)){let a=n.options.filter(i);if(a.length===0)continue;this.rows.push({kind:"group",label:n.label}),a.forEach(l=>r(l,0))}else i(n)&&r(n,0);if(this.opts.allowCreate&&e!==""&&!this.hasExactMatch(e)){let n=this.navItems.length;this.navItems.push({kind:"create"}),this.rows.push({kind:"create",navIndex:n})}this.rows.length===0?this.rows.push({kind:"empty"}):this.loadingMore&&this.rows.push({kind:"loading-more"})}hasExactMatch(t){return!!this.findOptionByLabel(t)}usesVirtualScroll(){return this.opts.virtualScroll!==!1&&this.rows.length>z}renderList(){this.buildRows(),this.renderRows(),this.announceStatus()}announceStatus(){let t=this.rows[0],e=this.hasReachedMaximum()?u(this.strings.maximumSelected,{count:String(this.opts.maxSelections)}):t?.kind==="loading"?this.strings.loading:t?.kind==="error"?this.strings.errorLoading:t?.kind==="empty"?this.strings.noResults:t?.kind==="min-length"?u(this.strings.minSearchLength,{count:String(this.opts.minSearchLength)}):"";this.liveRegion.textContent!==e&&(this.liveRegion.textContent=e)}renderRows(){let t=this.list.scrollTop,e=this.list.clientHeight,s=this.usesVirtualScroll();this.list.textContent="";let i=this.opts.itemHeight,r=0,n=this.rows.length;if(s){let a=e||i*8;r=Math.max(0,Math.floor(t/i)-q),n=Math.min(this.rows.length,r+Math.ceil(a/i)+q*2);let l=document.createElement("li");l.className="forge-select__spacer",l.setAttribute("aria-hidden","true"),l.style.height=`${r*i}px`,this.list.append(l)}for(let a=r;a<n;a++)this.list.append(this.renderRow(this.rows[a]));if(s){let a=document.createElement("li");a.className="forge-select__spacer",a.setAttribute("aria-hidden","true"),a.style.height=`${(this.rows.length-n)*i}px`,this.list.append(a),this.list.scrollTop!==t&&(this.list.scrollTop=t)}this.updateActiveDescendant()}renderRow(t){let e=document.createElement("li");switch(t.kind){case"group":e.className="forge-select__group-label",e.setAttribute("role","presentation"),e.textContent=t.label;break;case"empty":e.className="forge-select__empty",e.setAttribute("role","option"),e.setAttribute("aria-disabled","true"),e.setAttribute("aria-selected","false"),e.textContent=this.strings.noResults;break;case"min-length":e.className="forge-select__min-length",e.setAttribute("role","option"),e.setAttribute("aria-disabled","true"),e.setAttribute("aria-selected","false"),e.textContent=u(this.strings.minSearchLength,{count:String(this.opts.minSearchLength)});break;case"error":e.className="forge-select__error",e.setAttribute("role","option"),e.setAttribute("aria-disabled","true"),e.setAttribute("aria-selected","false"),e.textContent=this.strings.errorLoading;break;case"loading":e.className="forge-select__loading",e.setAttribute("role","option"),e.setAttribute("aria-disabled","true"),e.setAttribute("aria-selected","false"),e.textContent=this.strings.loading;break;case"loading-more":e.className="forge-select__loading-more",e.setAttribute("aria-hidden","true"),e.textContent=this.strings.loadingMore;break;case"create":e.className="forge-select__option forge-select__option--create",e.setAttribute("role","option"),e.id=`${this.uid}-nav-${t.navIndex}`,e.dataset.navIndex=String(t.navIndex),e.textContent=u(this.strings.createOption,{query:this.query.trim()}),t.navIndex===this.highlightedIndex&&e.classList.add("forge-select__option--highlighted");break;case"option":{e.className="forge-select__option",e.dataset.optionValue=t.option.value,t.option.className&&e.classList.add(...t.option.className.trim().split(/\s+/).filter(Boolean)),e.setAttribute("role","option");let s=this.selected.includes(t.option.value);if(e.setAttribute("aria-selected",String(s)),s&&e.classList.add("forge-select__option--selected"),this.opts.multiple&&t.hasChildren&&y(t.option,this.selected,this.isOptionDisabled)==="some"&&e.classList.add("forge-select__option--indeterminate"),t.depth>0&&(e.style.paddingLeft=`calc(12px + ${t.depth} * var(--fs-tree-indent, 18px))`),this.isOptionDisabled(t.option)||this.hasReachedMaximum()&&!this.selected.includes(t.option.value)?(e.classList.add("forge-select__option--disabled"),e.setAttribute("aria-disabled","true")):(e.id=`${this.uid}-nav-${t.navIndex}`,e.dataset.navIndex=String(t.navIndex),t.navIndex===this.highlightedIndex&&e.classList.add("forge-select__option--highlighted")),t.hasChildren){let i=this.query!==""||this.expandedValues.has(t.option.value);e.setAttribute("aria-expanded",String(i));let r=document.createElement("span");r.className="forge-select__twisty",r.dataset.twisty=t.option.value,r.setAttribute("aria-hidden","true"),r.textContent=i?"\u25BC":"\u25B6",e.append(r)}e.append(this.optionContent(t.option));break}}return e}optionContent(t){let e=this.rowContentCache.get(t.value);if(!e){let s=document.createElement("span");if(s.className="forge-select__option-content",x(s,t,this.opts.templateResult),this.rowContentCache.size>=K){let i=this.rowContentCache.keys().next().value;this.rowContentCache.delete(i)}this.rowContentCache.set(t.value,s),e=s}return e.cloneNode(!0)}moveHighlight(t){if(this.navItems.length===0)return;let e=this.highlightedIndex===-1?t>0?0:this.navItems.length-1:(this.highlightedIndex+t+this.navItems.length)%this.navItems.length;this.focusNavIndex(e)}focusNavIndex(t){if(this.highlightedIndex=t,this.usesVirtualScroll()){let e=this.rows.findIndex(s=>(s.kind==="option"||s.kind==="create")&&s.navIndex===t);if(e>=0){let s=this.opts.itemHeight,i=e*s,r=this.list.clientHeight||s*8,n=this.list.scrollTop;i<n?n=i:i+s>n+r&&(n=i+s-r),n!==this.list.scrollTop&&(this.list.scrollTop=n)}this.renderRows()}else this.renderRows(),this.list.querySelector(".forge-select__option--highlighted")?.scrollIntoView?.({block:"nearest"})}navigateTree(t){let e=this.navItems[this.highlightedIndex];if(!e||e.kind!=="option")return!1;let{option:s,parentValue:i}=e,r=!!s.children?.length,n=this.query!==""||this.expandedValues.has(s.value);if(t==="right"){if(r&&!n)return this.expandedValues.add(s.value),this.renderList(),!0;if(r){let a=this.navItems.findIndex(l=>l.kind==="option"&&l.parentValue===s.value);if(a>=0)return this.focusNavIndex(a),!0}return!1}if(r&&n&&this.query==="")return this.expandedValues.delete(s.value),this.renderList(),!0;if(i){let a=this.navItems.findIndex(l=>l.kind==="option"&&l.option.value===i);if(a>=0)return this.focusNavIndex(a),!0}return!1}updateActiveDescendant(){let t=this.searchInput??this.control;this.highlightedIndex>=0?t.setAttribute("aria-activedescendant",`${this.uid}-nav-${this.highlightedIndex}`):t.removeAttribute("aria-activedescendant")}scheduleRemoteLoad(t,e){this.ajaxTimer&&clearTimeout(this.ajaxTimer);let s=++this.ajaxRequestId;this.ajaxController?.abort(),this.ajaxController=null,this.page=0,this.hasMore=!0,this.loading=!0,this.loadingMore=!1,this.loadError=null,this.renderList(),this.ajaxTimer=setTimeout(()=>{this.ajaxTimer=null,this.loadRemote(t,{requestId:s})},e)}maybeLoadNextPage(){if(!this.opts.ajax?.pagination||!this.hasMore||this.loading||this.loadingMore)return;let{scrollHeight:e,scrollTop:s,clientHeight:i}=this.list,r=this.opts.itemHeight*2;e-s-i>=r||(this.loadingMore=!0,this.renderList(),this.loadRemote(this.query,{append:!0}))}async loadRemote(t,{append:e=!1,requestId:s}={}){let i=this.opts.ajax,r=s??++this.ajaxRequestId;if(r!==this.ajaxRequestId)return;this.ajaxController?.abort();let n=new AbortController;this.ajaxController=n;let a=e?this.page+1:0;try{let l;if(i.request)l=await i.request(t,a,n.signal);else{let d=R(i,t,a),c=await fetch(d,{signal:n.signal});if(c.ok===!1)throw new Error(`ForgeSelect: remote request failed with HTTP ${c.status}`);l=await c.json()}if(r!==this.ajaxRequestId||this.destroyed)return;let{options:h,hasMore:m}=k(i,l);if(e){let d=I(this.data);this.data=[...this.data,...h.filter(c=>!d.has(c.value))]}else this.data=h,this.rowContentCache.clear();this.page=a,this.hasMore=m,this.remoteLoaded=!0,this.loadError=null}catch(l){if(r!==this.ajaxRequestId||this.destroyed||n.signal.aborted)return;let h=l instanceof Error?l:new Error(String(l));e||(this.data=[],this.rowContentCache.clear()),this.hasMore=!1,this.loadError=h,this.emitter.emit("error",h)}finally{r===this.ajaxRequestId&&!this.destroyed&&(this.ajaxController=null,this.loading=!1,this.loadingMore=!1,this.isOpen&&this.renderList())}}};return U(W);})();
1
+ "use strict";var ForgeSelectBundle=(()=>{var L=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var Q=(a,e)=>{for(var t in e)L(a,t,{get:e[t],enumerable:!0})},G=(a,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of K(e))!U.call(a,s)&&s!==t&&L(a,s,{get:()=>e[s],enumerable:!(i=z(e,s))||i.enumerable});return a};var W=a=>G(L({},"__esModule",{value:!0}),a);var ie={};Q(ie,{ForgeSelect:()=>v,default:()=>v});var S=class{constructor(){this.handlers=new Map}on(e,t){let i=this.handlers.get(e);i||(i=new Set,this.handlers.set(e,i)),i.add(t)}off(e,t){this.handlers.get(e)?.delete(t)}emit(e,...t){let i=this.handlers.get(e);if(i)for(let s of[...i])s(...t)}clear(){this.handlers.clear()}};function N(a,e,t,i=4){let s=t-a.bottom,n=a.top,r=e>s&&n>s;return{dropUp:r,top:r?a.top-e-i:a.bottom+i}}var C={en:{noResults:"No results found",loading:"Loading\u2026",loadingMore:"Loading more\u2026",errorLoading:"Could not load options",createOption:'Create "{query}"',clearSelection:"Clear selection",removeItem:"Remove {label}",search:"Search",reorderHint:"{label}. Press Alt+Left or Alt+Right to reorder.",minSearchLength:"Type {count} or more characters to search",maximumSelected:"Maximum of {count} selections reached"},vi:{noResults:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3",loading:"\u0110ang t\u1EA3i\u2026",loadingMore:"\u0110ang t\u1EA3i th\xEAm\u2026",errorLoading:"Kh\xF4ng th\u1EC3 t\u1EA3i t\xF9y ch\u1ECDn",createOption:'T\u1EA1o "{query}"',clearSelection:"X\xF3a l\u1EF1a ch\u1ECDn",removeItem:"X\xF3a {label}",search:"T\xECm ki\u1EBFm",reorderHint:"{label}. Nh\u1EA5n Alt+Tr\xE1i ho\u1EB7c Alt+Ph\u1EA3i \u0111\u1EC3 s\u1EAFp x\u1EBFp l\u1EA1i.",minSearchLength:"Nh\u1EADp th\xEAm {count} k\xFD t\u1EF1 \u0111\u1EC3 t\xECm ki\u1EBFm",maximumSelected:"\u0110\xE3 \u0111\u1EA1t t\u1ED1i \u0111a {count} l\u1EF1a ch\u1ECDn"}};function T(a){return typeof a=="string"?C[a]??C.en:{...C.en,...a}}function p(a,e){return a.replace(/\{(\w+)\}/g,(t,i)=>e[i]??t)}function V(a){let e=[];for(let t of Array.from(a.children))t instanceof HTMLOptGroupElement?e.push({label:t.label,options:Array.from(t.querySelectorAll("option")).map(F)}):t instanceof HTMLOptionElement&&e.push(F(t));return e}function F(a){let e=a.parentElement instanceof HTMLOptGroupElement&&a.parentElement.disabled;return{value:a.value,label:a.textContent?.trim()??a.value,disabled:a.disabled||e||void 0}}function b(a,e,t,i="row"){if(t){let s=t(e);typeof s=="string"?a.innerHTML=s:a.append(s);return}if(!e.avatar&&!e.description){a.textContent=e.label;return}if(e.avatar){let s=document.createElement("img");s.className=i==="row"?"forge-select__option-avatar":"forge-select__inline-avatar",s.src=e.avatar,s.alt="",s.setAttribute("loading","lazy"),s.setAttribute("decoding","async"),a.append(s)}if(i==="row"&&e.description){let s=document.createElement("span");s.className="forge-select__option-body";let n=document.createElement("span");n.className="forge-select__option-label",n.textContent=e.label;let r=document.createElement("span");r.className="forge-select__option-desc",r.textContent=e.description,s.append(n,r),a.append(s)}else{let s=document.createElement("span");s.className="forge-select__option-label",s.textContent=e.label,a.append(s)}}function j(a,e,t){if(!a.url)throw new Error("ForgeSelect: ajax requires either url or request.");if(typeof a.url=="function")return a.url(e,t);if(!a.params)return a.url;let i=new URLSearchParams;for(let[n,r]of Object.entries(a.params(e,t)))i.set(n,String(r));let s=a.url.includes("?")?"&":"?";return`${a.url}${s}${i.toString()}`}function A(a,e){let t=a.transform?a.transform(e):e;if(Array.isArray(t))return{options:t,hasMore:!1};if(!t||!Array.isArray(t.options))throw new Error("ForgeSelect: ajax.transform must return an array of options, or an object shaped like { options: Option[], hasMore?: boolean }.");return{options:t.options,hasMore:a.pagination?!!t.hasMore:!1}}var y=class{constructor(){this.entries=new Map}get(e,t=Date.now()){let i=this.entries.get(e);if(i){if(i.expiresAt<=t){this.entries.delete(e);return}return i.value}}set(e,t,i,s=Date.now()){if(!(i<=0)){if(this.entries.size>=50&&!this.entries.has(e)){let n=this.entries.keys().next().value;this.entries.delete(n)}this.entries.set(e,{value:t,expiresAt:s+i})}}clear(){this.entries.clear()}};function f(a,e=!0){let t=a.toLocaleLowerCase();return e?t.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/đ/g,"d"):t}function X(a,e){if(e==="label")return a.label;if(e==="description")return a.description??"";let t=e.slice(5).split("."),i=a.meta;for(let s of t){if(!i||typeof i!="object")return"";i=i[s]}return i==null?"":String(i)}var I=class{constructor(){this.cache=new WeakMap}clear(){this.cache=new WeakMap}score(e,t,i){let s=f(t.trim(),i.accentInsensitive);if(!s)return 1;if(i.scorer)return i.scorer(e,t.trim(),s);let n=`${i.accentInsensitive?"1":"0"}:${i.fields.join("\0")}`,r=this.cache.get(e);r||(r=new Map,this.cache.set(e,r));let o=r.get(n);if(o||(o=i.fields.map(c=>f(X(e,c),i.accentInsensitive)),r.set(n,o)),!(i.tokenSearch?s.split(/\s+/).filter(Boolean):[s]).every(c=>o.some(d=>d.includes(c))))return 0;let l=o[i.fields.indexOf("label")];return l===s?4:l?.startsWith(s)?3:l?.includes(s)?2:1}};function q(a,e,t=!0){let i=f(e.trim(),t).split(/\s+/).filter(Boolean);if(!i.length)return[];let s=f(a,t),n=[];for(let r of i){let o=s.indexOf(r);o>=0&&n.push([o,o+r.length])}return n.sort((r,o)=>r[0]-o[0])}function g(a){return a.options!==void 0}var R=a=>!!a.disabled;function x(a,e=R){if(!a.children)return[];let t=[];for(let i of a.children)e(i)||t.push(i.value),t.push(...x(i,e));return t}function w(a,e,t=R){if(!a.children?.length)return e.includes(a.value)?"all":"none";let i=a.children.filter(s=>!t(s)).map(s=>w(s,e,t));return i.length===0?"none":i.every(s=>s==="all")?"all":i.every(s=>s==="none")?"none":"some"}function P(a,e){let t=i=>{for(let s of i){if(s.value===e)return s;let n=s.children?t(s.children):void 0;if(n)return n}};for(let i of a){let s=t(g(i)?i.options:[i]);if(s)return s}}function H(a,e,t=R){let i=s=>{if(!s.children?.length)return;for(let o of s.children)i(o);let n=w(s,e,t),r=e.indexOf(s.value);n==="all"&&r===-1?e.push(s.value):n!=="all"&&r!==-1&&e.splice(r,1)};for(let s of a)(g(s)?s.options:[s]).forEach(i)}function M(a){let e=new Set,t=i=>{e.add(i.value),i.children?.forEach(t)};for(let i of a)(g(i)?i.options:[i]).forEach(t);return e}function B(a,e){return a.length===e.length&&a.every((t,i)=>t===e[i])}var Y=36,O=5,Z=100,J=2e3,$=10,ee=500,te=0,v=class{constructor(e,t={}){this.selected=[];this.selectedOptions=new Map;this.suppressNextTagClick=!1;this.emitter=new S;this.uid=`forge-select-${++te}`;this.searchInput=null;this.portalHost=null;this.isOpen=!1;this.isDisabled=!1;this.destroyed=!1;this.query="";this.rows=[];this.navItems=[];this.highlightedIndex=-1;this.typeaheadBuffer="";this.typeaheadTimer=null;this.rowContentCache=new Map;this.rowHeightCache=new Map;this.rowOffsetsCache=null;this.scrollRafId=null;this.ancestorScrollRafId=null;this.searchIndex=new I;this.expandedValues=new Set;this.loading=!1;this.loadingMore=!1;this.page=0;this.hasMore=!0;this.ajaxTimer=null;this.ajaxRequestId=0;this.ajaxController=null;this.remoteLoaded=!1;this.remoteCache=new y;this.loadError=null;this.originalDisplay="";this.originalDisabled=!1;this.nativeSelect=null;this.nativeForm=null;this.syncingNative=!1;this.isOptionDisabled=e=>e.disabled===!0||(this.opts.isOptionDisabled?.(e)??!1);this.pointerDownOnControl=!1;this.onDocumentMouseDown=e=>{let t=e.target;!this.root.contains(t)&&!this.portalHost?.contains(t)&&this.close()};this.onWindowResize=()=>{this.positionDropdown()};this.onAncestorScroll=()=>{this.portalHost&&this.ancestorScrollRafId==null&&(this.ancestorScrollRafId=requestAnimationFrame(()=>{this.ancestorScrollRafId=null,this.positionDropdown()}))};this.onNativeInvalid=e=>{e.preventDefault(),this.control.classList.add("forge-select__control--invalid"),this.control.setAttribute("aria-invalid","true"),this.isOpen||this.open(),this.control.focus(),this.emitter.emit("invalid",this.nativeSelect?.validationMessage??"")};this.onNativeChange=()=>{if(!this.nativeSelect||this.destroyed||this.syncingNative)return;let e=Array.from(this.nativeSelect.selectedOptions,t=>t.value);this.applyNativeValues(e)};this.onFormReset=()=>{if(!this.nativeSelect||this.destroyed)return;let e=Array.from(this.nativeSelect.options).filter(t=>t.defaultSelected).map(t=>t.value);this.applyNativeValues(e)};let i=typeof e=="string"?document.querySelector(e):e;if(!i)throw new Error(`ForgeSelect: target element not found: ${String(e)}`);this.el=i;let s=i instanceof HTMLSelectElement?i:null;if(this.nativeSelect=s,this.nativeForm=s?.form??null,this.originalDisplay=i.style.display,this.originalDisabled=s?.disabled??!1,this.opts={placeholder:t.placeholder??"",searchable:t.searchable??!0,multiple:t.multiple??s?.multiple??!1,clearable:t.clearable??!1,allowCreate:t.allowCreate??!1,sortable:t.sortable??!1,closeOnSelect:t.closeOnSelect??!1,maxSelections:t.maxSelections==null||!Number.isFinite(t.maxSelections)?void 0:Math.max(0,Math.floor(t.maxSelections)),theme:t.theme??"default",disabled:t.disabled??s?.disabled??!1,required:t.required??s?.required??!1,data:t.data,ajax:t.ajax,templateResult:t.templateResult,templateSelection:t.templateSelection,filterOption:t.filterOption,searchFields:t.searchFields??["label","description"],tokenSearch:t.tokenSearch??!0,accentInsensitive:t.accentInsensitive??!0,searchScorer:t.searchScorer,highlightSearch:t.highlightSearch??!1,minSearchLength:Math.max(0,Math.floor(t.minSearchLength??0)),minResultsForSearch:Math.max(0,Math.floor(t.minResultsForSearch??0)),isOptionDisabled:t.isOptionDisabled,virtualScroll:t.virtualScroll,itemHeight:typeof t.itemHeight=="number"?Math.max(1,t.itemHeight):Y,variableItemHeight:t.itemHeight==="auto",language:t.language??"en",plugins:t.plugins??[],openOnFocus:t.openOnFocus??!1,dropdownParent:t.dropdownParent},this.strings=T(this.opts.language),this.plugins=this.opts.plugins,s&&(s.required=this.opts.required),this.data=this.opts.data??(s?V(s):[]),s&&!this.opts.data){let n=Array.from(s.options),r=s.multiple||s.selectedIndex>0||n.some(o=>o.defaultSelected);for(let o of n)r&&o.selected&&this.selectValue(o.value,!1)}this.buildDom(),this.renderValue(),this.opts.disabled&&this.disable(),s?.addEventListener("change",this.onNativeChange),s?.addEventListener("invalid",this.onNativeInvalid),this.nativeForm?.addEventListener("reset",this.onFormReset);for(let n of this.plugins)n.onInit?.(this);for(let n of this.opts.ajax?.prefetch??[])this.prefetchRemote(n)}applyNativeValues(e){this.selected=[];for(let t of this.opts.multiple?e:e.slice(0,1))this.selectValue(t,!1);this.renderValue(),this.isOpen&&this.renderList(),this.emitter.emit("change",this.getValue())}open(){if(!(this.isOpen||this.isDisabled||this.destroyed)){this.isOpen=!0,this.dropdown.hidden=!1,this.root.classList.add("forge-select--open"),this.control.setAttribute("aria-expanded","true"),document.addEventListener("mousedown",this.onDocumentMouseDown),this.opts.ajax&&(this.opts.ajax.loadOnOpen??!0)&&!this.remoteLoaded&&this.scheduleRemoteLoad(this.query,0),this.renderList(),this.positionDropdown(),window.addEventListener("resize",this.onWindowResize),document.addEventListener("scroll",this.onAncestorScroll,!0),this.searchInput&&!this.searchInput.hidden&&this.searchInput.focus(),this.emitter.emit("open");for(let e of this.plugins)e.onOpen?.(this)}}close(){if(this.isOpen){this.isOpen=!1,this.dropdown.hidden=!0,this.root.classList.remove("forge-select--open"),this.root.classList.remove("forge-select--drop-up"),this.control.setAttribute("aria-expanded","false"),document.removeEventListener("mousedown",this.onDocumentMouseDown),window.removeEventListener("resize",this.onWindowResize),document.removeEventListener("scroll",this.onAncestorScroll,!0),this.ancestorScrollRafId!=null&&(cancelAnimationFrame(this.ancestorScrollRafId),this.ancestorScrollRafId=null),this.scrollRafId!=null&&(cancelAnimationFrame(this.scrollRafId),this.scrollRafId=null),this.typeaheadTimer&&(clearTimeout(this.typeaheadTimer),this.typeaheadTimer=null),this.typeaheadBuffer="",this.highlightedIndex=-1,this.searchInput&&(this.searchInput.value="",this.query=""),this.emitter.emit("close");for(let e of this.plugins)e.onClose?.(this)}}positionDropdown(){let e=this.control.getBoundingClientRect(),t=N(e,this.dropdown.offsetHeight,window.innerHeight);this.root.classList.toggle("forge-select--drop-up",t.dropUp),this.portalHost&&(this.portalHost.style.top=`${t.top}px`,this.portalHost.style.left=`${e.left}px`,this.portalHost.style.width=`${e.width}px`)}destroy(){if(!this.destroyed){this.close();for(let e of this.plugins)e.onDestroy?.(this);this.destroyed=!0,this.ajaxTimer&&clearTimeout(this.ajaxTimer),this.ajaxController?.abort(),this.scrollRafId!=null&&cancelAnimationFrame(this.scrollRafId),this.typeaheadTimer&&clearTimeout(this.typeaheadTimer),this.nativeSelect?.removeEventListener("change",this.onNativeChange),this.nativeSelect?.removeEventListener("invalid",this.onNativeInvalid),this.nativeForm?.removeEventListener("reset",this.onFormReset),this.rowContentCache.clear(),this.rowHeightCache.clear(),this.searchIndex.clear(),this.portalHost?.remove(),this.root.remove(),this.el.style.display=this.originalDisplay,this.nativeSelect&&(this.nativeSelect.disabled=this.originalDisabled),this.emitter.clear()}}getValue(){return this.opts.multiple?[...this.selected]:this.selected[0]??null}getSearchQuery(){return this.query}setSearchQuery(e,t={}){this.applySearchQuery(e,t.emitSearch??!0)}isDropdownOpen(){return this.isOpen}updateOptions(e){e.data&&this.setData(e.data),"ajax"in e&&e.ajax!==this.opts.ajax&&(this.opts.ajax=e.ajax,this.remoteLoaded=!1,this.clearRemoteCache()),e.placeholder!==void 0&&(this.opts.placeholder=e.placeholder),e.clearable!==void 0&&(this.opts.clearable=e.clearable),e.allowCreate!==void 0&&(this.opts.allowCreate=e.allowCreate),e.sortable!==void 0&&(this.opts.sortable=e.sortable),e.closeOnSelect!==void 0&&(this.opts.closeOnSelect=e.closeOnSelect),"maxSelections"in e&&(this.opts.maxSelections=e.maxSelections==null||!Number.isFinite(e.maxSelections)?void 0:Math.max(0,Math.floor(e.maxSelections))),e.theme!==void 0&&(this.opts.theme=e.theme,this.root.dataset.theme=e.theme,this.portalHost&&(this.portalHost.dataset.theme=e.theme)),e.required!==void 0&&(this.opts.required=e.required,e.required?this.control.setAttribute("aria-required","true"):this.control.removeAttribute("aria-required"),this.nativeSelect&&(this.nativeSelect.required=e.required)),e.templateResult!==void 0&&(this.opts.templateResult=e.templateResult),e.templateSelection!==void 0&&(this.opts.templateSelection=e.templateSelection),e.filterOption!==void 0&&(this.opts.filterOption=e.filterOption),e.searchFields!==void 0&&(this.opts.searchFields=e.searchFields),e.tokenSearch!==void 0&&(this.opts.tokenSearch=e.tokenSearch),e.accentInsensitive!==void 0&&(this.opts.accentInsensitive=e.accentInsensitive),e.searchScorer!==void 0&&(this.opts.searchScorer=e.searchScorer),e.highlightSearch!==void 0&&(this.opts.highlightSearch=e.highlightSearch),e.minSearchLength!==void 0&&(this.opts.minSearchLength=Math.max(0,Math.floor(e.minSearchLength))),e.minResultsForSearch!==void 0&&(this.opts.minResultsForSearch=Math.max(0,Math.floor(e.minResultsForSearch))),e.isOptionDisabled!==void 0&&(this.opts.isOptionDisabled=e.isOptionDisabled),e.virtualScroll!==void 0&&(this.opts.virtualScroll=e.virtualScroll),e.itemHeight!==void 0&&(this.opts.variableItemHeight=e.itemHeight==="auto",typeof e.itemHeight=="number"&&(this.opts.itemHeight=Math.max(1,e.itemHeight)),this.root.style.setProperty("--fs-item-height",`${this.opts.itemHeight}px`),this.portalHost?.style.setProperty("--fs-item-height",`${this.opts.itemHeight}px`)),e.language!==void 0&&(this.opts.language=e.language,this.strings=T(e.language),this.clearBtn.setAttribute("aria-label",this.strings.clearSelection),this.searchInput?.setAttribute("aria-label",this.strings.search)),e.openOnFocus!==void 0&&(this.opts.openOnFocus=e.openOnFocus),e.disabled!==void 0&&(e.disabled?this.disable():this.enable()),this.root.classList.toggle("forge-select--sortable",this.opts.sortable&&this.opts.multiple),this.updateSearchVisibility(),this.rowContentCache.clear(),this.rowHeightCache.clear(),this.searchIndex.clear(),this.renderValue(),this.isOpen&&this.renderList()}validate(){let e=(!this.opts.required||this.selected.length>0)&&(this.control.dataset.validationMessage??"")==="";return this.control.classList.toggle("forge-select__control--invalid",!e),this.control.setAttribute("aria-invalid",String(!e)),e}setCustomValidity(e){this.nativeSelect?.setCustomValidity(e),this.control.dataset.validationMessage=e}reportValidity(){let e=this.validate()&&(this.nativeSelect?.checkValidity()??!0);if(!e){let t=this.nativeSelect?.validationMessage??this.control.dataset.validationMessage??"";if(this.nativeSelect)return this.nativeSelect.reportValidity();this.emitter.emit("invalid",t)}return e}reload(){this.opts.ajax&&(this.clearRemoteCache(),this.remoteLoaded=!1,this.scheduleRemoteLoad(this.query,0))}clearRemoteCache(){this.remoteCache.clear()}setValue(e,t={}){let i=e==null?[]:Array.isArray(e)?e:[e],s=this.opts.multiple?i:i.slice(0,1);if(!B(s,this.selected)){this.selected=[];for(let n of s)this.selectValue(n,!1);this.afterSelectionChange(t.emitChange??!0)}}setData(e){this.ajaxTimer&&(clearTimeout(this.ajaxTimer),this.ajaxTimer=null),this.ajaxController?.abort(),this.ajaxController=null,this.ajaxRequestId+=1,this.setLoading(!1),this.loadingMore=!1,this.loadError=null,this.remoteLoaded=!0,this.page=0,this.hasMore=!1,this.data=e,this.opts.data=e,this.updateSearchVisibility(),this.rowContentCache.clear(),this.rowHeightCache.clear(),this.searchIndex.clear(),this.highlightedIndex=-1,this.isOpen&&this.renderList()}selectAll(){if(this.opts.multiple){this.selected=[];for(let e of this.allSelectableValues()){let t=this.findOption(e);t&&this.canSelectOption(t)&&this.selectValue(e,!1)}this.afterSelectionChange()}}clearAll(){this.clearSelection()}enable(){this.isDisabled=!1,this.root.classList.remove("forge-select--disabled"),this.control.tabIndex=0,this.control.setAttribute("aria-disabled","false"),this.nativeSelect&&(this.nativeSelect.disabled=!1)}disable(){this.close(),this.isDisabled=!0,this.root.classList.add("forge-select--disabled"),this.control.tabIndex=-1,this.control.setAttribute("aria-disabled","true"),this.nativeSelect&&(this.nativeSelect.disabled=!0)}on(e,t){this.emitter.on(e,t)}off(e,t){this.emitter.off(e,t)}applyAccessibleName(){let e=this.el.getAttribute("aria-labelledby"),t=this.el.getAttribute("aria-label");if(e)this.control.setAttribute("aria-labelledby",e);else if(t)this.control.setAttribute("aria-label",t);else if(this.el.id){let i=Array.from(document.getElementsByTagName("label")).find(s=>s.htmlFor===this.el.id);i&&(i.id||(i.id=`${this.uid}-label`),this.control.setAttribute("aria-labelledby",i.id))}}shouldShowSearch(){return this.opts.searchable&&(this.opts.ajax!=null||M(this.data).size>=this.opts.minResultsForSearch)}updateSearchVisibility(){this.searchInput&&(this.searchInput.hidden=!this.shouldShowSearch(),this.searchInput.hidden&&(this.searchInput.value="",this.query=""))}buildDom(){let e=typeof this.opts.dropdownParent=="string"?document.querySelector(this.opts.dropdownParent):this.opts.dropdownParent;if(this.opts.dropdownParent&&!e)throw new Error(`ForgeSelect: dropdown parent not found: ${String(this.opts.dropdownParent)}`);this.root=document.createElement("div"),this.root.className="forge-select",this.root.dataset.theme=this.opts.theme,this.root.style.setProperty("--fs-item-height",`${this.opts.itemHeight}px`),this.opts.sortable&&this.opts.multiple&&this.root.classList.add("forge-select--sortable"),this.control=document.createElement("div"),this.control.className="forge-select__control",this.control.setAttribute("role","combobox"),this.control.setAttribute("aria-haspopup","listbox"),this.control.setAttribute("aria-expanded","false"),this.control.setAttribute("aria-controls",`${this.uid}-list`),this.opts.required&&this.control.setAttribute("aria-required","true"),this.control.tabIndex=0,this.applyAccessibleName(),this.valueEl=document.createElement("div"),this.valueEl.className="forge-select__value",this.clearBtn=document.createElement("button"),this.clearBtn.type="button",this.clearBtn.className="forge-select__clear",this.clearBtn.setAttribute("aria-label",this.strings.clearSelection),this.clearBtn.textContent="\xD7",this.clearBtn.hidden=!0;let t=document.createElement("span");t.className="forge-select__arrow",t.setAttribute("aria-hidden","true"),this.control.append(this.valueEl,this.clearBtn,t),this.dropdown=document.createElement("div"),this.dropdown.className="forge-select__dropdown",this.dropdown.hidden=!0,this.opts.searchable&&(this.searchInput=document.createElement("input"),this.searchInput.type="search",this.searchInput.className="forge-select__search",this.searchInput.setAttribute("aria-label",this.strings.search),this.searchInput.setAttribute("aria-autocomplete","list"),this.searchInput.setAttribute("aria-controls",`${this.uid}-list`),this.searchInput.hidden=!this.shouldShowSearch(),this.dropdown.append(this.searchInput)),this.list=document.createElement("ul"),this.list.className="forge-select__list",this.list.id=`${this.uid}-list`,this.list.setAttribute("role","listbox"),this.opts.multiple&&this.list.setAttribute("aria-multiselectable","true"),this.dropdown.append(this.list),this.liveRegion=document.createElement("div"),this.liveRegion.className="forge-select__sr-only",this.liveRegion.setAttribute("role","status"),this.liveRegion.setAttribute("aria-live","polite"),this.root.append(this.control,this.liveRegion),e||this.root.append(this.dropdown),this.el.style.display="none",this.el.insertAdjacentElement("afterend",this.root),e&&(this.portalHost=document.createElement("div"),this.portalHost.className="forge-select forge-select--portal-host",this.portalHost.dataset.theme=this.opts.theme,this.portalHost.style.setProperty("--fs-item-height",`${this.opts.itemHeight}px`),this.portalHost.append(this.dropdown),e.append(this.portalHost)),this.bindEvents()}bindEvents(){this.control.addEventListener("click",e=>{if(e.target!==this.clearBtn){if(this.suppressNextTagClick){this.suppressNextTagClick=!1;return}this.isDisabled||(this.isOpen?this.close():this.open())}}),this.control.addEventListener("keydown",e=>this.handleKeydown(e)),this.control.addEventListener("mousedown",()=>{this.pointerDownOnControl=!0}),this.control.addEventListener("focus",()=>{this.opts.openOnFocus&&!this.pointerDownOnControl&&!this.isOpen&&!this.isDisabled&&this.open(),this.pointerDownOnControl=!1}),this.clearBtn.addEventListener("click",e=>{e.stopPropagation(),this.clearSelection()}),this.searchInput&&(this.searchInput.addEventListener("input",()=>{this.applySearchQuery(this.searchInput.value,!0)}),this.searchInput.addEventListener("keydown",e=>this.handleKeydown(e)),this.searchInput.addEventListener("paste",e=>{if(!this.opts.multiple||!this.opts.allowCreate)return;let i=(e.clipboardData?.getData("text")??"").split(/[,\n]+/).map(n=>n.trim()).filter(Boolean);if(i.length<2)return;e.preventDefault();let s=[];for(let n of i){let r=this.createTag(n);r&&s.push(r)}if(s.length!==0){this.searchInput.value="",this.query="",this.afterSelectionChange();for(let n of s)n.created&&this.emitter.emit("create",n.option),this.emitter.emit("select",n.option);this.opts.closeOnSelect?this.close():this.renderList()}})),this.list.addEventListener("click",e=>{let t=e.target,i=t.closest("[data-twisty]");if(i){let r=i.dataset.twisty;this.expandedValues.has(r)?this.expandedValues.delete(r):this.expandedValues.add(r),this.renderList();return}let s=t.closest("li[data-nav-index]");if(!s){let r=t.closest("li[data-option-value]"),o=r?this.findOption(r.dataset.optionValue):void 0;o&&this.hasReachedMaximum()&&!this.selected.includes(o.value)&&this.announceMaximum(o);return}let n=Number(s.dataset.navIndex);this.activateNavItem(n)}),this.list.addEventListener("scroll",()=>{this.scrollRafId==null&&(this.scrollRafId=requestAnimationFrame(()=>{this.scrollRafId=null,this.usesVirtualScroll()&&this.renderRows(),this.maybeLoadNextPage()}))})}applySearchQuery(e,t){this.query=e,this.searchInput&&this.searchInput.value!==e&&(this.searchInput.value=e),this.highlightedIndex=-1,this.list.scrollTop=0,t&&this.emitter.emit("search",e);let i=e.trim(),s=i!==""&&i.length<this.opts.minSearchLength;if(this.opts.ajax&&!s){this.scheduleRemoteLoad(e,this.opts.ajax.debounce??250);return}s&&(this.ajaxTimer&&(clearTimeout(this.ajaxTimer),this.ajaxTimer=null),this.ajaxController?.abort(),this.setLoading(!1)),this.renderList()}handleKeydown(e){if(!this.isDisabled)switch(e.key){case"Enter":e.preventDefault(),this.isOpen?this.highlightedIndex>=0&&this.activateNavItem(this.highlightedIndex):this.open();break;case" ":e.target===this.control&&(e.preventDefault(),this.isOpen||this.open());break;case"ArrowDown":e.preventDefault(),this.isOpen?this.moveHighlight(1):this.open();break;case"ArrowUp":e.preventDefault(),this.isOpen&&this.moveHighlight(-1);break;case"Escape":this.isOpen&&(e.preventDefault(),this.close(),this.control.focus());break;case"ArrowRight":this.isOpen&&this.navigateTree("right")&&e.preventDefault();break;case"ArrowLeft":this.isOpen&&this.navigateTree("left")&&e.preventDefault();break;case"Home":this.isOpen&&(e.preventDefault(),this.focusNavIndex(0));break;case"End":this.isOpen&&(e.preventDefault(),this.focusNavIndex(this.navItems.length-1));break;case"PageDown":this.isOpen&&(e.preventDefault(),this.focusNavIndex(Math.min(this.navItems.length-1,(this.highlightedIndex===-1?0:this.highlightedIndex)+$)));break;case"PageUp":this.isOpen&&(e.preventDefault(),this.focusNavIndex(Math.max(0,(this.highlightedIndex===-1?0:this.highlightedIndex)-$)));break;case"Tab":this.close();break;default:this.isOpen&&e.target===this.control&&e.key.length===1&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&this.handleTypeahead(e.key);break}}handleTypeahead(e){this.typeaheadTimer&&clearTimeout(this.typeaheadTimer),this.typeaheadBuffer+=f(e,this.opts.accentInsensitive),this.typeaheadTimer=setTimeout(()=>{this.typeaheadBuffer="",this.typeaheadTimer=null},ee);let t=[...this.typeaheadBuffer].every(s=>s===this.typeaheadBuffer[0])?this.typeaheadBuffer[0]:this.typeaheadBuffer,i=this.navItems.length;for(let s=1;s<=i;s+=1){let n=(this.highlightedIndex+s+i)%i,r=this.navItems[n];if(r.kind==="option"&&f(r.option.label,this.opts.accentInsensitive).startsWith(t)){this.focusNavIndex(n);return}}}canSelectOption(e){if(this.opts.maxSelections==null)return!0;let t=[...this.selected];t.includes(e.value)||t.push(e.value);for(let i of x(e,this.isOptionDisabled))t.includes(i)||t.push(i);return H(this.data,t,this.isOptionDisabled),t.length<=this.opts.maxSelections}hasReachedMaximum(){return this.opts.maxSelections!=null&&this.selected.length>=this.opts.maxSelections}announceMaximum(e){let t=this.opts.maxSelections;t!=null&&(this.liveRegion.textContent=p(this.strings.maximumSelected,{count:String(t)}),this.emitter.emit("maximum",{limit:t,option:e}))}selectValue(e,t){if(this.selected.includes(e))return;let i=this.findOption(e)??this.selectedOptions.get(e)??{value:e,label:e};if(this.selectedOptions.set(e,i),this.opts.multiple){this.selected.push(e);for(let s of x(i,this.isOptionDisabled))this.selected.includes(s)||this.selected.push(s);this.syncTreeAncestors()}else this.selected=[e];t&&(this.afterSelectionChange(),this.emitter.emit("select",i))}deselectValue(e,t){let i=this.selected.indexOf(e);if(i===-1)return;let s=this.findOption(e)??this.selectedOptions.get(e);if(this.selected.splice(i,1),this.opts.multiple){if(s)for(let n of x(s,this.isOptionDisabled)){let r=this.selected.indexOf(n);r!==-1&&this.selected.splice(r,1)}this.syncTreeAncestors()}t&&(this.afterSelectionChange(),this.emitter.emit("unselect",s??{value:e,label:e}))}syncTreeAncestors(){H(this.data,this.selected,this.isOptionDisabled)}clearSelection(){this.selected.length!==0&&(this.selected=[],this.emitter.emit("clear"),this.afterSelectionChange())}allSelectableValues(){let e=[],t=i=>{this.isOptionDisabled(i)||e.push(i.value),i.children?.forEach(t)};for(let i of this.data)(g(i)?i.options:[i]).forEach(t);return e}afterSelectionChange(e=!0){this.renderValue(),this.syncNativeSelect(e),(!this.opts.required||this.selected.length>0)&&(this.control.classList.remove("forge-select__control--invalid"),this.control.removeAttribute("aria-invalid")),this.isOpen&&(this.opts.maxSelections!=null?this.renderList():this.renderRows()),e&&this.emitter.emit("change",this.getValue())}syncNativeSelect(e=!0){if(!(this.el instanceof HTMLSelectElement))return;let t=new Set;for(let i of Array.from(this.el.options))t.add(i.value),i.selected=this.selected.includes(i.value);for(let i of this.selected){if(t.has(i))continue;let s=document.createElement("option");s.value=i,s.textContent=this.selectedOptions.get(i)?.label??i,s.selected=!0,this.el.append(s)}if(this.opts.sortable&&this.opts.multiple)for(let i of this.selected){let s=Array.from(this.el.options).find(n=>n.value===i);s&&this.el.append(s)}if(e){this.syncingNative=!0;try{this.el.dispatchEvent(new Event("change",{bubbles:!0}))}finally{this.syncingNative=!1}}}findOption(e){return P(this.data,e)}findOptionByLabel(e){let t=e.toLowerCase(),i=s=>{for(let n of s){if(n.label.toLowerCase()===t)return n;let r=n.children?i(n.children):void 0;if(r)return r}};for(let s of this.data){let n=i(g(s)?s.options:[s]);if(n)return n}}createTag(e){let t=e.trim();if(!t)return;let i=this.findOptionByLabel(t);if(i){if(this.selected.includes(i.value))return;if(this.opts.multiple&&!this.canSelectOption(i)){this.announceMaximum(i);return}return this.selectValue(i.value,!1),{option:i,created:!1}}let s={value:t,label:t};if(this.opts.multiple&&!this.canSelectOption(s)){this.announceMaximum(s);return}return this.data.push(s),this.selectValue(s.value,!1),{option:s,created:!0}}createFromQuery(){let e=this.query.trim();if(!e)return;let t=this.createTag(e);t&&(this.searchInput&&(this.searchInput.value="",this.query=""),this.afterSelectionChange(),t.created&&this.emitter.emit("create",t.option),this.emitter.emit("select",t.option),!this.opts.multiple||this.opts.closeOnSelect?this.close():this.isOpen&&this.renderList())}activateNavItem(e){let t=this.navItems[e];if(!t)return;if(t.kind==="create"){this.createFromQuery();return}let{value:i}=t.option;if(this.opts.multiple){let s=!1;this.selected.includes(i)?(this.deselectValue(i,!0),s=!0):this.canSelectOption(t.option)?(this.selectValue(i,!0),s=!0):this.announceMaximum(t.option),s&&this.opts.closeOnSelect&&this.close()}else this.selectValue(i,!0),this.close(),this.control.focus()}renderValue(){this.valueEl.textContent="";let e=this.selected.length>0;if(this.clearBtn.hidden=!(this.opts.clearable&&e),!e){let t=document.createElement("span");t.className="forge-select__placeholder",t.textContent=this.opts.placeholder,this.valueEl.append(t);return}if(this.opts.multiple)for(let t of this.selected){let i=this.selectedOptions.get(t)??{value:t,label:t},s=document.createElement("span");s.className="forge-select__tag";let n=document.createElement("span");n.className="forge-select__tag-label",b(n,i,this.opts.templateSelection,"inline");let r=document.createElement("button");r.type="button",r.className="forge-select__tag-remove",r.setAttribute("aria-label",p(this.strings.removeItem,{label:i.label})),r.textContent="\xD7",r.addEventListener("click",o=>{o.stopPropagation(),this.isDisabled||this.deselectValue(t,!0)}),s.append(n,r),this.opts.sortable&&(s.dataset.value=t,s.tabIndex=0,s.setAttribute("aria-roledescription","draggable item"),s.setAttribute("aria-label",p(this.strings.reorderHint,{label:i.label})),s.addEventListener("keydown",o=>this.handleTagKeydown(o,t)),this.bindTagDrag(s,t)),this.valueEl.append(s)}else{let t=this.selectedOptions.get(this.selected[0])??{value:this.selected[0],label:this.selected[0]},i=document.createElement("span");i.className="forge-select__single-value",b(i,t,this.opts.templateSelection,"inline"),this.valueEl.append(i)}}bindTagDrag(e,t){let s=0,n=!1,r=[],o=l=>{if(!n){if(Math.abs(l.clientX-s)<4)return;n=!0,r=[...this.selected],typeof this.valueEl.setPointerCapture=="function"&&this.valueEl.setPointerCapture(l.pointerId),e.classList.add("forge-select__tag--dragging")}l.preventDefault();let c=r.indexOf(t),d=Array.from(this.valueEl.querySelectorAll(".forge-select__tag"));for(let u of d){if(u===e)continue;let m=u.dataset.value;if(!m)continue;let E=r.indexOf(m);if(E===-1)continue;let D=u.getBoundingClientRect(),k=D.left+D.width/2,_=c<E;if(_?l.clientX>k:l.clientX<k){r.splice(c,1),r.splice(E,0,t),_?this.valueEl.insertBefore(e,u.nextSibling):this.valueEl.insertBefore(e,u);break}}},h=l=>{this.valueEl.removeEventListener("pointermove",o),this.valueEl.removeEventListener("pointerup",h),this.valueEl.removeEventListener("pointercancel",h),n&&(typeof this.valueEl.releasePointerCapture=="function"&&this.valueEl.releasePointerCapture(l.pointerId),e.classList.remove("forge-select__tag--dragging"),this.selected=r,this.suppressNextTagClick=!0,this.afterSelectionChange(),this.emitter.emit("reorder",[...this.selected]))};e.addEventListener("pointerdown",l=>{this.isDisabled||l.button!==0||l.target.closest(".forge-select__tag-remove")||(s=l.clientX,n=!1,this.valueEl.addEventListener("pointermove",o),this.valueEl.addEventListener("pointerup",h),this.valueEl.addEventListener("pointercancel",h))})}handleTagKeydown(e,t){if(!e.altKey||e.key!=="ArrowLeft"&&e.key!=="ArrowRight")return;let i=this.selected.indexOf(t),s=e.key==="ArrowLeft"?i-1:i+1;if(i===-1||s<0||s>=this.selected.length)return;e.preventDefault(),e.stopPropagation();let n=[...this.selected];[n[i],n[s]]=[n[s],n[i]],this.selected=n,this.afterSelectionChange(),this.emitter.emit("reorder",[...this.selected]),this.focusTagByValue(t)}focusTagByValue(e){for(let t of Array.from(this.valueEl.querySelectorAll(".forge-select__tag")))if(t.dataset.value===e){t.focus();return}}buildRows(){this.rows=[],this.navItems=[],this.rowOffsetsCache=null;let e=this.query.trim(),t=f(e,this.opts.accentInsensitive),i=r=>t===""||(this.opts.filterOption?this.opts.filterOption(r,e):this.searchIndex.score(r,e,{fields:this.opts.searchFields,tokenSearch:this.opts.tokenSearch,accentInsensitive:this.opts.accentInsensitive,scorer:this.opts.searchScorer})>0),s=r=>t===""||i(r)||(r.children??[]).some(s),n=(r,o,h)=>{let l=-1;this.isOptionDisabled(r)||this.hasReachedMaximum()&&!this.selected.includes(r.value)||(l=this.navItems.length,this.navItems.push({kind:"option",option:r,parentValue:h}));let d=!!r.children&&r.children.length>0;if(this.rows.push({kind:"option",option:r,navIndex:l,depth:o,hasChildren:d}),d&&(t!==""||this.expandedValues.has(r.value)))for(let m of r.children)s(m)&&n(m,o+1,r.value)};if(e!==""&&e.length<this.opts.minSearchLength){this.rows.push({kind:"min-length"});return}if(this.loading){this.rows.push({kind:"loading"});return}if(this.loadError){this.rows.push({kind:"error"});return}for(let r of this.data)if(g(r)){let o=r.options.filter(s);if(o.length===0)continue;this.rows.push({kind:"group",label:r.label}),o.forEach(h=>n(h,0))}else s(r)&&n(r,0);if(this.opts.allowCreate&&t!==""&&!this.hasExactMatch(t)){let r=this.navItems.length;this.navItems.push({kind:"create"}),this.rows.push({kind:"create",navIndex:r})}this.rows.length===0?this.rows.push({kind:"empty"}):this.loadingMore&&this.rows.push({kind:"loading-more"})}hasExactMatch(e){return!!this.findOptionByLabel(e)}usesVirtualScroll(){return this.opts.virtualScroll!==!1&&this.rows.length>Z}rowKey(e,t){return e.kind==="option"?`option:${e.option.value}`:e.kind==="group"?`group:${e.label}:${t}`:`${e.kind}:${t}`}measuredRowHeight(e){return this.opts.variableItemHeight?this.rowHeightCache.get(this.rowKey(this.rows[e],e))??this.opts.itemHeight:this.opts.itemHeight}rowOffset(e){if(!this.opts.variableItemHeight)return e*this.opts.itemHeight;let t=0;for(let i=0;i<e;i+=1)t+=this.measuredRowHeight(i);return t}rowOffsets(){if(this.rowOffsetsCache)return this.rowOffsetsCache;let e=[0];for(let t=0;t<this.rows.length;t+=1)e.push(e[t]+this.measuredRowHeight(t));return this.rowOffsetsCache=e,e}renderList(){this.buildRows(),this.renderRows(),this.announceStatus()}announceStatus(){let e=this.rows[0],t=this.hasReachedMaximum()?p(this.strings.maximumSelected,{count:String(this.opts.maxSelections)}):e?.kind==="loading"?this.strings.loading:e?.kind==="error"?this.strings.errorLoading:e?.kind==="empty"?this.strings.noResults:e?.kind==="min-length"?p(this.strings.minSearchLength,{count:String(this.opts.minSearchLength)}):"";this.liveRegion.textContent!==t&&(this.liveRegion.textContent=t)}renderRows(){let e=this.list.scrollTop,t=this.list.clientHeight,i=this.usesVirtualScroll();this.list.textContent="";let s=this.opts.itemHeight,n=this.opts.variableItemHeight?this.rowOffsets():null,r=0,o=this.rows.length;if(i){let l=t||s*8;if(this.opts.variableItemHeight){for(;r<this.rows.length&&n[r+1]<e;)r+=1;r=Math.max(0,r-O),o=r;let d=e+l+O*s;for(;o<this.rows.length&&n[o]<d;)o+=1}else r=Math.max(0,Math.floor(e/s)-O),o=Math.min(this.rows.length,r+Math.ceil(l/s)+O*2);let c=document.createElement("li");c.className="forge-select__spacer",c.setAttribute("aria-hidden","true"),c.style.height=`${n?.[r]??this.rowOffset(r)}px`,this.list.append(c)}let h=[];for(let l=r;l<o;l++){let c=this.renderRow(this.rows[l]);this.list.append(c),h.push(c)}if(this.opts.variableItemHeight)for(let l=r;l<o;l++){let c=h[l-r],d=c.getBoundingClientRect().height||c.offsetHeight;if(d>0){let u=this.rowKey(this.rows[l],l);this.rowHeightCache.get(u)!==d&&(this.rowOffsetsCache=null),this.rowHeightCache.set(u,d)}}if(i){let l=document.createElement("li");l.className="forge-select__spacer",l.setAttribute("aria-hidden","true"),l.style.height=`${n?n[this.rows.length]-n[o]:this.rowOffset(this.rows.length)-this.rowOffset(o)}px`,this.list.append(l),this.list.scrollTop!==e&&(this.list.scrollTop=e)}this.updateActiveDescendant()}renderRow(e){let t=document.createElement("li");switch(e.kind){case"group":t.className="forge-select__group-label",t.setAttribute("role","presentation"),t.textContent=e.label;break;case"empty":t.className="forge-select__empty",t.setAttribute("role","option"),t.setAttribute("aria-disabled","true"),t.setAttribute("aria-selected","false"),t.textContent=this.strings.noResults;break;case"min-length":t.className="forge-select__min-length",t.setAttribute("role","option"),t.setAttribute("aria-disabled","true"),t.setAttribute("aria-selected","false"),t.textContent=p(this.strings.minSearchLength,{count:String(this.opts.minSearchLength)});break;case"error":t.className="forge-select__error",t.setAttribute("role","option"),t.setAttribute("aria-disabled","true"),t.setAttribute("aria-selected","false"),t.textContent=this.strings.errorLoading;break;case"loading":t.className="forge-select__loading",t.setAttribute("role","option"),t.setAttribute("aria-disabled","true"),t.setAttribute("aria-selected","false"),t.textContent=this.strings.loading;break;case"loading-more":t.className="forge-select__loading-more",t.setAttribute("aria-hidden","true"),t.textContent=this.strings.loadingMore;break;case"create":t.className="forge-select__option forge-select__option--create",t.setAttribute("role","option"),t.id=`${this.uid}-nav-${e.navIndex}`,t.dataset.navIndex=String(e.navIndex),t.textContent=p(this.strings.createOption,{query:this.query.trim()}),e.navIndex===this.highlightedIndex&&t.classList.add("forge-select__option--highlighted");break;case"option":{t.className="forge-select__option",t.dataset.optionValue=e.option.value,e.option.className&&t.classList.add(...e.option.className.trim().split(/\s+/).filter(Boolean)),t.setAttribute("role","option");let i=this.selected.includes(e.option.value);if(t.setAttribute("aria-selected",String(i)),i&&t.classList.add("forge-select__option--selected"),this.opts.multiple&&e.hasChildren&&w(e.option,this.selected,this.isOptionDisabled)==="some"&&(t.classList.add("forge-select__option--indeterminate"),t.dataset.selectionState="mixed"),e.depth>0&&(t.style.paddingLeft=`calc(12px + ${e.depth} * var(--fs-tree-indent, 18px))`),this.isOptionDisabled(e.option)||this.hasReachedMaximum()&&!this.selected.includes(e.option.value)?(t.classList.add("forge-select__option--disabled"),t.setAttribute("aria-disabled","true")):(t.id=`${this.uid}-nav-${e.navIndex}`,t.dataset.navIndex=String(e.navIndex),e.navIndex===this.highlightedIndex&&t.classList.add("forge-select__option--highlighted")),e.hasChildren){let s=this.query!==""||this.expandedValues.has(e.option.value);t.setAttribute("aria-expanded",String(s));let n=document.createElement("span");n.className="forge-select__twisty",n.dataset.twisty=e.option.value,n.setAttribute("aria-hidden","true"),n.textContent=s?"\u25BC":"\u25B6",t.append(n)}t.append(this.optionContent(e.option));break}}return t}optionContent(e){if(this.opts.highlightSearch&&this.query.trim()&&!this.opts.templateResult){let i=document.createElement("span");i.className="forge-select__option-content",b(i,e,void 0);let s=i.querySelector(".forge-select__option-label")??i,n=q(e.label,this.query,this.opts.accentInsensitive);if(n.length){s.textContent="";let r=0;for(let[o,h]of n){if(o<r)continue;s.append(document.createTextNode(e.label.slice(r,o)));let l=document.createElement("mark");l.className="forge-select__match",l.textContent=e.label.slice(o,h),s.append(l),r=h}s.append(document.createTextNode(e.label.slice(r)))}return i}let t=this.rowContentCache.get(e.value);if(!t){let i=document.createElement("span");if(i.className="forge-select__option-content",b(i,e,this.opts.templateResult),this.rowContentCache.size>=J){let s=this.rowContentCache.keys().next().value;this.rowContentCache.delete(s)}this.rowContentCache.set(e.value,i),t=i}return t.cloneNode(!0)}moveHighlight(e){if(this.navItems.length===0)return;let t=this.highlightedIndex===-1?e>0?0:this.navItems.length-1:(this.highlightedIndex+e+this.navItems.length)%this.navItems.length;this.focusNavIndex(t)}focusNavIndex(e){if(this.navItems.length!==0)if(this.highlightedIndex=e,this.usesVirtualScroll()){let t=this.rows.findIndex(i=>(i.kind==="option"||i.kind==="create")&&i.navIndex===e);if(t>=0){let i=this.measuredRowHeight(t),s=this.rowOffset(t),n=this.list.clientHeight||i*8,r=this.list.scrollTop;s<r?r=s:s+i>r+n&&(r=s+i-n),r!==this.list.scrollTop&&(this.list.scrollTop=r)}this.renderRows()}else this.renderRows(),this.list.querySelector(".forge-select__option--highlighted")?.scrollIntoView?.({block:"nearest"})}navigateTree(e){let t=this.navItems[this.highlightedIndex];if(!t||t.kind!=="option")return!1;let{option:i,parentValue:s}=t,n=!!i.children?.length,r=this.query!==""||this.expandedValues.has(i.value);if(e==="right"){if(n&&!r)return this.expandedValues.add(i.value),this.renderList(),!0;if(n){let o=this.navItems.findIndex(h=>h.kind==="option"&&h.parentValue===i.value);if(o>=0)return this.focusNavIndex(o),!0}return!1}if(n&&r&&this.query==="")return this.expandedValues.delete(i.value),this.renderList(),!0;if(s){let o=this.navItems.findIndex(h=>h.kind==="option"&&h.option.value===s);if(o>=0)return this.focusNavIndex(o),!0}return!1}updateActiveDescendant(){let e=this.searchInput??this.control;this.highlightedIndex>=0?e.setAttribute("aria-activedescendant",`${this.uid}-nav-${this.highlightedIndex}`):e.removeAttribute("aria-activedescendant")}scheduleRemoteLoad(e,t){this.ajaxTimer&&clearTimeout(this.ajaxTimer);let i=++this.ajaxRequestId;this.ajaxController?.abort(),this.ajaxController=null,this.page=0,this.hasMore=!0,this.setLoading(!0),this.loadingMore=!1,this.loadError=null,this.renderList(),this.ajaxTimer=setTimeout(()=>{this.ajaxTimer=null,this.loadRemote(e,{requestId:i})},t)}setLoading(e){this.loading!==e&&(this.loading=e,this.emitter.emit("loading",e))}remoteCacheKey(e,t){return`${e}\0${t}`}async requestRemote(e,t,i){let s=this.opts.ajax,n=Math.max(0,Math.floor(s.retry??0))+1,r;for(let o=0;o<n;o+=1)try{if(s.request)return await s.request(e,t,i);let h=await fetch(j(s,e,t),{signal:i});if(h.ok===!1)throw new Error(`ForgeSelect: remote request failed with HTTP ${h.status}`);return await h.json()}catch(h){if(r=h,i.aborted||o===n-1)throw h;let l=Math.max(0,s.retryDelay??250)*2**o;await new Promise((c,d)=>{let u=setTimeout(c,l);i.addEventListener("abort",()=>{clearTimeout(u),d(new DOMException("Aborted","AbortError"))},{once:!0})})}throw r}async prefetchRemote(e){let t=this.opts.ajax;if(!t||(t.cacheTtl??3e4)<=0)return;let i=this.remoteCacheKey(e,0);if(this.remoteCache.get(i))return;let s=new AbortController;try{let n=await this.requestRemote(e,0,s.signal);this.remoteCache.set(i,A(t,n),t.cacheTtl??3e4)}catch{}}maybeLoadNextPage(){if(!this.opts.ajax?.pagination||!this.hasMore||this.loading||this.loadingMore)return;let{scrollHeight:t,scrollTop:i,clientHeight:s}=this.list,n=this.opts.itemHeight*2;t-i-s>=n||(this.loadingMore=!0,this.renderList(),this.loadRemote(this.query,{append:!0}))}async loadRemote(e,{append:t=!1,requestId:i}={}){let s=this.opts.ajax,n=i??++this.ajaxRequestId;if(n!==this.ajaxRequestId)return;this.ajaxController?.abort();let r=new AbortController;this.ajaxController=r;let o=t?this.page+1:0;try{let h=this.remoteCacheKey(e,o),l=this.remoteCache.get(h);if(!l){let u=await this.requestRemote(e,o,r.signal);l=A(s,u),this.remoteCache.set(h,l,s.cacheTtl??3e4)}if(n!==this.ajaxRequestId||this.destroyed)return;let{options:c,hasMore:d}=l;if(t){let u=M(this.data);this.data=[...this.data,...c.filter(m=>!u.has(m.value))]}else this.data=c,this.rowContentCache.clear(),this.rowHeightCache.clear();this.page=o,this.hasMore=d,this.remoteLoaded=!0,this.loadError=null}catch(h){if(n!==this.ajaxRequestId||this.destroyed||r.signal.aborted)return;let l=h instanceof Error?h:new Error(String(h));t||(this.data=[],this.rowContentCache.clear(),this.rowHeightCache.clear()),this.hasMore=!1,this.loadError=l,this.emitter.emit("error",l)}finally{n===this.ajaxRequestId&&!this.destroyed&&(this.ajaxController=null,this.setLoading(!1),this.loadingMore=!1,this.isOpen&&this.renderList())}}};return W(ie);})();
2
2
  //# sourceMappingURL=index.global.js.map