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/README.md +1 -1
- package/dist/index.cjs +467 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -3
- package/dist/index.d.ts +65 -3
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +467 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/forge-select.css +12 -0
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
|
|
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
|
|
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.global.js
CHANGED
|
@@ -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
|