forge-select 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +352 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -3
- package/dist/index.d.ts +54 -3
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +352 -42
- 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;
|
|
@@ -192,6 +222,8 @@ declare class ForgeSelect {
|
|
|
192
222
|
private navItems;
|
|
193
223
|
private highlightedIndex;
|
|
194
224
|
private rowContentCache;
|
|
225
|
+
private rowHeightCache;
|
|
226
|
+
private searchIndex;
|
|
195
227
|
private expandedValues;
|
|
196
228
|
private loading;
|
|
197
229
|
private loadingMore;
|
|
@@ -201,6 +233,7 @@ declare class ForgeSelect {
|
|
|
201
233
|
private ajaxRequestId;
|
|
202
234
|
private ajaxController;
|
|
203
235
|
private remoteLoaded;
|
|
236
|
+
private remoteCache;
|
|
204
237
|
private loadError;
|
|
205
238
|
private originalDisplay;
|
|
206
239
|
private originalDisabled;
|
|
@@ -230,6 +263,15 @@ declare class ForgeSelect {
|
|
|
230
263
|
private positionDropdown;
|
|
231
264
|
destroy(): void;
|
|
232
265
|
getValue(): ForgeSelectValue;
|
|
266
|
+
getSearchQuery(): string;
|
|
267
|
+
setSearchQuery(query: string, options?: SetSearchQueryOptions): void;
|
|
268
|
+
isDropdownOpen(): boolean;
|
|
269
|
+
updateOptions(options: ForgeSelectUpdateOptions): void;
|
|
270
|
+
validate(): boolean;
|
|
271
|
+
setCustomValidity(message: string): void;
|
|
272
|
+
reportValidity(): boolean;
|
|
273
|
+
reload(): void;
|
|
274
|
+
clearRemoteCache(): void;
|
|
233
275
|
setValue(value: ForgeSelectValue, options?: SetValueOptions): void;
|
|
234
276
|
/**
|
|
235
277
|
* Replaces the option list after construction. An open dropdown re-renders
|
|
@@ -264,6 +306,7 @@ declare class ForgeSelect {
|
|
|
264
306
|
private updateSearchVisibility;
|
|
265
307
|
private buildDom;
|
|
266
308
|
private bindEvents;
|
|
309
|
+
private applySearchQuery;
|
|
267
310
|
private handleKeydown;
|
|
268
311
|
private canSelectOption;
|
|
269
312
|
private hasReachedMaximum;
|
|
@@ -305,6 +348,10 @@ declare class ForgeSelect {
|
|
|
305
348
|
private buildRows;
|
|
306
349
|
private hasExactMatch;
|
|
307
350
|
private usesVirtualScroll;
|
|
351
|
+
private rowKey;
|
|
352
|
+
private measuredRowHeight;
|
|
353
|
+
private rowOffset;
|
|
354
|
+
private rowOffsets;
|
|
308
355
|
private renderList;
|
|
309
356
|
private announceStatus;
|
|
310
357
|
private renderRows;
|
|
@@ -321,6 +368,10 @@ declare class ForgeSelect {
|
|
|
321
368
|
private navigateTree;
|
|
322
369
|
private updateActiveDescendant;
|
|
323
370
|
private scheduleRemoteLoad;
|
|
371
|
+
private setLoading;
|
|
372
|
+
private remoteCacheKey;
|
|
373
|
+
private requestRemote;
|
|
374
|
+
private prefetchRemote;
|
|
324
375
|
/**
|
|
325
376
|
* Fires on every list scroll. Only acts when pagination is opted into via
|
|
326
377
|
* `ajax.pagination`; reads real scroll geometry rather than row counts so
|
|
@@ -330,4 +381,4 @@ declare class ForgeSelect {
|
|
|
330
381
|
private loadRemote;
|
|
331
382
|
}
|
|
332
383
|
|
|
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 };
|
|
384
|
+
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;
|
|
@@ -192,6 +222,8 @@ declare class ForgeSelect {
|
|
|
192
222
|
private navItems;
|
|
193
223
|
private highlightedIndex;
|
|
194
224
|
private rowContentCache;
|
|
225
|
+
private rowHeightCache;
|
|
226
|
+
private searchIndex;
|
|
195
227
|
private expandedValues;
|
|
196
228
|
private loading;
|
|
197
229
|
private loadingMore;
|
|
@@ -201,6 +233,7 @@ declare class ForgeSelect {
|
|
|
201
233
|
private ajaxRequestId;
|
|
202
234
|
private ajaxController;
|
|
203
235
|
private remoteLoaded;
|
|
236
|
+
private remoteCache;
|
|
204
237
|
private loadError;
|
|
205
238
|
private originalDisplay;
|
|
206
239
|
private originalDisabled;
|
|
@@ -230,6 +263,15 @@ declare class ForgeSelect {
|
|
|
230
263
|
private positionDropdown;
|
|
231
264
|
destroy(): void;
|
|
232
265
|
getValue(): ForgeSelectValue;
|
|
266
|
+
getSearchQuery(): string;
|
|
267
|
+
setSearchQuery(query: string, options?: SetSearchQueryOptions): void;
|
|
268
|
+
isDropdownOpen(): boolean;
|
|
269
|
+
updateOptions(options: ForgeSelectUpdateOptions): void;
|
|
270
|
+
validate(): boolean;
|
|
271
|
+
setCustomValidity(message: string): void;
|
|
272
|
+
reportValidity(): boolean;
|
|
273
|
+
reload(): void;
|
|
274
|
+
clearRemoteCache(): void;
|
|
233
275
|
setValue(value: ForgeSelectValue, options?: SetValueOptions): void;
|
|
234
276
|
/**
|
|
235
277
|
* Replaces the option list after construction. An open dropdown re-renders
|
|
@@ -264,6 +306,7 @@ declare class ForgeSelect {
|
|
|
264
306
|
private updateSearchVisibility;
|
|
265
307
|
private buildDom;
|
|
266
308
|
private bindEvents;
|
|
309
|
+
private applySearchQuery;
|
|
267
310
|
private handleKeydown;
|
|
268
311
|
private canSelectOption;
|
|
269
312
|
private hasReachedMaximum;
|
|
@@ -305,6 +348,10 @@ declare class ForgeSelect {
|
|
|
305
348
|
private buildRows;
|
|
306
349
|
private hasExactMatch;
|
|
307
350
|
private usesVirtualScroll;
|
|
351
|
+
private rowKey;
|
|
352
|
+
private measuredRowHeight;
|
|
353
|
+
private rowOffset;
|
|
354
|
+
private rowOffsets;
|
|
308
355
|
private renderList;
|
|
309
356
|
private announceStatus;
|
|
310
357
|
private renderRows;
|
|
@@ -321,6 +368,10 @@ declare class ForgeSelect {
|
|
|
321
368
|
private navigateTree;
|
|
322
369
|
private updateActiveDescendant;
|
|
323
370
|
private scheduleRemoteLoad;
|
|
371
|
+
private setLoading;
|
|
372
|
+
private remoteCacheKey;
|
|
373
|
+
private requestRemote;
|
|
374
|
+
private prefetchRemote;
|
|
324
375
|
/**
|
|
325
376
|
* Fires on every list scroll. Only acts when pagination is opted into via
|
|
326
377
|
* `ajax.pagination`; reads real scroll geometry rather than row counts so
|
|
@@ -330,4 +381,4 @@ declare class ForgeSelect {
|
|
|
330
381
|
private loadRemote;
|
|
331
382
|
}
|
|
332
383
|
|
|
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 };
|
|
384
|
+
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 B=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var U=(a,e)=>{for(var t in e)L(a,t,{get:e[t],enumerable:!0})},Q=(a,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of z(e))!K.call(a,s)&&s!==t&&L(a,s,{get:()=>e[s],enumerable:!(i=B(e,s))||i.enumerable});return a};var G=a=>Q(L({},"__esModule",{value:!0}),a);var ee={};U(ee,{ForgeSelect:()=>v,default:()=>v});var x=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 A(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 T(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()){i>0&&this.entries.set(e,{value:t,expiresAt:s+i})}clear(){this.entries.clear()}};function g(a,e=!0){let t=a.toLocaleLowerCase();return e?t.normalize("NFD").replace(/[\u0300-\u036f]/g,"").replace(/đ/g,"d"):t}function W(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 w=class{constructor(){this.cache=new WeakMap}clear(){this.cache=new WeakMap}score(e,t,i){let s=g(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=>g(W(e,c),i.accentInsensitive)),r.set(n,o)),!(i.tokenSearch?s.split(/\s+/).filter(Boolean):[s]).every(c=>o.some(u=>u.includes(c))))return 0;let h=o[i.fields.indexOf("label")];return h===s?4:h?.startsWith(s)?3:h?.includes(s)?2:1}};function q(a,e,t=!0){let i=g(e.trim(),t).split(/\s+/).filter(Boolean);if(!i.length)return[];let s=g(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 m(a){return a.options!==void 0}var H=a=>!!a.disabled;function S(a,e=H){if(!a.children)return[];let t=[];for(let i of a.children)e(i)||t.push(i.value),t.push(...S(i,e));return t}function O(a,e,t=H){if(!a.children?.length)return e.includes(a.value)?"all":"none";let i=a.children.filter(s=>!t(s)).map(s=>O(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(m(i)?i.options:[i]);if(s)return s}}function M(a,e,t=H){let i=s=>{if(!s.children?.length)return;for(let o of s.children)i(o);let n=O(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)(m(s)?s.options:[s]).forEach(i)}function D(a){let e=new Set,t=i=>{e.add(i.value),i.children?.forEach(t)};for(let i of a)(m(i)?i.options:[i]).forEach(t);return e}function $(a,e){return a.length===e.length&&a.every((t,i)=>t===e[i])}var X=36,E=5,J=100,Y=2e3,Z=0,v=class{constructor(e,t={}){this.selected=[];this.selectedOptions=new Map;this.suppressNextTagClick=!1;this.emitter=new x;this.uid=`forge-select-${++Z}`;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.rowHeightCache=new Map;this.searchIndex=new w;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.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):X,variableItemHeight:t.itemHeight==="auto",language:t.language??"en",plugins:t.plugins??[],openOnFocus:t.openOnFocus??!1,dropdownParent:t.dropdownParent},this.strings=A(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.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.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=A(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.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(!$(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.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||D(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.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,this.rowContentCache.clear(),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"Tab":this.close();break}}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 S(e,this.isOptionDisabled))t.includes(i)||t.push(i);return M(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 S(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 S(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(){M(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)(m(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.renderList(),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(m(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())}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=h=>{if(!n){if(Math.abs(h.clientX-s)<4)return;n=!0,r=[...this.selected],typeof this.valueEl.setPointerCapture=="function"&&this.valueEl.setPointerCapture(h.pointerId),e.classList.add("forge-select__tag--dragging")}h.preventDefault();let c=r.indexOf(t),u=Array.from(this.valueEl.querySelectorAll(".forge-select__tag"));for(let d of u){if(d===e)continue;let f=d.dataset.value;if(!f)continue;let I=r.indexOf(f);if(I===-1)continue;let R=d.getBoundingClientRect(),k=R.left+R.width/2,_=c<I;if(_?h.clientX>k:h.clientX<k){r.splice(c,1),r.splice(I,0,t),_?this.valueEl.insertBefore(e,d.nextSibling):this.valueEl.insertBefore(e,d);break}}},l=h=>{this.valueEl.removeEventListener("pointermove",o),this.valueEl.removeEventListener("pointerup",l),this.valueEl.removeEventListener("pointercancel",l),n&&(typeof this.valueEl.releasePointerCapture=="function"&&this.valueEl.releasePointerCapture(h.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",h=>{this.isDisabled||h.button!==0||h.target.closest(".forge-select__tag-remove")||(s=h.clientX,n=!1,this.valueEl.addEventListener("pointermove",o),this.valueEl.addEventListener("pointerup",l),this.valueEl.addEventListener("pointercancel",l))})}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=[];let e=this.query.trim(),t=g(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,l)=>{let h=-1;this.isOptionDisabled(r)||this.hasReachedMaximum()&&!this.selected.includes(r.value)||(h=this.navItems.length,this.navItems.push({kind:"option",option:r,parentValue:l}));let u=!!r.children&&r.children.length>0;if(this.rows.push({kind:"option",option:r,navIndex:h,depth:o,hasChildren:u}),u&&(t!==""||this.expandedValues.has(r.value)))for(let f of r.children)s(f)&&n(f,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(m(r)){let o=r.options.filter(s);if(o.length===0)continue;this.rows.push({kind:"group",label:r.label}),o.forEach(l=>n(l,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>J}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(){let e=[0];for(let t=0;t<this.rows.length;t+=1)e.push(e[t]+this.measuredRowHeight(t));return 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-E),o=r;let c=e+l+E*s;for(;o<this.rows.length&&n[o]<c;)o+=1}else r=Math.max(0,Math.floor(e/s)-E),o=Math.min(this.rows.length,r+Math.ceil(l/s)+E*2);let h=document.createElement("li");h.className="forge-select__spacer",h.setAttribute("aria-hidden","true"),h.style.height=`${n?.[r]??this.rowOffset(r)}px`,this.list.append(h)}for(let l=r;l<o;l++){let h=this.renderRow(this.rows[l]);if(this.list.append(h),this.opts.variableItemHeight){let c=h.getBoundingClientRect().height||h.offsetHeight;c>0&&this.rowHeightCache.set(this.rowKey(this.rows[l],l),c)}}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&&O(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,l]of n){if(o<r)continue;s.append(document.createTextNode(e.label.slice(r,o)));let h=document.createElement("mark");h.className="forge-select__match",h.textContent=e.label.slice(o,l),s.append(h),r=l}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>=Y){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.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(l=>l.kind==="option"&&l.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(l=>l.kind==="option"&&l.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 l=await fetch(j(s,e,t),{signal:i});if(l.ok===!1)throw new Error(`ForgeSelect: remote request failed with HTTP ${l.status}`);return await l.json()}catch(l){if(r=l,i.aborted||o===n-1)throw l;let h=Math.max(0,s.retryDelay??250)*2**o;await new Promise((c,u)=>{let d=setTimeout(c,h);i.addEventListener("abort",()=>{clearTimeout(d),u(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,T(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 l=this.remoteCacheKey(e,o),h=this.remoteCache.get(l);if(!h){let d=await this.requestRemote(e,o,r.signal);h=T(s,d),this.remoteCache.set(l,h,s.cacheTtl??3e4)}if(n!==this.ajaxRequestId||this.destroyed)return;let{options:c,hasMore:u}=h;if(t){let d=D(this.data);this.data=[...this.data,...c.filter(f=>!d.has(f.value))]}else this.data=c,this.rowContentCache.clear();this.page=o,this.hasMore=u,this.remoteLoaded=!0,this.loadError=null}catch(l){if(n!==this.ajaxRequestId||this.destroyed||r.signal.aborted)return;let h=l instanceof Error?l:new Error(String(l));t||(this.data=[],this.rowContentCache.clear()),this.hasMore=!1,this.loadError=h,this.emitter.emit("error",h)}finally{n===this.ajaxRequestId&&!this.destroyed&&(this.ajaxController=null,this.setLoading(!1),this.loadingMore=!1,this.isOpen&&this.renderList())}}};return G(ee);})();
|
|
2
2
|
//# sourceMappingURL=index.global.js.map
|