@strapi/ui-primitives 1.19.0-typescript.0 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const reactComposeRefs = require("@radix-ui/react-compose-refs");
6
+ const reactContext = require("@radix-ui/react-context");
7
+ const reactSlot = require("@radix-ui/react-slot");
8
+ const primitive = require("@radix-ui/primitive");
9
+ const reactDismissableLayer = require("@radix-ui/react-dismissable-layer");
10
+ const reactFocusGuards = require("@radix-ui/react-focus-guards");
11
+ const reactFocusScope = require("@radix-ui/react-focus-scope");
12
+ const reactId = require("@radix-ui/react-id");
13
+ const PopperPrimitive = require("@radix-ui/react-popper");
14
+ const reactPortal = require("@radix-ui/react-portal");
15
+ const reactPrimitive = require("@radix-ui/react-primitive");
16
+ const reactUseControllableState = require("@radix-ui/react-use-controllable-state");
17
+ const reactUseLayoutEffect = require("@radix-ui/react-use-layout-effect");
18
+ const ariaHidden = require("aria-hidden");
19
+ const ReactDOM = require("react-dom");
20
+ const reactRemoveScroll = require("react-remove-scroll");
21
+ const number = require("@radix-ui/number");
22
+ const reactCollection = require("@radix-ui/react-collection");
23
+ const reactDirection = require("@radix-ui/react-direction");
24
+ const reactUsePrevious = require("@radix-ui/react-use-previous");
25
+ const reactVisuallyHidden = require("@radix-ui/react-visually-hidden");
26
+ const reactUseCallbackRef = require("@radix-ui/react-use-callback-ref");
27
+ function _interopNamespace(e) {
28
+ if (e && e.__esModule)
29
+ return e;
30
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
31
+ if (e) {
32
+ for (const k in e) {
33
+ if (k !== "default") {
34
+ const d = Object.getOwnPropertyDescriptor(e, k);
35
+ Object.defineProperty(n, k, d.get ? d : {
36
+ enumerable: true,
37
+ get: () => e[k]
38
+ });
39
+ }
40
+ }
41
+ }
42
+ n.default = e;
43
+ return Object.freeze(n);
44
+ }
45
+ const React__namespace = /* @__PURE__ */ _interopNamespace(React);
46
+ const PopperPrimitive__namespace = /* @__PURE__ */ _interopNamespace(PopperPrimitive);
47
+ const ReactDOM__namespace = /* @__PURE__ */ _interopNamespace(ReactDOM);
48
+ function createCollection(name) {
49
+ const PROVIDER_NAME = `${name}CollectionProvider`;
50
+ const [createCollectionContext, createCollectionScope2] = reactContext.createContextScope(PROVIDER_NAME);
51
+ const [CollectionProviderImpl, useCollectionContext] = createCollectionContext(PROVIDER_NAME, {
52
+ collectionRef: { current: null },
53
+ itemMap: /* @__PURE__ */ new Map(),
54
+ listeners: /* @__PURE__ */ new Set()
55
+ });
56
+ const CollectionProvider = (props) => {
57
+ const { scope, children } = props;
58
+ const ref = React__namespace.useRef(null);
59
+ const itemMap = React__namespace.useRef(/* @__PURE__ */ new Map()).current;
60
+ const listeners = React__namespace.useRef(/* @__PURE__ */ new Set()).current;
61
+ return /* @__PURE__ */ jsxRuntime.jsx(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, listeners, children });
62
+ };
63
+ CollectionProvider.displayName = PROVIDER_NAME;
64
+ const COLLECTION_SLOT_NAME = `${name}CollectionSlot`;
65
+ const CollectionSlot = React__namespace.forwardRef((props, forwardedRef) => {
66
+ const { scope, children } = props;
67
+ const context = useCollectionContext(COLLECTION_SLOT_NAME, scope);
68
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, context.collectionRef);
69
+ return /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { ref: composedRefs, children });
70
+ });
71
+ CollectionSlot.displayName = COLLECTION_SLOT_NAME;
72
+ const ITEM_SLOT_NAME = `${name}CollectionItemSlot`;
73
+ const ITEM_DATA_ATTR = "data-radix-collection-item";
74
+ const CollectionItemSlot = React__namespace.forwardRef((props, forwardedRef) => {
75
+ const { scope, children, ...itemData } = props;
76
+ const ref = React__namespace.useRef(null);
77
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, ref);
78
+ const context = useCollectionContext(ITEM_SLOT_NAME, scope);
79
+ React__namespace.useEffect(() => {
80
+ const previousMap = Array.from(context.itemMap.values());
81
+ context.itemMap.set(ref, { ref, ...itemData });
82
+ context.listeners.forEach((listener) => listener(Array.from(context.itemMap.values()), previousMap));
83
+ return () => {
84
+ const previousMap2 = Array.from(context.itemMap.values());
85
+ context.itemMap.delete(ref);
86
+ context.listeners.forEach((listener) => listener(Array.from(context.itemMap.values()), previousMap2));
87
+ };
88
+ });
89
+ return /* @__PURE__ */ jsxRuntime.jsx(reactSlot.Slot, { ...{ [ITEM_DATA_ATTR]: "" }, ref: composedRefs, children });
90
+ });
91
+ CollectionItemSlot.displayName = ITEM_SLOT_NAME;
92
+ function useCollection2(scope) {
93
+ const context = useCollectionContext(`${name}CollectionConsumer`, scope);
94
+ const getItems = React__namespace.useCallback(() => {
95
+ const collectionNode = context.collectionRef.current;
96
+ if (!collectionNode)
97
+ return [];
98
+ const orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));
99
+ const items = Array.from(context.itemMap.values());
100
+ const orderedItems = items.sort(
101
+ (a, b) => orderedNodes.indexOf(a.ref.current) - orderedNodes.indexOf(b.ref.current)
102
+ );
103
+ return orderedItems;
104
+ }, [context.collectionRef, context.itemMap]);
105
+ const subscribe = React__namespace.useCallback(
106
+ (listener) => {
107
+ context.listeners.add(listener);
108
+ return () => context.listeners.delete(listener);
109
+ },
110
+ [context.listeners]
111
+ );
112
+ return { getItems, subscribe };
113
+ }
114
+ return [
115
+ { Provider: CollectionProvider, Slot: CollectionSlot, ItemSlot: CollectionItemSlot },
116
+ useCollection2,
117
+ createCollectionScope2
118
+ ];
119
+ }
120
+ const cache = /* @__PURE__ */ new Map();
121
+ function useCollator(locale, options) {
122
+ const cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "");
123
+ if (cache.has(cacheKey)) {
124
+ return cache.get(cacheKey);
125
+ }
126
+ const formatter = new Intl.Collator(locale, options);
127
+ cache.set(cacheKey, formatter);
128
+ return formatter;
129
+ }
130
+ function useFilter(locale, options) {
131
+ const collator = useCollator(locale, {
132
+ usage: "search",
133
+ ...options
134
+ });
135
+ return {
136
+ startsWith(string, substring) {
137
+ if (substring.length === 0) {
138
+ return true;
139
+ }
140
+ string = string.normalize("NFC");
141
+ substring = substring.normalize("NFC");
142
+ return collator.compare(string.slice(0, substring.length), substring) === 0;
143
+ },
144
+ endsWith(string, substring) {
145
+ if (substring.length === 0) {
146
+ return true;
147
+ }
148
+ string = string.normalize("NFC");
149
+ substring = substring.normalize("NFC");
150
+ return collator.compare(string.slice(-substring.length), substring) === 0;
151
+ },
152
+ contains(string, substring) {
153
+ if (substring.length === 0) {
154
+ return true;
155
+ }
156
+ string = string.normalize("NFC");
157
+ substring = substring.normalize("NFC");
158
+ let scan = 0;
159
+ const sliceLen = substring.length;
160
+ for (; scan + sliceLen <= string.length; scan++) {
161
+ const slice = string.slice(scan, scan + sliceLen);
162
+ if (collator.compare(substring, slice) === 0) {
163
+ return true;
164
+ }
165
+ }
166
+ return false;
167
+ }
168
+ };
169
+ }
170
+ const usePrev = (value) => {
171
+ const ref = React__namespace.useRef();
172
+ React__namespace.useEffect(() => {
173
+ ref.current = value;
174
+ });
175
+ return ref.current;
176
+ };
177
+ const OPEN_KEYS$1 = [" ", "Enter", "ArrowUp", "ArrowDown"];
178
+ const SELECTION_KEYS$1 = ["Enter"];
179
+ const defaultIsPrintableCharacter = (str) => {
180
+ return Boolean(str.length === 1 && str.match(/\S| /));
181
+ };
182
+ const COMBOBOX_NAME = "Combobox";
183
+ const [Collection$1, useCollection$1] = createCollection(COMBOBOX_NAME);
184
+ const [ComboboxProvider, useComboboxContext] = reactContext.createContext(COMBOBOX_NAME);
185
+ const ComboboxProviders = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx(PopperPrimitive__namespace.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(Collection$1.Provider, { scope: void 0, children }) });
186
+ const formatAutocomplete = (autocomplete) => {
187
+ if (typeof autocomplete === "string") {
188
+ if (autocomplete === "none") {
189
+ return {
190
+ type: autocomplete,
191
+ filter: void 0
192
+ };
193
+ }
194
+ return {
195
+ type: autocomplete,
196
+ filter: "startsWith"
197
+ };
198
+ }
199
+ return autocomplete;
200
+ };
201
+ const Combobox = (props) => {
202
+ const {
203
+ allowCustomValue = false,
204
+ autocomplete = "none",
205
+ children,
206
+ open: openProp,
207
+ defaultOpen,
208
+ onOpenChange,
209
+ value: valueProp,
210
+ defaultValue,
211
+ onValueChange,
212
+ disabled,
213
+ required = false,
214
+ locale = "en-EN",
215
+ onTextValueChange,
216
+ textValue: textValueProp,
217
+ defaultTextValue,
218
+ filterValue: filterValueProp,
219
+ defaultFilterValue,
220
+ onFilterValueChange,
221
+ isPrintableCharacter = defaultIsPrintableCharacter
222
+ } = props;
223
+ const [trigger, setTrigger] = React__namespace.useState(null);
224
+ const [viewport, setViewport] = React__namespace.useState(null);
225
+ const [content, setContent] = React__namespace.useState(null);
226
+ const [visuallyFocussedItem, setVisuallyFocussedItem] = React__namespace.useState(null);
227
+ const [open = false, setOpen] = reactUseControllableState.useControllableState({
228
+ prop: openProp,
229
+ defaultProp: defaultOpen,
230
+ onChange: onOpenChange
231
+ });
232
+ const [value, setValue] = reactUseControllableState.useControllableState({
233
+ prop: valueProp,
234
+ defaultProp: defaultValue,
235
+ onChange: onValueChange
236
+ });
237
+ const [textValue, setTextValue] = reactUseControllableState.useControllableState({
238
+ prop: textValueProp,
239
+ defaultProp: allowCustomValue && !defaultTextValue ? valueProp : defaultTextValue,
240
+ onChange: onTextValueChange
241
+ });
242
+ const [filterValue, setFilterValue] = reactUseControllableState.useControllableState({
243
+ prop: filterValueProp,
244
+ defaultProp: defaultFilterValue,
245
+ onChange: onFilterValueChange
246
+ });
247
+ const id = reactId.useId();
248
+ const focusFirst = React__namespace.useCallback(
249
+ (candidates, items) => {
250
+ const allItems = items.map((item) => item.ref.current);
251
+ const [firstItem, ...restItems] = allItems;
252
+ const [lastItem] = restItems.slice(-1);
253
+ const PREVIOUSLY_FOCUSED_ELEMENT = visuallyFocussedItem ?? items.find((item) => item.value === value)?.ref.current;
254
+ for (const candidate of candidates) {
255
+ if (candidate === PREVIOUSLY_FOCUSED_ELEMENT)
256
+ return;
257
+ candidate?.scrollIntoView({ block: "nearest" });
258
+ if (candidate === firstItem && viewport)
259
+ viewport.scrollTop = 0;
260
+ if (candidate === lastItem && viewport)
261
+ viewport.scrollTop = viewport.scrollHeight;
262
+ setVisuallyFocussedItem(candidate);
263
+ if (autocomplete === "both") {
264
+ const item = items.find((item2) => item2.ref.current === candidate);
265
+ if (item) {
266
+ setTextValue(item.textValue);
267
+ }
268
+ }
269
+ if (candidate !== PREVIOUSLY_FOCUSED_ELEMENT)
270
+ return;
271
+ }
272
+ },
273
+ [autocomplete, setTextValue, viewport, visuallyFocussedItem, value]
274
+ );
275
+ const autocompleteObject = formatAutocomplete(autocomplete);
276
+ React__namespace.useEffect(() => {
277
+ if (autocomplete !== "both") {
278
+ setVisuallyFocussedItem(null);
279
+ }
280
+ }, [textValue, autocomplete]);
281
+ React__namespace.useEffect(() => {
282
+ if (content && trigger)
283
+ return ariaHidden.hideOthers([content, trigger]);
284
+ }, [content, trigger]);
285
+ return /* @__PURE__ */ jsxRuntime.jsx(ComboboxProviders, { children: /* @__PURE__ */ jsxRuntime.jsx(
286
+ ComboboxProvider,
287
+ {
288
+ allowCustomValue,
289
+ autocomplete: autocompleteObject,
290
+ required,
291
+ trigger,
292
+ onTriggerChange: setTrigger,
293
+ contentId: id,
294
+ value,
295
+ onValueChange: setValue,
296
+ open,
297
+ onOpenChange: setOpen,
298
+ disabled,
299
+ locale,
300
+ focusFirst,
301
+ textValue,
302
+ onTextValueChange: setTextValue,
303
+ onViewportChange: setViewport,
304
+ onContentChange: setContent,
305
+ visuallyFocussedItem,
306
+ filterValue,
307
+ onFilterValueChange: setFilterValue,
308
+ onVisuallyFocussedItemChange: setVisuallyFocussedItem,
309
+ isPrintableCharacter,
310
+ children
311
+ }
312
+ ) });
313
+ };
314
+ const TRIGGER_NAME$1 = "ComboboxTrigger";
315
+ const ComboboxTrigger = React__namespace.forwardRef((props, forwardedRef) => {
316
+ const { ...triggerProps } = props;
317
+ const context = useComboboxContext(TRIGGER_NAME$1);
318
+ const handleOpen = () => {
319
+ if (!context.disabled) {
320
+ context.onOpenChange(true);
321
+ }
322
+ };
323
+ return /* @__PURE__ */ jsxRuntime.jsx(PopperPrimitive__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
324
+ reactFocusScope.FocusScope,
325
+ {
326
+ asChild: true,
327
+ trapped: context.open,
328
+ onMountAutoFocus: (event) => {
329
+ event.preventDefault();
330
+ },
331
+ onUnmountAutoFocus: (event) => {
332
+ context.trigger?.focus({ preventScroll: true });
333
+ document.getSelection()?.empty();
334
+ event.preventDefault();
335
+ },
336
+ children: /* @__PURE__ */ jsxRuntime.jsx(
337
+ "div",
338
+ {
339
+ ref: forwardedRef,
340
+ "data-disabled": context.disabled ? "" : void 0,
341
+ ...triggerProps,
342
+ onClick: primitive.composeEventHandlers(triggerProps.onClick, () => {
343
+ context.trigger?.focus();
344
+ }),
345
+ onPointerDown: primitive.composeEventHandlers(triggerProps.onPointerDown, (event) => {
346
+ const target = event.target;
347
+ if (target.hasPointerCapture(event.pointerId)) {
348
+ target.releasePointerCapture(event.pointerId);
349
+ }
350
+ const buttonTarg = target.closest("button") ?? target.closest("div");
351
+ if (buttonTarg !== event.currentTarget) {
352
+ return;
353
+ }
354
+ if (event.button === 0 && event.ctrlKey === false) {
355
+ handleOpen();
356
+ context.trigger?.focus();
357
+ }
358
+ })
359
+ }
360
+ )
361
+ }
362
+ ) });
363
+ });
364
+ ComboboxTrigger.displayName = TRIGGER_NAME$1;
365
+ const INPUT_NAME = "ComboboxInput";
366
+ const ComboxboxTextInput = React__namespace.forwardRef((props, forwardedRef) => {
367
+ const context = useComboboxContext(INPUT_NAME);
368
+ const inputRef = React__namespace.useRef(null);
369
+ const { getItems } = useCollection$1(void 0);
370
+ const { startsWith } = useFilter(context.locale, { sensitivity: "base" });
371
+ const isDisabled = context.disabled;
372
+ const composedRefs = reactComposeRefs.useComposedRefs(inputRef, forwardedRef, context.onTriggerChange);
373
+ const handleOpen = () => {
374
+ if (!isDisabled) {
375
+ context.onOpenChange(true);
376
+ }
377
+ };
378
+ const previousFilter = usePrev(context.filterValue);
379
+ reactUseLayoutEffect.useLayoutEffect(() => {
380
+ const timeout = setTimeout(() => {
381
+ if (context.textValue === "" || context.textValue === void 0 || context.filterValue === "" || context.filterValue === void 0)
382
+ return;
383
+ const firstItem = getItems().find(
384
+ (item) => item.type === "option" && startsWith(item.textValue, context.textValue)
385
+ );
386
+ const characterChangedAtIndex = findChangedIndex(previousFilter ?? "", context.filterValue);
387
+ if (firstItem && !context.visuallyFocussedItem && characterChangedAtIndex === context.filterValue.length) {
388
+ inputRef.current?.setSelectionRange(context.filterValue.length, context.textValue.length);
389
+ }
390
+ });
391
+ return () => clearTimeout(timeout);
392
+ }, [context.textValue, context.filterValue, startsWith, context.visuallyFocussedItem, getItems, previousFilter]);
393
+ return /* @__PURE__ */ jsxRuntime.jsx(
394
+ "input",
395
+ {
396
+ type: "text",
397
+ role: "combobox",
398
+ "aria-controls": context.contentId,
399
+ "aria-expanded": context.open,
400
+ "aria-required": context.required,
401
+ "aria-autocomplete": context.autocomplete.type,
402
+ "data-state": context.open ? "open" : "closed",
403
+ "aria-disabled": isDisabled,
404
+ "aria-activedescendant": context.visuallyFocussedItem?.id,
405
+ disabled: isDisabled,
406
+ "data-disabled": isDisabled ? "" : void 0,
407
+ "data-placeholder": context.textValue === void 0 ? "" : void 0,
408
+ value: context.textValue ?? "",
409
+ ...props,
410
+ ref: composedRefs,
411
+ onKeyDown: primitive.composeEventHandlers(props.onKeyDown, (event) => {
412
+ if (["ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) {
413
+ if (!context.open) {
414
+ handleOpen();
415
+ }
416
+ setTimeout(() => {
417
+ const items = getItems().filter((item) => !item.disabled && item.isVisible);
418
+ let candidateNodes = items.map((item) => item.ref.current);
419
+ if (["ArrowUp", "End"].includes(event.key)) {
420
+ candidateNodes = candidateNodes.slice().reverse();
421
+ }
422
+ if (["ArrowUp", "ArrowDown"].includes(event.key)) {
423
+ const currentElement = context.visuallyFocussedItem ?? getItems().find((item) => item.value === context.value)?.ref.current;
424
+ if (currentElement) {
425
+ let currentIndex = candidateNodes.indexOf(currentElement);
426
+ if (currentIndex === candidateNodes.length - 1) {
427
+ currentIndex = -1;
428
+ }
429
+ candidateNodes = candidateNodes.slice(currentIndex + 1);
430
+ }
431
+ }
432
+ if (["ArrowDown"].includes(event.key) && context.autocomplete.type === "both" && candidateNodes.length > 1) {
433
+ const [firstItem, ...restItems] = candidateNodes;
434
+ const firstItemText = getItems().find((item) => item.ref.current === firstItem).textValue;
435
+ if (context.textValue === firstItemText) {
436
+ candidateNodes = restItems;
437
+ }
438
+ }
439
+ context.focusFirst(candidateNodes, getItems());
440
+ });
441
+ event.preventDefault();
442
+ } else if (["Tab"].includes(event.key) && context.open) {
443
+ event.preventDefault();
444
+ } else if (["Escape"].includes(event.key)) {
445
+ if (context.open) {
446
+ context.onOpenChange(false);
447
+ } else {
448
+ context.onValueChange(void 0);
449
+ context.onTextValueChange("");
450
+ }
451
+ event.preventDefault();
452
+ } else if (SELECTION_KEYS$1.includes(event.key)) {
453
+ if (context.visuallyFocussedItem) {
454
+ const focussedItem = getItems().find((item) => item.ref.current === context.visuallyFocussedItem);
455
+ if (focussedItem) {
456
+ context.onValueChange(focussedItem.value);
457
+ context.onTextValueChange(focussedItem.textValue);
458
+ if (context.autocomplete.type === "both") {
459
+ context.onFilterValueChange(focussedItem.textValue);
460
+ }
461
+ focussedItem.ref.current?.click();
462
+ }
463
+ } else {
464
+ const matchedItem = getItems().find(
465
+ (item) => item.type === "option" && !item.disabled && item.textValue === context.textValue
466
+ );
467
+ if (matchedItem) {
468
+ context.onValueChange(matchedItem.value);
469
+ context.onTextValueChange(matchedItem.textValue);
470
+ if (context.autocomplete.type === "both") {
471
+ context.onFilterValueChange(matchedItem.textValue);
472
+ }
473
+ matchedItem.ref.current?.click();
474
+ }
475
+ }
476
+ context.onOpenChange(false);
477
+ event.preventDefault();
478
+ } else {
479
+ context.onVisuallyFocussedItemChange(null);
480
+ }
481
+ }),
482
+ onChange: primitive.composeEventHandlers(props.onChange, (event) => {
483
+ context.onTextValueChange(event.currentTarget.value);
484
+ if (context.autocomplete.type === "both") {
485
+ context.onFilterValueChange(event.currentTarget.value);
486
+ }
487
+ }),
488
+ onKeyUp: primitive.composeEventHandlers(props.onKeyUp, (event) => {
489
+ if (!context.open && (context.isPrintableCharacter(event.key) || ["Backspace"].includes(event.key))) {
490
+ handleOpen();
491
+ }
492
+ setTimeout(() => {
493
+ if (context.autocomplete.type === "both" && context.isPrintableCharacter(event.key) && context.filterValue !== void 0) {
494
+ const value = context.filterValue;
495
+ const firstItem = getItems().find((item) => startsWith(item.textValue, value));
496
+ if (firstItem) {
497
+ context.onTextValueChange(firstItem.textValue);
498
+ }
499
+ }
500
+ });
501
+ if (context.autocomplete.type === "none" && context.isPrintableCharacter(event.key)) {
502
+ const value = context.textValue ?? "";
503
+ const nextItem = getItems().find((item) => startsWith(item.textValue, value));
504
+ if (nextItem) {
505
+ context.onVisuallyFocussedItemChange(nextItem.ref.current);
506
+ nextItem.ref.current?.scrollIntoView();
507
+ }
508
+ }
509
+ }),
510
+ onBlur: primitive.composeEventHandlers(props.onBlur, () => {
511
+ if (context.open) {
512
+ return;
513
+ }
514
+ context.onVisuallyFocussedItemChange(null);
515
+ const [activeItem] = getItems().filter(
516
+ (item) => item.textValue === context.textValue && item.type === "option"
517
+ );
518
+ if (activeItem) {
519
+ context.onValueChange(activeItem.value);
520
+ if (context.autocomplete.type === "both") {
521
+ context.onFilterValueChange(activeItem.textValue);
522
+ }
523
+ return;
524
+ }
525
+ if (context.allowCustomValue) {
526
+ context.onValueChange(context.textValue);
527
+ if (context.autocomplete.type === "both") {
528
+ context.onFilterValueChange(context.textValue);
529
+ }
530
+ return;
531
+ }
532
+ const [previousItem] = getItems().filter((item) => item.value === context.value && item.type === "option");
533
+ if (previousItem && context.textValue !== "") {
534
+ context.onTextValueChange(previousItem.textValue);
535
+ if (context.autocomplete.type === "both") {
536
+ context.onFilterValueChange(previousItem.textValue);
537
+ }
538
+ } else {
539
+ context.onValueChange(void 0);
540
+ context.onTextValueChange("");
541
+ }
542
+ })
543
+ }
544
+ );
545
+ });
546
+ ComboxboxTextInput.displayName = "ComboboxTextInput";
547
+ const ComboboxIcon = React__namespace.forwardRef((props, forwardedRef) => {
548
+ const { children, ...iconProps } = props;
549
+ const context = useComboboxContext(INPUT_NAME);
550
+ const isDisabled = context.disabled;
551
+ const handleOpen = () => {
552
+ if (!isDisabled) {
553
+ context.onOpenChange(true);
554
+ context.trigger?.focus();
555
+ }
556
+ };
557
+ return /* @__PURE__ */ jsxRuntime.jsx(
558
+ reactPrimitive.Primitive.button,
559
+ {
560
+ "aria-hidden": true,
561
+ type: "button",
562
+ "aria-disabled": isDisabled,
563
+ "aria-controls": context.contentId,
564
+ "aria-expanded": context.open,
565
+ disabled: isDisabled,
566
+ "data-disabled": isDisabled ? "" : void 0,
567
+ ...iconProps,
568
+ tabIndex: -1,
569
+ ref: forwardedRef,
570
+ onClick: primitive.composeEventHandlers(iconProps.onClick, () => {
571
+ context.trigger?.focus();
572
+ }),
573
+ onPointerDown: primitive.composeEventHandlers(iconProps.onPointerDown, (event) => {
574
+ if (event.button === 0 && event.ctrlKey === false) {
575
+ handleOpen();
576
+ event.preventDefault();
577
+ }
578
+ }),
579
+ onKeyDown: primitive.composeEventHandlers(iconProps.onKeyDown, (event) => {
580
+ if (OPEN_KEYS$1.includes(event.key)) {
581
+ handleOpen();
582
+ event.preventDefault();
583
+ }
584
+ }),
585
+ children: children || "▼"
586
+ }
587
+ );
588
+ });
589
+ ComboboxIcon.displayName = "ComboboxIcon";
590
+ const PORTAL_NAME$1 = "ComboboxPortal";
591
+ const ComboboxPortal = (props) => {
592
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPortal.Portal, { asChild: true, ...props });
593
+ };
594
+ ComboboxPortal.displayName = PORTAL_NAME$1;
595
+ const CONTENT_NAME$1 = "ComboboxContent";
596
+ const ComboboxContent = React__namespace.forwardRef((props, forwardedRef) => {
597
+ const context = useComboboxContext(CONTENT_NAME$1);
598
+ const { getItems } = useCollection$1(void 0);
599
+ const [fragment, setFragment] = React__namespace.useState();
600
+ reactUseLayoutEffect.useLayoutEffect(() => {
601
+ setFragment(new DocumentFragment());
602
+ }, []);
603
+ reactUseLayoutEffect.useLayoutEffect(() => {
604
+ if (context.open && context.autocomplete.type === "none") {
605
+ setTimeout(() => {
606
+ const activeItem = getItems().find((item) => item.value === context.value);
607
+ activeItem?.ref.current?.scrollIntoView({ block: "nearest" });
608
+ });
609
+ }
610
+ }, [getItems, context.autocomplete, context.value, context.open]);
611
+ if (!context.open) {
612
+ const frag = fragment;
613
+ return frag ? ReactDOM__namespace.createPortal(
614
+ /* @__PURE__ */ jsxRuntime.jsx(Collection$1.Slot, { scope: void 0, children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: props.children }) }),
615
+ frag
616
+ ) : null;
617
+ }
618
+ return /* @__PURE__ */ jsxRuntime.jsx(ComboboxContentImpl, { ...props, ref: forwardedRef });
619
+ });
620
+ ComboboxContent.displayName = CONTENT_NAME$1;
621
+ const CONTENT_MARGIN$1 = 10;
622
+ const ComboboxContentImpl = React__namespace.forwardRef(
623
+ (props, forwardedRef) => {
624
+ const { onEscapeKeyDown, onPointerDownOutside, ...contentProps } = props;
625
+ const context = useComboboxContext(CONTENT_NAME$1);
626
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, (node) => context.onContentChange(node));
627
+ const { onOpenChange } = context;
628
+ reactFocusGuards.useFocusGuards();
629
+ React__namespace.useEffect(() => {
630
+ const close = () => {
631
+ onOpenChange(false);
632
+ };
633
+ window.addEventListener("blur", close);
634
+ window.addEventListener("resize", close);
635
+ return () => {
636
+ window.removeEventListener("blur", close);
637
+ window.removeEventListener("resize", close);
638
+ };
639
+ }, [onOpenChange]);
640
+ return /* @__PURE__ */ jsxRuntime.jsx(reactRemoveScroll.RemoveScroll, { allowPinchZoom: true, children: /* @__PURE__ */ jsxRuntime.jsx(
641
+ reactDismissableLayer.DismissableLayer,
642
+ {
643
+ asChild: true,
644
+ onEscapeKeyDown,
645
+ onPointerDownOutside,
646
+ onFocusOutside: (event) => {
647
+ event.preventDefault();
648
+ },
649
+ onDismiss: () => {
650
+ context.onOpenChange(false);
651
+ context.trigger?.focus({ preventScroll: true });
652
+ },
653
+ children: /* @__PURE__ */ jsxRuntime.jsx(
654
+ ComboboxPopperPosition,
655
+ {
656
+ role: "listbox",
657
+ id: context.contentId,
658
+ "data-state": context.open ? "open" : "closed",
659
+ onContextMenu: (event) => event.preventDefault(),
660
+ ...contentProps,
661
+ ref: composedRefs,
662
+ style: {
663
+ // flex layout so we can place the scroll buttons properly
664
+ display: "flex",
665
+ flexDirection: "column",
666
+ // reset the outline by default as the content MAY get focused
667
+ outline: "none",
668
+ ...contentProps.style
669
+ }
670
+ }
671
+ )
672
+ }
673
+ ) });
674
+ }
675
+ );
676
+ ComboboxContentImpl.displayName = "ComboboxContentImpl";
677
+ const ComboboxPopperPosition = React__namespace.forwardRef(
678
+ (props, forwardedRef) => {
679
+ const { align = "start", collisionPadding = CONTENT_MARGIN$1, ...popperProps } = props;
680
+ return /* @__PURE__ */ jsxRuntime.jsx(
681
+ PopperPrimitive__namespace.Content,
682
+ {
683
+ ...popperProps,
684
+ ref: forwardedRef,
685
+ align,
686
+ collisionPadding,
687
+ style: {
688
+ // Ensure border-box for floating-ui calculations
689
+ boxSizing: "border-box",
690
+ ...popperProps.style,
691
+ // re-namespace exposed content custom properties
692
+ ...{
693
+ "--radix-combobox-content-transform-origin": "var(--radix-popper-transform-origin)",
694
+ "--radix-combobox-content-available-width": "var(--radix-popper-available-width)",
695
+ "--radix-combobox-content-available-height": "var(--radix-popper-available-height)",
696
+ "--radix-combobox-trigger-width": "var(--radix-popper-anchor-width)",
697
+ "--radix-combobox-trigger-height": "var(--radix-popper-anchor-height)"
698
+ }
699
+ }
700
+ }
701
+ );
702
+ }
703
+ );
704
+ ComboboxPopperPosition.displayName = "ComboboxPopperPosition";
705
+ const VIEWPORT_NAME$1 = "ComboboxViewport";
706
+ const ComboboxViewport = React__namespace.forwardRef((props, forwardedRef) => {
707
+ const comboboxContext = useComboboxContext(VIEWPORT_NAME$1);
708
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, comboboxContext.onViewportChange);
709
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
710
+ /* @__PURE__ */ jsxRuntime.jsx(
711
+ "style",
712
+ {
713
+ dangerouslySetInnerHTML: {
714
+ __html: `[data-radix-combobox-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-combobox-viewport]::-webkit-scrollbar{display:none}`
715
+ }
716
+ }
717
+ ),
718
+ /* @__PURE__ */ jsxRuntime.jsx(Collection$1.Slot, { scope: void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
719
+ reactPrimitive.Primitive.div,
720
+ {
721
+ "data-radix-combobox-viewport": "",
722
+ role: "presentation",
723
+ ...props,
724
+ ref: composedRefs,
725
+ style: {
726
+ // we use position: 'relative' here on the `viewport` so that when we call
727
+ // `selectedItem.offsetTop` in calculations, the offset is relative to the viewport
728
+ // (independent of the scrollUpButton).
729
+ position: "relative",
730
+ flex: 1,
731
+ overflow: "auto",
732
+ ...props.style
733
+ }
734
+ }
735
+ ) })
736
+ ] });
737
+ });
738
+ ComboboxViewport.displayName = VIEWPORT_NAME$1;
739
+ const ITEM_NAME$1 = "ComboboxItem";
740
+ const [ComboboxItemProvider, useComboboxItemContext] = reactContext.createContext(ITEM_NAME$1);
741
+ const ComboboxItem = React__namespace.forwardRef((props, forwardedRef) => {
742
+ const { value, disabled = false, textValue: textValueProp, ...restProps } = props;
743
+ const [fragment, setFragment] = React__namespace.useState();
744
+ reactUseLayoutEffect.useLayoutEffect(() => {
745
+ setFragment(new DocumentFragment());
746
+ }, []);
747
+ const { onTextValueChange, textValue: contextTextValue, ...context } = useComboboxContext(ITEM_NAME$1);
748
+ const textId = reactId.useId();
749
+ const [textValue, setTextValue] = React__namespace.useState(textValueProp ?? "");
750
+ const isSelected = context.value === value;
751
+ const { startsWith, contains } = useFilter(context.locale, { sensitivity: "base" });
752
+ const handleTextValueChange = React__namespace.useCallback((node) => {
753
+ setTextValue((prevTextValue) => {
754
+ return prevTextValue || (node?.textContent ?? "").trim();
755
+ });
756
+ }, []);
757
+ React__namespace.useEffect(() => {
758
+ if (isSelected && contextTextValue === void 0 && textValue !== "") {
759
+ onTextValueChange(textValue);
760
+ }
761
+ }, [textValue, isSelected, contextTextValue, onTextValueChange]);
762
+ if (context.autocomplete.type === "both" && textValue && context.filterValue && !startsWith(textValue, context.filterValue) || context.autocomplete.type === "list" && context.autocomplete.filter === "startsWith" && textValue && contextTextValue && !startsWith(textValue, contextTextValue) || context.autocomplete.type === "list" && context.autocomplete.filter === "contains" && textValue && contextTextValue && !contains(textValue, contextTextValue)) {
763
+ return fragment ? ReactDOM__namespace.createPortal(
764
+ /* @__PURE__ */ jsxRuntime.jsx(
765
+ ComboboxItemProvider,
766
+ {
767
+ textId,
768
+ onTextValueChange: handleTextValueChange,
769
+ isSelected,
770
+ textValue,
771
+ children: /* @__PURE__ */ jsxRuntime.jsx(
772
+ Collection$1.ItemSlot,
773
+ {
774
+ scope: void 0,
775
+ value,
776
+ textValue,
777
+ disabled,
778
+ type: "option",
779
+ isVisible: false,
780
+ children: /* @__PURE__ */ jsxRuntime.jsx(ComboboxItemImpl, { ref: forwardedRef, value, disabled, ...restProps })
781
+ }
782
+ )
783
+ }
784
+ ),
785
+ fragment
786
+ ) : null;
787
+ }
788
+ return /* @__PURE__ */ jsxRuntime.jsx(
789
+ ComboboxItemProvider,
790
+ {
791
+ textId,
792
+ onTextValueChange: handleTextValueChange,
793
+ isSelected,
794
+ textValue,
795
+ children: /* @__PURE__ */ jsxRuntime.jsx(
796
+ Collection$1.ItemSlot,
797
+ {
798
+ scope: void 0,
799
+ value,
800
+ textValue,
801
+ disabled,
802
+ type: "option",
803
+ isVisible: true,
804
+ children: /* @__PURE__ */ jsxRuntime.jsx(ComboboxItemImpl, { ref: forwardedRef, value, disabled, ...restProps })
805
+ }
806
+ )
807
+ }
808
+ );
809
+ });
810
+ ComboboxItem.displayName = ITEM_NAME$1;
811
+ const ITEM_IMPL_NAME = "ComboboxItemImpl";
812
+ const ComboboxItemImpl = React__namespace.forwardRef((props, forwardedRef) => {
813
+ const { value, disabled = false, ...restProps } = props;
814
+ const itemRef = React__namespace.useRef(null);
815
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, itemRef);
816
+ const { getItems } = useCollection$1(void 0);
817
+ const { onTextValueChange, visuallyFocussedItem, ...context } = useComboboxContext(ITEM_NAME$1);
818
+ const { isSelected, textValue, textId } = useComboboxItemContext(ITEM_IMPL_NAME);
819
+ const handleSelect = () => {
820
+ if (!disabled) {
821
+ context.onValueChange(value);
822
+ onTextValueChange(textValue);
823
+ context.onOpenChange(false);
824
+ if (context.autocomplete.type === "both") {
825
+ context.onFilterValueChange(textValue);
826
+ }
827
+ context.trigger?.focus({ preventScroll: true });
828
+ }
829
+ };
830
+ const isFocused = React__namespace.useMemo(() => {
831
+ return visuallyFocussedItem === getItems().find((item) => item.ref.current === itemRef.current)?.ref.current;
832
+ }, [getItems, visuallyFocussedItem]);
833
+ const id = reactId.useId();
834
+ return /* @__PURE__ */ jsxRuntime.jsx(
835
+ reactPrimitive.Primitive.div,
836
+ {
837
+ role: "option",
838
+ "aria-labelledby": textId,
839
+ "data-highlighted": isFocused ? "" : void 0,
840
+ "aria-selected": isSelected && isFocused,
841
+ "data-state": isSelected ? "checked" : "unchecked",
842
+ "aria-disabled": disabled || void 0,
843
+ "data-disabled": disabled ? "" : void 0,
844
+ tabIndex: disabled ? void 0 : -1,
845
+ ...restProps,
846
+ id,
847
+ ref: composedRefs,
848
+ onPointerUp: primitive.composeEventHandlers(restProps.onPointerUp, handleSelect)
849
+ }
850
+ );
851
+ });
852
+ ComboboxItemImpl.displayName = ITEM_IMPL_NAME;
853
+ const ITEM_TEXT_NAME$1 = "ComboboxItemText";
854
+ const ComboboxItemText = React__namespace.forwardRef((props, forwardedRef) => {
855
+ const { className: _unusedClassName, style: _unusedStyle, ...itemTextProps } = props;
856
+ const itemContext = useComboboxItemContext(ITEM_TEXT_NAME$1);
857
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, itemContext.onTextValueChange);
858
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.span, { id: itemContext.textId, ...itemTextProps, ref: composedRefs });
859
+ });
860
+ ComboboxItemText.displayName = ITEM_TEXT_NAME$1;
861
+ const ITEM_INDICATOR_NAME$1 = "ComboboxItemIndicator";
862
+ const ComboboxItemIndicator = React__namespace.forwardRef((props, forwardedRef) => {
863
+ const { isSelected } = useComboboxItemContext(ITEM_INDICATOR_NAME$1);
864
+ return isSelected ? /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.span, { "aria-hidden": true, ...props, ref: forwardedRef }) : null;
865
+ });
866
+ ComboboxItemIndicator.displayName = ITEM_INDICATOR_NAME$1;
867
+ const NO_VALUE_FOUND_NAME = "ComboboxNoValueFound";
868
+ const ComboboxNoValueFound = React__namespace.forwardRef((props, ref) => {
869
+ const { textValue = "", filterValue = "", locale, autocomplete } = useComboboxContext(NO_VALUE_FOUND_NAME);
870
+ const [items, setItems] = React__namespace.useState([]);
871
+ const { subscribe } = useCollection$1(void 0);
872
+ const { startsWith, contains } = useFilter(locale, { sensitivity: "base" });
873
+ React__namespace.useEffect(() => {
874
+ const unsub = subscribe((state) => {
875
+ setItems(state);
876
+ });
877
+ return () => {
878
+ unsub();
879
+ };
880
+ }, [subscribe]);
881
+ if (items.length === 0)
882
+ return null;
883
+ if (autocomplete.type === "none") {
884
+ return null;
885
+ }
886
+ if (autocomplete.type === "list" && autocomplete.filter === "startsWith" && items.some((item) => startsWith(item.textValue, textValue))) {
887
+ return null;
888
+ }
889
+ if (autocomplete.type === "both" && items.some((item) => startsWith(item.textValue, filterValue))) {
890
+ return null;
891
+ }
892
+ if (autocomplete.type === "list" && autocomplete.filter === "contains" && items.some((item) => contains(item.textValue, textValue))) {
893
+ return null;
894
+ }
895
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.div, { ...props, ref });
896
+ });
897
+ ComboboxNoValueFound.displayName = NO_VALUE_FOUND_NAME;
898
+ const ComboboxCreateItem = React__namespace.forwardRef((props, ref) => {
899
+ const { disabled = false, ...restProps } = props;
900
+ const context = useComboboxContext(NO_VALUE_FOUND_NAME);
901
+ const { textValue, visuallyFocussedItem } = context;
902
+ const { getItems, subscribe } = useCollection$1(void 0);
903
+ const itemRef = React__namespace.useRef(null);
904
+ const [show, setShow] = React__namespace.useState(false);
905
+ const composedRefs = reactComposeRefs.useComposedRefs(ref, itemRef);
906
+ const isFocused = React__namespace.useMemo(() => {
907
+ return visuallyFocussedItem === getItems().find((item) => item.ref.current === itemRef.current)?.ref.current;
908
+ }, [getItems, visuallyFocussedItem]);
909
+ const id = reactId.useId();
910
+ const handleSelect = () => {
911
+ if (!disabled && textValue) {
912
+ context.onValueChange(textValue);
913
+ context.onTextValueChange(textValue);
914
+ context.onOpenChange(false);
915
+ if (context.autocomplete.type === "both") {
916
+ context.onFilterValueChange(textValue);
917
+ }
918
+ context.trigger?.focus({ preventScroll: true });
919
+ }
920
+ };
921
+ reactUseLayoutEffect.useLayoutEffect(() => {
922
+ const unsub = subscribe((state) => {
923
+ setShow(!state.some((item) => item.textValue === textValue && item.type !== "create"));
924
+ });
925
+ if (getItems().length === 0) {
926
+ setShow(true);
927
+ }
928
+ return () => {
929
+ unsub();
930
+ };
931
+ }, [textValue, subscribe, getItems]);
932
+ if (!textValue || !show) {
933
+ return null;
934
+ }
935
+ return /* @__PURE__ */ jsxRuntime.jsx(
936
+ Collection$1.ItemSlot,
937
+ {
938
+ scope: void 0,
939
+ value: textValue ?? "",
940
+ textValue: textValue ?? "",
941
+ disabled,
942
+ isVisible: true,
943
+ type: "create",
944
+ children: /* @__PURE__ */ jsxRuntime.jsx(
945
+ reactPrimitive.Primitive.div,
946
+ {
947
+ role: "option",
948
+ tabIndex: disabled ? void 0 : -1,
949
+ "aria-disabled": disabled || void 0,
950
+ "data-disabled": disabled ? "" : void 0,
951
+ "data-highlighted": isFocused ? "" : void 0,
952
+ ...restProps,
953
+ id,
954
+ ref: composedRefs,
955
+ onPointerUp: primitive.composeEventHandlers(restProps.onPointerUp, handleSelect)
956
+ }
957
+ )
958
+ }
959
+ );
960
+ });
961
+ ComboboxCreateItem.displayName = "ComboboxCreateItem";
962
+ const Root$1 = Combobox;
963
+ const Trigger$1 = ComboboxTrigger;
964
+ const TextInput = ComboxboxTextInput;
965
+ const Icon$1 = ComboboxIcon;
966
+ const Portal$1 = ComboboxPortal;
967
+ const Content$1 = ComboboxContent;
968
+ const Viewport$1 = ComboboxViewport;
969
+ const Item$1 = ComboboxItem;
970
+ const ItemText$1 = ComboboxItemText;
971
+ const ItemIndicator$1 = ComboboxItemIndicator;
972
+ const NoValueFound = ComboboxNoValueFound;
973
+ const CreateItem = ComboboxCreateItem;
974
+ function findChangedIndex(a, b) {
975
+ const length = Math.min(a.length, b.length);
976
+ for (let i = 0; i < length; i++) {
977
+ if (a[i] !== b[i]) {
978
+ return i;
979
+ }
980
+ }
981
+ return length;
982
+ }
983
+ const Combobox$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
984
+ __proto__: null,
985
+ ComboboxItem,
986
+ Content: Content$1,
987
+ CreateItem,
988
+ Icon: Icon$1,
989
+ Item: Item$1,
990
+ ItemIndicator: ItemIndicator$1,
991
+ ItemText: ItemText$1,
992
+ NoValueFound,
993
+ Portal: Portal$1,
994
+ Root: Root$1,
995
+ TextInput,
996
+ Trigger: Trigger$1,
997
+ Viewport: Viewport$1
998
+ }, Symbol.toStringTag, { value: "Module" }));
999
+ const OPEN_KEYS = [" ", "Enter", "ArrowUp", "ArrowDown"];
1000
+ const SELECTION_KEYS = [" ", "Enter"];
1001
+ const SELECT_NAME = "Select";
1002
+ const [Collection, useCollection, createCollectionScope] = reactCollection.createCollection(SELECT_NAME);
1003
+ const [createSelectContext, createSelectScope] = reactContext.createContextScope(SELECT_NAME, [
1004
+ createCollectionScope,
1005
+ PopperPrimitive.createPopperScope
1006
+ ]);
1007
+ const usePopperScope = PopperPrimitive.createPopperScope();
1008
+ const [SelectProvider, useSelectContext] = createSelectContext(SELECT_NAME);
1009
+ const [SelectNativeOptionsProvider, useSelectNativeOptionsContext] = createSelectContext(SELECT_NAME);
1010
+ const Select = (props) => {
1011
+ const {
1012
+ __scopeSelect,
1013
+ children,
1014
+ open: openProp,
1015
+ defaultOpen,
1016
+ onOpenChange,
1017
+ value: valueProp,
1018
+ defaultValue,
1019
+ onValueChange,
1020
+ dir,
1021
+ // name,
1022
+ // autoComplete,
1023
+ disabled,
1024
+ required,
1025
+ multi = false
1026
+ } = props;
1027
+ const popperScope = usePopperScope(__scopeSelect);
1028
+ const [trigger, setTrigger] = React__namespace.useState(null);
1029
+ const [valueNode, setValueNode] = React__namespace.useState(null);
1030
+ const [valueNodeHasChildren, setValueNodeHasChildren] = React__namespace.useState(false);
1031
+ const direction = reactDirection.useDirection(dir);
1032
+ const [open = false, setOpen] = reactUseControllableState.useControllableState({
1033
+ prop: openProp,
1034
+ defaultProp: defaultOpen,
1035
+ onChange: onOpenChange
1036
+ });
1037
+ const [value, setValue] = reactUseControllableState.useControllableState({
1038
+ prop: valueProp,
1039
+ defaultProp: defaultValue,
1040
+ onChange(value2) {
1041
+ if (onValueChange) {
1042
+ if (Array.isArray(value2)) {
1043
+ onValueChange(value2);
1044
+ } else {
1045
+ onValueChange(value2);
1046
+ }
1047
+ }
1048
+ }
1049
+ });
1050
+ const triggerPointerDownPosRef = React__namespace.useRef(null);
1051
+ const [_nativeOptionsSet, setNativeOptionsSet] = React__namespace.useState(/* @__PURE__ */ new Set());
1052
+ return /* @__PURE__ */ jsxRuntime.jsx(PopperPrimitive__namespace.Root, { ...popperScope, children: /* @__PURE__ */ jsxRuntime.jsx(
1053
+ SelectProvider,
1054
+ {
1055
+ required,
1056
+ scope: __scopeSelect,
1057
+ trigger,
1058
+ onTriggerChange: setTrigger,
1059
+ valueNode,
1060
+ onValueNodeChange: setValueNode,
1061
+ valueNodeHasChildren,
1062
+ onValueNodeHasChildrenChange: setValueNodeHasChildren,
1063
+ contentId: reactId.useId(),
1064
+ value,
1065
+ onValueChange: setValue,
1066
+ open,
1067
+ onOpenChange: setOpen,
1068
+ dir: direction,
1069
+ triggerPointerDownPosRef,
1070
+ disabled,
1071
+ multi,
1072
+ children: /* @__PURE__ */ jsxRuntime.jsx(Collection.Provider, { scope: __scopeSelect, children: /* @__PURE__ */ jsxRuntime.jsx(
1073
+ SelectNativeOptionsProvider,
1074
+ {
1075
+ scope: props.__scopeSelect,
1076
+ onNativeOptionAdd: React__namespace.useCallback((option) => {
1077
+ setNativeOptionsSet((prev) => new Set(prev).add(option));
1078
+ }, []),
1079
+ onNativeOptionRemove: React__namespace.useCallback((option) => {
1080
+ setNativeOptionsSet((prev) => {
1081
+ const optionsSet = new Set(prev);
1082
+ optionsSet.delete(option);
1083
+ return optionsSet;
1084
+ });
1085
+ }, []),
1086
+ children
1087
+ }
1088
+ ) })
1089
+ }
1090
+ ) });
1091
+ };
1092
+ Select.displayName = SELECT_NAME;
1093
+ const TRIGGER_NAME = "SelectTrigger";
1094
+ const SelectTrigger = React__namespace.forwardRef(
1095
+ (props, forwardedRef) => {
1096
+ const { __scopeSelect, ...triggerProps } = props;
1097
+ const popperScope = usePopperScope(__scopeSelect);
1098
+ const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
1099
+ const isDisabled = context.disabled;
1100
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, context.onTriggerChange);
1101
+ const getItems = useCollection(__scopeSelect);
1102
+ const [searchRef, handleTypeaheadSearch, resetTypeahead] = useTypeaheadSearch((search) => {
1103
+ const enabledItems = getItems().filter((item) => !item.disabled);
1104
+ const currentItem = enabledItems.find((item) => item.value === context.value);
1105
+ const nextItem = findNextItem(enabledItems, search, currentItem);
1106
+ if (nextItem !== void 0 && !Array.isArray(nextItem.value)) {
1107
+ const newValue = context.multi ? [nextItem.value] : nextItem.value;
1108
+ context.onValueChange(newValue);
1109
+ }
1110
+ });
1111
+ const handleOpen = () => {
1112
+ if (!isDisabled) {
1113
+ context.onOpenChange(true);
1114
+ resetTypeahead();
1115
+ }
1116
+ };
1117
+ return /* @__PURE__ */ jsxRuntime.jsx(PopperPrimitive__namespace.Anchor, { asChild: true, ...popperScope, children: /* @__PURE__ */ jsxRuntime.jsx(
1118
+ reactPrimitive.Primitive.div,
1119
+ {
1120
+ role: "combobox",
1121
+ "aria-controls": context.contentId,
1122
+ "aria-expanded": context.open,
1123
+ "aria-required": context.required,
1124
+ "aria-autocomplete": "none",
1125
+ dir: context.dir,
1126
+ "data-state": context.open ? "open" : "closed",
1127
+ "data-disabled": isDisabled ? "" : void 0,
1128
+ "data-placeholder": context.value === void 0 ? "" : void 0,
1129
+ tabIndex: isDisabled ? void 0 : 0,
1130
+ ...triggerProps,
1131
+ ref: composedRefs,
1132
+ onClick: primitive.composeEventHandlers(triggerProps.onClick, (event) => {
1133
+ event.currentTarget.focus();
1134
+ }),
1135
+ onPointerDown: primitive.composeEventHandlers(triggerProps.onPointerDown, (event) => {
1136
+ const target = event.target;
1137
+ if (target.hasPointerCapture(event.pointerId)) {
1138
+ target.releasePointerCapture(event.pointerId);
1139
+ }
1140
+ const buttonTarg = target.closest("button") ?? target.closest("div");
1141
+ if (buttonTarg !== event.currentTarget) {
1142
+ return;
1143
+ }
1144
+ if (event.button === 0 && event.ctrlKey === false) {
1145
+ handleOpen();
1146
+ context.triggerPointerDownPosRef.current = {
1147
+ x: Math.round(event.pageX),
1148
+ y: Math.round(event.pageY)
1149
+ };
1150
+ event.preventDefault();
1151
+ }
1152
+ }),
1153
+ onKeyDown: primitive.composeEventHandlers(triggerProps.onKeyDown, (event) => {
1154
+ const isTypingAhead = searchRef.current !== "";
1155
+ const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
1156
+ const target = event.target;
1157
+ const buttonTarg = target.closest("button") ?? target.closest("div");
1158
+ if (buttonTarg !== event.currentTarget) {
1159
+ return;
1160
+ }
1161
+ if (!isModifierKey && event.key.length === 1)
1162
+ handleTypeaheadSearch(event.key);
1163
+ if (isTypingAhead && event.key === " ")
1164
+ return;
1165
+ if (OPEN_KEYS.includes(event.key)) {
1166
+ handleOpen();
1167
+ event.preventDefault();
1168
+ }
1169
+ })
1170
+ }
1171
+ ) });
1172
+ }
1173
+ );
1174
+ SelectTrigger.displayName = TRIGGER_NAME;
1175
+ const VALUE_NAME = "SelectValue";
1176
+ const SelectValue = React__namespace.forwardRef(
1177
+ (props, forwardedRef) => {
1178
+ const { __scopeSelect, children, placeholder, ...valueProps } = props;
1179
+ const context = useSelectContext(VALUE_NAME, __scopeSelect);
1180
+ const { onValueNodeHasChildrenChange } = context;
1181
+ const hasChildren = children !== void 0;
1182
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, context.onValueNodeChange);
1183
+ const [valuedItems, setValuedItems] = React__namespace.useState([]);
1184
+ const getItems = useCollection(__scopeSelect);
1185
+ reactUseLayoutEffect.useLayoutEffect(() => {
1186
+ onValueNodeHasChildrenChange(hasChildren);
1187
+ }, [onValueNodeHasChildrenChange, hasChildren]);
1188
+ React__namespace.useLayoutEffect(() => {
1189
+ if (Array.isArray(context.value) && valuedItems.length !== context.value.length) {
1190
+ const timeout = setTimeout(() => {
1191
+ const valuedItems2 = getItems().filter(
1192
+ (item) => !Array.isArray(item.value) ? context.value?.includes(item.value) : false
1193
+ );
1194
+ setValuedItems(valuedItems2);
1195
+ });
1196
+ return () => {
1197
+ clearTimeout(timeout);
1198
+ };
1199
+ }
1200
+ }, [context.value, getItems, valuedItems]);
1201
+ let renderValue;
1202
+ if ((context.value === void 0 || context.value.length === 0) && placeholder !== void 0) {
1203
+ renderValue = /* @__PURE__ */ jsxRuntime.jsx("span", { children: placeholder });
1204
+ } else if (typeof children === "function") {
1205
+ if (Array.isArray(context.value)) {
1206
+ const childrenArray = context.value.map((value) => {
1207
+ const valueItem = valuedItems.find((item) => item.value === value);
1208
+ if (!valueItem) {
1209
+ return null;
1210
+ }
1211
+ return children({ value, textValue: valueItem?.textValue });
1212
+ });
1213
+ renderValue = childrenArray.every((child) => child === null) ? placeholder : childrenArray;
1214
+ } else {
1215
+ renderValue = children(context.value);
1216
+ }
1217
+ } else {
1218
+ renderValue = children;
1219
+ }
1220
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.span, { ...valueProps, ref: composedRefs, children: renderValue || null });
1221
+ }
1222
+ );
1223
+ SelectValue.displayName = VALUE_NAME;
1224
+ const ICON_NAME = "SelectIcon";
1225
+ const SelectIcon = React__namespace.forwardRef(
1226
+ (props, forwardedRef) => {
1227
+ const { __scopeSelect, children, ...iconProps } = props;
1228
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.span, { "aria-hidden": true, ...iconProps, ref: forwardedRef, children: children || "▼" });
1229
+ }
1230
+ );
1231
+ SelectIcon.displayName = ICON_NAME;
1232
+ const PORTAL_NAME = "SelectPortal";
1233
+ const SelectPortal = (props) => {
1234
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPortal.Portal, { asChild: true, ...props });
1235
+ };
1236
+ SelectPortal.displayName = PORTAL_NAME;
1237
+ const CONTENT_NAME = "SelectContent";
1238
+ const SelectContent = React__namespace.forwardRef(
1239
+ (props, forwardedRef) => {
1240
+ const context = useSelectContext(CONTENT_NAME, props.__scopeSelect);
1241
+ const [fragment, setFragment] = React__namespace.useState();
1242
+ reactUseLayoutEffect.useLayoutEffect(() => {
1243
+ setFragment(new DocumentFragment());
1244
+ }, []);
1245
+ if (!context.open) {
1246
+ const frag = fragment;
1247
+ return frag ? ReactDOM__namespace.createPortal(
1248
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContentProvider, { scope: props.__scopeSelect, children: /* @__PURE__ */ jsxRuntime.jsx(Collection.Slot, { scope: props.__scopeSelect, children: /* @__PURE__ */ jsxRuntime.jsx("div", { children: props.children }) }) }),
1249
+ frag
1250
+ ) : null;
1251
+ }
1252
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectContentImpl, { ...props, ref: forwardedRef });
1253
+ }
1254
+ );
1255
+ SelectContent.displayName = CONTENT_NAME;
1256
+ const CONTENT_MARGIN = 10;
1257
+ const [SelectContentProvider, useSelectContentContext] = createSelectContext(CONTENT_NAME);
1258
+ const CONTENT_IMPL_NAME = "SelectContentImpl";
1259
+ const SelectContentImpl = React__namespace.forwardRef(
1260
+ (props, forwardedRef) => {
1261
+ const {
1262
+ __scopeSelect,
1263
+ position = "item-aligned",
1264
+ onCloseAutoFocus,
1265
+ onEscapeKeyDown,
1266
+ onPointerDownOutside,
1267
+ //
1268
+ // PopperContent props
1269
+ side,
1270
+ sideOffset,
1271
+ align,
1272
+ alignOffset,
1273
+ arrowPadding,
1274
+ collisionBoundary,
1275
+ collisionPadding,
1276
+ sticky,
1277
+ hideWhenDetached,
1278
+ avoidCollisions,
1279
+ //
1280
+ ...contentProps
1281
+ } = props;
1282
+ const context = useSelectContext(CONTENT_NAME, __scopeSelect);
1283
+ const [content, setContent] = React__namespace.useState(null);
1284
+ const [viewport, setViewport] = React__namespace.useState(null);
1285
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, (node) => setContent(node));
1286
+ const [selectedItem, setSelectedItem] = React__namespace.useState(null);
1287
+ const [selectedItemText, setSelectedItemText] = React__namespace.useState(null);
1288
+ const getItems = useCollection(__scopeSelect);
1289
+ const [isPositioned, setIsPositioned] = React__namespace.useState(false);
1290
+ const firstValidItemFoundRef = React__namespace.useRef(false);
1291
+ React__namespace.useEffect(() => {
1292
+ if (content)
1293
+ return ariaHidden.hideOthers(content);
1294
+ }, [content]);
1295
+ reactFocusGuards.useFocusGuards();
1296
+ const focusFirst = React__namespace.useCallback(
1297
+ (candidates) => {
1298
+ const [firstItem, ...restItems] = getItems().map((item) => item.ref.current);
1299
+ const [lastItem] = restItems.slice(-1);
1300
+ const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
1301
+ for (const candidate of candidates) {
1302
+ if (candidate === PREVIOUSLY_FOCUSED_ELEMENT)
1303
+ return;
1304
+ candidate?.scrollIntoView({ block: "nearest" });
1305
+ if (candidate === firstItem && viewport)
1306
+ viewport.scrollTop = 0;
1307
+ if (candidate === lastItem && viewport)
1308
+ viewport.scrollTop = viewport.scrollHeight;
1309
+ candidate?.focus();
1310
+ if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT)
1311
+ return;
1312
+ }
1313
+ },
1314
+ [getItems, viewport]
1315
+ );
1316
+ const focusSelectedItem = React__namespace.useCallback(
1317
+ () => focusFirst([selectedItem, content]),
1318
+ [focusFirst, selectedItem, content]
1319
+ );
1320
+ React__namespace.useEffect(() => {
1321
+ if (isPositioned) {
1322
+ focusSelectedItem();
1323
+ }
1324
+ }, [isPositioned, focusSelectedItem]);
1325
+ const { onOpenChange, triggerPointerDownPosRef } = context;
1326
+ React__namespace.useEffect(() => {
1327
+ if (content) {
1328
+ let pointerMoveDelta = { x: 0, y: 0 };
1329
+ const handlePointerMove = (event) => {
1330
+ pointerMoveDelta = {
1331
+ x: Math.abs(Math.round(event.pageX) - (triggerPointerDownPosRef.current?.x ?? 0)),
1332
+ y: Math.abs(Math.round(event.pageY) - (triggerPointerDownPosRef.current?.y ?? 0))
1333
+ };
1334
+ };
1335
+ const handlePointerUp = (event) => {
1336
+ if (pointerMoveDelta.x <= 10 && pointerMoveDelta.y <= 10) {
1337
+ event.preventDefault();
1338
+ } else if (!content.contains(event.target)) {
1339
+ onOpenChange(false);
1340
+ }
1341
+ document.removeEventListener("pointermove", handlePointerMove);
1342
+ triggerPointerDownPosRef.current = null;
1343
+ };
1344
+ if (triggerPointerDownPosRef.current !== null) {
1345
+ document.addEventListener("pointermove", handlePointerMove);
1346
+ document.addEventListener("pointerup", handlePointerUp, { capture: true, once: true });
1347
+ }
1348
+ return () => {
1349
+ document.removeEventListener("pointermove", handlePointerMove);
1350
+ document.removeEventListener("pointerup", handlePointerUp, { capture: true });
1351
+ };
1352
+ }
1353
+ }, [content, onOpenChange, triggerPointerDownPosRef]);
1354
+ React__namespace.useEffect(() => {
1355
+ const close = () => onOpenChange(false);
1356
+ window.addEventListener("blur", close);
1357
+ window.addEventListener("resize", close);
1358
+ return () => {
1359
+ window.removeEventListener("blur", close);
1360
+ window.removeEventListener("resize", close);
1361
+ };
1362
+ }, [onOpenChange]);
1363
+ const [searchRef, handleTypeaheadSearch] = useTypeaheadSearch((search) => {
1364
+ const enabledItems = getItems().filter((item) => !item.disabled);
1365
+ const currentItem = enabledItems.find((item) => item.ref.current === document.activeElement);
1366
+ const nextItem = findNextItem(enabledItems, search, currentItem);
1367
+ if (nextItem) {
1368
+ setTimeout(() => nextItem.ref.current.focus());
1369
+ }
1370
+ });
1371
+ const itemRefCallback = React__namespace.useCallback(
1372
+ (node, value, disabled) => {
1373
+ const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
1374
+ const isSelectedItem = context.value !== void 0 && context.value === value;
1375
+ if (isSelectedItem || isFirstValidItem) {
1376
+ setSelectedItem(node);
1377
+ if (isFirstValidItem)
1378
+ firstValidItemFoundRef.current = true;
1379
+ }
1380
+ },
1381
+ [context.value]
1382
+ );
1383
+ const handleItemLeave = React__namespace.useCallback(() => content?.focus(), [content]);
1384
+ const itemTextRefCallback = React__namespace.useCallback(
1385
+ (node, value, disabled) => {
1386
+ const isFirstValidItem = !firstValidItemFoundRef.current && !disabled;
1387
+ const isSelectedItem = context.value !== void 0 && (Array.isArray(value) ? value.every((v) => context.value?.includes(v)) : context.value === value);
1388
+ if (isSelectedItem || isFirstValidItem) {
1389
+ setSelectedItemText(node);
1390
+ }
1391
+ },
1392
+ [context.value]
1393
+ );
1394
+ const SelectPosition = position === "popper" ? SelectPopperPosition : SelectItemAlignedPosition;
1395
+ const popperContentProps = SelectPosition === SelectPopperPosition ? {
1396
+ side,
1397
+ sideOffset,
1398
+ align,
1399
+ alignOffset,
1400
+ arrowPadding,
1401
+ collisionBoundary,
1402
+ collisionPadding,
1403
+ sticky,
1404
+ hideWhenDetached,
1405
+ avoidCollisions
1406
+ } : {};
1407
+ return /* @__PURE__ */ jsxRuntime.jsx(
1408
+ SelectContentProvider,
1409
+ {
1410
+ scope: __scopeSelect,
1411
+ content,
1412
+ viewport,
1413
+ onViewportChange: setViewport,
1414
+ itemRefCallback,
1415
+ selectedItem,
1416
+ onItemLeave: handleItemLeave,
1417
+ itemTextRefCallback,
1418
+ focusSelectedItem,
1419
+ selectedItemText,
1420
+ position,
1421
+ isPositioned,
1422
+ searchRef,
1423
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactRemoveScroll.RemoveScroll, { as: reactSlot.Slot, allowPinchZoom: true, children: /* @__PURE__ */ jsxRuntime.jsx(
1424
+ reactFocusScope.FocusScope,
1425
+ {
1426
+ asChild: true,
1427
+ trapped: context.open,
1428
+ onMountAutoFocus: (event) => {
1429
+ event.preventDefault();
1430
+ },
1431
+ onUnmountAutoFocus: primitive.composeEventHandlers(onCloseAutoFocus, (event) => {
1432
+ context.trigger?.focus({ preventScroll: true });
1433
+ document.getSelection()?.empty();
1434
+ event.preventDefault();
1435
+ }),
1436
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1437
+ reactDismissableLayer.DismissableLayer,
1438
+ {
1439
+ asChild: true,
1440
+ disableOutsidePointerEvents: true,
1441
+ onEscapeKeyDown,
1442
+ onPointerDownOutside,
1443
+ onFocusOutside: (event) => event.preventDefault(),
1444
+ onDismiss: () => context.onOpenChange(false),
1445
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1446
+ SelectPosition,
1447
+ {
1448
+ role: "listbox",
1449
+ id: context.contentId,
1450
+ "data-state": context.open ? "open" : "closed",
1451
+ "aria-multiselectable": context.multi ? "true" : void 0,
1452
+ dir: context.dir,
1453
+ onContextMenu: (event) => event.preventDefault(),
1454
+ ...contentProps,
1455
+ ...popperContentProps,
1456
+ onPlaced: () => setIsPositioned(true),
1457
+ ref: composedRefs,
1458
+ style: {
1459
+ // flex layout so we can place the scroll buttons properly
1460
+ display: "flex",
1461
+ flexDirection: "column",
1462
+ // reset the outline by default as the content MAY get focused
1463
+ outline: "none",
1464
+ ...contentProps.style
1465
+ },
1466
+ onKeyDown: primitive.composeEventHandlers(contentProps.onKeyDown, (event) => {
1467
+ const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
1468
+ if (event.key === "Tab")
1469
+ event.preventDefault();
1470
+ if (!isModifierKey && event.key.length === 1)
1471
+ handleTypeaheadSearch(event.key);
1472
+ if (["ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) {
1473
+ const items = getItems().filter((item) => !item.disabled);
1474
+ let candidateNodes = items.map((item) => item.ref.current);
1475
+ if (["ArrowUp", "End"].includes(event.key)) {
1476
+ candidateNodes = candidateNodes.slice().reverse();
1477
+ }
1478
+ if (["ArrowUp", "ArrowDown"].includes(event.key)) {
1479
+ const currentElement = event.target;
1480
+ const currentIndex = candidateNodes.indexOf(currentElement);
1481
+ candidateNodes = candidateNodes.slice(currentIndex + 1);
1482
+ }
1483
+ setTimeout(() => focusFirst(candidateNodes));
1484
+ event.preventDefault();
1485
+ }
1486
+ })
1487
+ }
1488
+ )
1489
+ }
1490
+ )
1491
+ }
1492
+ ) })
1493
+ }
1494
+ );
1495
+ }
1496
+ );
1497
+ SelectContentImpl.displayName = CONTENT_IMPL_NAME;
1498
+ const ITEM_ALIGNED_POSITION_NAME = "SelectItemAlignedPosition";
1499
+ const SelectItemAlignedPosition = React__namespace.forwardRef(
1500
+ (props, forwardedRef) => {
1501
+ const { __scopeSelect, onPlaced, ...popperProps } = props;
1502
+ const context = useSelectContext(CONTENT_NAME, __scopeSelect);
1503
+ const contentContext = useSelectContentContext(CONTENT_NAME, __scopeSelect);
1504
+ const [contentWrapper, setContentWrapper] = React__namespace.useState(null);
1505
+ const [content, setContent] = React__namespace.useState(null);
1506
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, (node) => setContent(node));
1507
+ const getItems = useCollection(__scopeSelect);
1508
+ const shouldExpandOnScrollRef = React__namespace.useRef(false);
1509
+ const shouldRepositionRef = React__namespace.useRef(true);
1510
+ const { viewport, selectedItem, selectedItemText, focusSelectedItem } = contentContext;
1511
+ const position = React__namespace.useCallback(() => {
1512
+ if (context.trigger && context.valueNode && contentWrapper && content && viewport && selectedItem && selectedItemText) {
1513
+ const triggerRect = context.trigger.getBoundingClientRect();
1514
+ const contentRect = content.getBoundingClientRect();
1515
+ const valueNodeRect = context.valueNode.getBoundingClientRect();
1516
+ const itemTextRect = selectedItemText.getBoundingClientRect();
1517
+ if (context.dir !== "rtl") {
1518
+ const itemTextOffset = itemTextRect.left - contentRect.left;
1519
+ const left = valueNodeRect.left - itemTextOffset;
1520
+ const leftDelta = triggerRect.left - left;
1521
+ const minContentWidth = triggerRect.width + leftDelta;
1522
+ const contentWidth = Math.max(minContentWidth, contentRect.width);
1523
+ const rightEdge = window.innerWidth - CONTENT_MARGIN;
1524
+ const clampedLeft = number.clamp(left, [CONTENT_MARGIN, rightEdge - contentWidth]);
1525
+ contentWrapper.style.minWidth = `${minContentWidth}px`;
1526
+ contentWrapper.style.left = `${clampedLeft}px`;
1527
+ } else {
1528
+ const itemTextOffset = contentRect.right - itemTextRect.right;
1529
+ const right = window.innerWidth - valueNodeRect.right - itemTextOffset;
1530
+ const rightDelta = window.innerWidth - triggerRect.right - right;
1531
+ const minContentWidth = triggerRect.width + rightDelta;
1532
+ const contentWidth = Math.max(minContentWidth, contentRect.width);
1533
+ const leftEdge = window.innerWidth - CONTENT_MARGIN;
1534
+ const clampedRight = number.clamp(right, [CONTENT_MARGIN, leftEdge - contentWidth]);
1535
+ contentWrapper.style.minWidth = `${minContentWidth}px`;
1536
+ contentWrapper.style.right = `${clampedRight}px`;
1537
+ }
1538
+ const items = getItems();
1539
+ const availableHeight = window.innerHeight - CONTENT_MARGIN * 2;
1540
+ const itemsHeight = viewport.scrollHeight;
1541
+ const contentStyles = window.getComputedStyle(content);
1542
+ const contentBorderTopWidth = parseInt(contentStyles.borderTopWidth, 10);
1543
+ const contentPaddingTop = parseInt(contentStyles.paddingTop, 10);
1544
+ const contentBorderBottomWidth = parseInt(contentStyles.borderBottomWidth, 10);
1545
+ const contentPaddingBottom = parseInt(contentStyles.paddingBottom, 10);
1546
+ const fullContentHeight = contentBorderTopWidth + contentPaddingTop + itemsHeight + contentPaddingBottom + contentBorderBottomWidth;
1547
+ const minContentHeight = Math.min(selectedItem.offsetHeight * 5, fullContentHeight);
1548
+ const viewportStyles = window.getComputedStyle(viewport);
1549
+ const viewportPaddingTop = parseInt(viewportStyles.paddingTop, 10);
1550
+ const viewportPaddingBottom = parseInt(viewportStyles.paddingBottom, 10);
1551
+ const topEdgeToTriggerMiddle = triggerRect.top + triggerRect.height / 2 - CONTENT_MARGIN;
1552
+ const triggerMiddleToBottomEdge = availableHeight - topEdgeToTriggerMiddle;
1553
+ const selectedItemHalfHeight = selectedItem.offsetHeight / 2;
1554
+ const itemOffsetMiddle = selectedItem.offsetTop + selectedItemHalfHeight;
1555
+ const contentTopToItemMiddle = contentBorderTopWidth + contentPaddingTop + itemOffsetMiddle;
1556
+ const itemMiddleToContentBottom = fullContentHeight - contentTopToItemMiddle;
1557
+ const willAlignWithoutTopOverflow = contentTopToItemMiddle <= topEdgeToTriggerMiddle;
1558
+ if (willAlignWithoutTopOverflow) {
1559
+ const isLastItem = selectedItem === items[items.length - 1].ref.current;
1560
+ contentWrapper.style.bottom = `${0}px`;
1561
+ const viewportOffsetBottom = content.clientHeight - viewport.offsetTop - viewport.offsetHeight;
1562
+ const clampedTriggerMiddleToBottomEdge = Math.max(
1563
+ triggerMiddleToBottomEdge,
1564
+ selectedItemHalfHeight + // viewport might have padding bottom, include it to avoid a scrollable viewport
1565
+ (isLastItem ? viewportPaddingBottom : 0) + viewportOffsetBottom + contentBorderBottomWidth
1566
+ );
1567
+ const height = contentTopToItemMiddle + clampedTriggerMiddleToBottomEdge;
1568
+ contentWrapper.style.height = `${height}px`;
1569
+ } else {
1570
+ const isFirstItem = selectedItem === items[0].ref.current;
1571
+ contentWrapper.style.top = `${0}px`;
1572
+ const clampedTopEdgeToTriggerMiddle = Math.max(
1573
+ topEdgeToTriggerMiddle,
1574
+ contentBorderTopWidth + viewport.offsetTop + // viewport might have padding top, include it to avoid a scrollable viewport
1575
+ (isFirstItem ? viewportPaddingTop : 0) + selectedItemHalfHeight
1576
+ );
1577
+ const height = clampedTopEdgeToTriggerMiddle + itemMiddleToContentBottom;
1578
+ contentWrapper.style.height = `${height}px`;
1579
+ viewport.scrollTop = contentTopToItemMiddle - topEdgeToTriggerMiddle + viewport.offsetTop;
1580
+ }
1581
+ contentWrapper.style.margin = `${CONTENT_MARGIN}px 0`;
1582
+ contentWrapper.style.minHeight = `${minContentHeight}px`;
1583
+ contentWrapper.style.maxHeight = `${availableHeight}px`;
1584
+ onPlaced?.();
1585
+ requestAnimationFrame(() => shouldExpandOnScrollRef.current = true);
1586
+ }
1587
+ }, [
1588
+ getItems,
1589
+ context.trigger,
1590
+ context.valueNode,
1591
+ contentWrapper,
1592
+ content,
1593
+ viewport,
1594
+ selectedItem,
1595
+ selectedItemText,
1596
+ context.dir,
1597
+ onPlaced
1598
+ ]);
1599
+ reactUseLayoutEffect.useLayoutEffect(() => position(), [position]);
1600
+ const [contentZIndex, setContentZIndex] = React__namespace.useState();
1601
+ reactUseLayoutEffect.useLayoutEffect(() => {
1602
+ if (content)
1603
+ setContentZIndex(window.getComputedStyle(content).zIndex);
1604
+ }, [content]);
1605
+ const handleScrollButtonChange = React__namespace.useCallback(
1606
+ (node) => {
1607
+ if (node && shouldRepositionRef.current === true) {
1608
+ position();
1609
+ focusSelectedItem?.();
1610
+ shouldRepositionRef.current = false;
1611
+ }
1612
+ },
1613
+ [position, focusSelectedItem]
1614
+ );
1615
+ return /* @__PURE__ */ jsxRuntime.jsx(
1616
+ SelectViewportProvider,
1617
+ {
1618
+ scope: __scopeSelect,
1619
+ contentWrapper,
1620
+ shouldExpandOnScrollRef,
1621
+ onScrollButtonChange: handleScrollButtonChange,
1622
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1623
+ "div",
1624
+ {
1625
+ ref: setContentWrapper,
1626
+ style: {
1627
+ display: "flex",
1628
+ flexDirection: "column",
1629
+ position: "fixed",
1630
+ zIndex: contentZIndex
1631
+ },
1632
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1633
+ reactPrimitive.Primitive.div,
1634
+ {
1635
+ ...popperProps,
1636
+ ref: composedRefs,
1637
+ style: {
1638
+ // When we get the height of the content, it includes borders. If we were to set
1639
+ // the height without having `boxSizing: 'border-box'` it would be too big.
1640
+ boxSizing: "border-box",
1641
+ // We need to ensure the content doesn't get taller than the wrapper
1642
+ maxHeight: "100%",
1643
+ ...popperProps.style
1644
+ }
1645
+ }
1646
+ )
1647
+ }
1648
+ )
1649
+ }
1650
+ );
1651
+ }
1652
+ );
1653
+ SelectItemAlignedPosition.displayName = ITEM_ALIGNED_POSITION_NAME;
1654
+ const POPPER_POSITION_NAME = "SelectPopperPosition";
1655
+ const SelectPopperPosition = React__namespace.forwardRef(
1656
+ (props, forwardedRef) => {
1657
+ const { __scopeSelect, align = "start", collisionPadding = CONTENT_MARGIN, ...popperProps } = props;
1658
+ const popperScope = usePopperScope(__scopeSelect);
1659
+ return /* @__PURE__ */ jsxRuntime.jsx(
1660
+ PopperPrimitive__namespace.Content,
1661
+ {
1662
+ ...popperScope,
1663
+ ...popperProps,
1664
+ ref: forwardedRef,
1665
+ align,
1666
+ collisionPadding,
1667
+ style: {
1668
+ // Ensure border-box for floating-ui calculations
1669
+ boxSizing: "border-box",
1670
+ ...popperProps.style,
1671
+ // re-namespace exposed content custom properties
1672
+ ...{
1673
+ "--radix-select-content-transform-origin": "var(--radix-popper-transform-origin)",
1674
+ "--radix-select-content-available-width": "var(--radix-popper-available-width)",
1675
+ "--radix-select-content-available-height": "var(--radix-popper-available-height)",
1676
+ "--radix-select-trigger-width": "var(--radix-popper-anchor-width)",
1677
+ "--radix-select-trigger-height": "var(--radix-popper-anchor-height)"
1678
+ }
1679
+ }
1680
+ }
1681
+ );
1682
+ }
1683
+ );
1684
+ SelectPopperPosition.displayName = POPPER_POSITION_NAME;
1685
+ const [SelectViewportProvider, useSelectViewportContext] = createSelectContext(
1686
+ CONTENT_NAME,
1687
+ {}
1688
+ );
1689
+ const VIEWPORT_NAME = "SelectViewport";
1690
+ const SelectViewport = React__namespace.forwardRef(
1691
+ (props, forwardedRef) => {
1692
+ const { __scopeSelect, ...viewportProps } = props;
1693
+ const contentContext = useSelectContentContext(VIEWPORT_NAME, __scopeSelect);
1694
+ const viewportContext = useSelectViewportContext(VIEWPORT_NAME, __scopeSelect);
1695
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, contentContext.onViewportChange);
1696
+ const prevScrollTopRef = React__namespace.useRef(0);
1697
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1698
+ /* @__PURE__ */ jsxRuntime.jsx(
1699
+ "style",
1700
+ {
1701
+ dangerouslySetInnerHTML: {
1702
+ __html: `[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`
1703
+ }
1704
+ }
1705
+ ),
1706
+ /* @__PURE__ */ jsxRuntime.jsx(Collection.Slot, { scope: __scopeSelect, children: /* @__PURE__ */ jsxRuntime.jsx(
1707
+ reactPrimitive.Primitive.div,
1708
+ {
1709
+ "data-radix-select-viewport": "",
1710
+ role: "presentation",
1711
+ ...viewportProps,
1712
+ ref: composedRefs,
1713
+ style: {
1714
+ // we use position: 'relative' here on the `viewport` so that when we call
1715
+ // `selectedItem.offsetTop` in calculations, the offset is relative to the viewport
1716
+ // (independent of the scrollUpButton).
1717
+ position: "relative",
1718
+ flex: 1,
1719
+ overflow: "auto",
1720
+ ...viewportProps.style
1721
+ },
1722
+ onScroll: primitive.composeEventHandlers(viewportProps.onScroll, (event) => {
1723
+ const viewport = event.currentTarget;
1724
+ const { contentWrapper, shouldExpandOnScrollRef } = viewportContext;
1725
+ if (shouldExpandOnScrollRef?.current && contentWrapper) {
1726
+ const scrolledBy = Math.abs(prevScrollTopRef.current - viewport.scrollTop);
1727
+ if (scrolledBy > 0) {
1728
+ const availableHeight = window.innerHeight - CONTENT_MARGIN * 2;
1729
+ const cssMinHeight = parseFloat(contentWrapper.style.minHeight);
1730
+ const cssHeight = parseFloat(contentWrapper.style.height);
1731
+ const prevHeight = Math.max(cssMinHeight, cssHeight);
1732
+ if (prevHeight < availableHeight) {
1733
+ const nextHeight = prevHeight + scrolledBy;
1734
+ const clampedNextHeight = Math.min(availableHeight, nextHeight);
1735
+ const heightDiff = nextHeight - clampedNextHeight;
1736
+ contentWrapper.style.height = `${clampedNextHeight}px`;
1737
+ if (contentWrapper.style.bottom === "0px") {
1738
+ viewport.scrollTop = heightDiff > 0 ? heightDiff : 0;
1739
+ contentWrapper.style.justifyContent = "flex-end";
1740
+ }
1741
+ }
1742
+ }
1743
+ }
1744
+ prevScrollTopRef.current = viewport.scrollTop;
1745
+ })
1746
+ }
1747
+ ) })
1748
+ ] });
1749
+ }
1750
+ );
1751
+ SelectViewport.displayName = VIEWPORT_NAME;
1752
+ const GROUP_NAME = "SelectGroup";
1753
+ const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
1754
+ const SelectGroup = React__namespace.forwardRef(
1755
+ (props, forwardedRef) => {
1756
+ const { __scopeSelect, ...groupProps } = props;
1757
+ const groupId = reactId.useId();
1758
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectGroupContextProvider, { scope: __scopeSelect, id: groupId, children: /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.div, { role: "group", "aria-labelledby": groupId, ...groupProps, ref: forwardedRef }) });
1759
+ }
1760
+ );
1761
+ SelectGroup.displayName = GROUP_NAME;
1762
+ const LABEL_NAME = "SelectLabel";
1763
+ const SelectLabel = React__namespace.forwardRef(
1764
+ (props, forwardedRef) => {
1765
+ const { __scopeSelect, ...labelProps } = props;
1766
+ const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
1767
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.div, { id: groupContext.id, ...labelProps, ref: forwardedRef });
1768
+ }
1769
+ );
1770
+ SelectLabel.displayName = LABEL_NAME;
1771
+ const ITEM_NAME = "SelectItem";
1772
+ const [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
1773
+ const SelectItem = React__namespace.forwardRef(
1774
+ (props, forwardedRef) => {
1775
+ const { __scopeSelect, value, disabled = false, textValue: textValueProp, ...itemProps } = props;
1776
+ const context = useSelectContext(ITEM_NAME, __scopeSelect);
1777
+ const contentContext = useSelectContentContext(ITEM_NAME, __scopeSelect);
1778
+ const isSelected = typeof value === "string" ? Array.isArray(context.value) ? context.value.includes(value) : context.value === value : value.every((v) => context.value?.includes(v));
1779
+ const isIntermediate = Array.isArray(context.value) && Array.isArray(value) && value.some((v) => context.value?.includes(v));
1780
+ const [textValue, setTextValue] = React__namespace.useState(textValueProp ?? "");
1781
+ const [isFocused, setIsFocused] = React__namespace.useState(false);
1782
+ const composedRefs = reactComposeRefs.useComposedRefs(
1783
+ forwardedRef,
1784
+ (node) => contentContext.itemRefCallback?.(node, value, disabled)
1785
+ );
1786
+ const textId = reactId.useId();
1787
+ const handleSelect = () => {
1788
+ if (!disabled) {
1789
+ let newValue = context.multi && typeof value === "string" ? [value] : value;
1790
+ if (isIntermediate && !isSelected) {
1791
+ context.onValueChange(newValue);
1792
+ } else if (Array.isArray(context.value)) {
1793
+ newValue = toggleArrayValue(value, context.value);
1794
+ }
1795
+ context.onValueChange(newValue);
1796
+ if (!context.multi) {
1797
+ context.onOpenChange(false);
1798
+ }
1799
+ }
1800
+ };
1801
+ if (!context.multi && Array.isArray(value)) {
1802
+ throw new Error("You can only pass an array of values in multi selects");
1803
+ }
1804
+ return /* @__PURE__ */ jsxRuntime.jsx(
1805
+ SelectItemContextProvider,
1806
+ {
1807
+ scope: __scopeSelect,
1808
+ value,
1809
+ disabled,
1810
+ textId,
1811
+ isSelected,
1812
+ isIntermediate,
1813
+ onItemTextChange: React__namespace.useCallback((node) => {
1814
+ setTextValue((prevTextValue) => prevTextValue || (node?.textContent ?? "").trim());
1815
+ }, []),
1816
+ children: /* @__PURE__ */ jsxRuntime.jsx(Collection.ItemSlot, { scope: __scopeSelect, value, disabled, textValue, children: /* @__PURE__ */ jsxRuntime.jsx(
1817
+ reactPrimitive.Primitive.div,
1818
+ {
1819
+ role: "option",
1820
+ "aria-labelledby": textId,
1821
+ "data-highlighted": isFocused ? "" : void 0,
1822
+ "aria-selected": !context.multi ? isSelected && isFocused : void 0,
1823
+ "aria-checked": context.multi ? isSelected : void 0,
1824
+ "data-state": isSelected ? "checked" : "unchecked",
1825
+ "aria-disabled": disabled || void 0,
1826
+ "data-disabled": disabled ? "" : void 0,
1827
+ tabIndex: disabled ? void 0 : -1,
1828
+ ...itemProps,
1829
+ ref: composedRefs,
1830
+ onFocus: primitive.composeEventHandlers(itemProps.onFocus, () => setIsFocused(true)),
1831
+ onBlur: primitive.composeEventHandlers(itemProps.onBlur, () => setIsFocused(false)),
1832
+ onPointerUp: primitive.composeEventHandlers(itemProps.onPointerUp, handleSelect),
1833
+ onPointerMove: primitive.composeEventHandlers(itemProps.onPointerMove, (event) => {
1834
+ if (disabled) {
1835
+ contentContext.onItemLeave?.();
1836
+ } else {
1837
+ event.currentTarget.focus({ preventScroll: true });
1838
+ }
1839
+ }),
1840
+ onPointerLeave: primitive.composeEventHandlers(itemProps.onPointerLeave, (event) => {
1841
+ if (event.currentTarget === document.activeElement) {
1842
+ contentContext.onItemLeave?.();
1843
+ }
1844
+ }),
1845
+ onKeyDown: primitive.composeEventHandlers(itemProps.onKeyDown, (event) => {
1846
+ const isTypingAhead = contentContext.searchRef?.current !== "";
1847
+ if (isTypingAhead && event.key === " ")
1848
+ return;
1849
+ if (SELECTION_KEYS.includes(event.key))
1850
+ handleSelect();
1851
+ if (event.key === " ")
1852
+ event.preventDefault();
1853
+ })
1854
+ }
1855
+ ) })
1856
+ }
1857
+ );
1858
+ }
1859
+ );
1860
+ SelectItem.displayName = ITEM_NAME;
1861
+ const ITEM_TEXT_NAME = "SelectItemText";
1862
+ const SelectItemText = React__namespace.forwardRef(
1863
+ (props, forwardedRef) => {
1864
+ const { __scopeSelect, className: _className, style: _style, ...itemTextProps } = props;
1865
+ const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
1866
+ const contentContext = useSelectContentContext(ITEM_TEXT_NAME, __scopeSelect);
1867
+ const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
1868
+ const nativeOptionsContext = useSelectNativeOptionsContext(ITEM_TEXT_NAME, __scopeSelect);
1869
+ const [itemTextNode, setItemTextNode] = React__namespace.useState(null);
1870
+ const composedRefs = reactComposeRefs.useComposedRefs(
1871
+ forwardedRef,
1872
+ (node) => setItemTextNode(node),
1873
+ itemContext.onItemTextChange,
1874
+ (node) => contentContext.itemTextRefCallback?.(node, itemContext.value, itemContext.disabled)
1875
+ );
1876
+ const textContent = itemTextNode?.textContent;
1877
+ const nativeOption = React__namespace.useMemo(
1878
+ () => /* @__PURE__ */ jsxRuntime.jsx(
1879
+ "option",
1880
+ {
1881
+ value: itemContext.value,
1882
+ disabled: itemContext.disabled,
1883
+ children: textContent
1884
+ },
1885
+ Array.isArray(itemContext.value) ? itemContext.value.join(";") : itemContext.value
1886
+ ),
1887
+ [itemContext.disabled, itemContext.value, textContent]
1888
+ );
1889
+ const { onNativeOptionAdd, onNativeOptionRemove } = nativeOptionsContext;
1890
+ reactUseLayoutEffect.useLayoutEffect(() => {
1891
+ onNativeOptionAdd(nativeOption);
1892
+ return () => onNativeOptionRemove(nativeOption);
1893
+ }, [onNativeOptionAdd, onNativeOptionRemove, nativeOption]);
1894
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1895
+ /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.span, { id: itemContext.textId, ...itemTextProps, ref: composedRefs }),
1896
+ itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? ReactDOM__namespace.createPortal(itemTextProps.children, context.valueNode) : null
1897
+ ] });
1898
+ }
1899
+ );
1900
+ SelectItemText.displayName = ITEM_TEXT_NAME;
1901
+ const ITEM_INDICATOR_NAME = "SelectItemIndicator";
1902
+ const SelectItemIndicator = React__namespace.forwardRef(
1903
+ (props, forwardedRef) => {
1904
+ const { __scopeSelect, children, ...itemIndicatorProps } = props;
1905
+ const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
1906
+ if (typeof children === "function") {
1907
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.span, { "aria-hidden": true, ...itemIndicatorProps, ref: forwardedRef, children: children({
1908
+ isSelected: itemContext.isSelected,
1909
+ isIntermediate: itemContext.isIntermediate
1910
+ }) });
1911
+ }
1912
+ return itemContext.isSelected ? /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.span, { "aria-hidden": true, ...itemIndicatorProps, ref: forwardedRef, children }) : null;
1913
+ }
1914
+ );
1915
+ SelectItemIndicator.displayName = ITEM_INDICATOR_NAME;
1916
+ const SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
1917
+ const SelectScrollUpButton = React__namespace.forwardRef(
1918
+ (props, forwardedRef) => {
1919
+ const contentContext = useSelectContentContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
1920
+ const viewportContext = useSelectViewportContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
1921
+ const [canScrollUp, setCanScrollUp] = React__namespace.useState(false);
1922
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, viewportContext.onScrollButtonChange);
1923
+ reactUseLayoutEffect.useLayoutEffect(() => {
1924
+ if (contentContext.viewport && contentContext.isPositioned) {
1925
+ const viewport = contentContext.viewport;
1926
+ const handleScroll = () => {
1927
+ const canScrollUp2 = viewport.scrollTop > 0;
1928
+ setCanScrollUp(canScrollUp2);
1929
+ };
1930
+ handleScroll();
1931
+ viewport.addEventListener("scroll", handleScroll);
1932
+ return () => viewport.removeEventListener("scroll", handleScroll);
1933
+ }
1934
+ }, [contentContext.viewport, contentContext.isPositioned]);
1935
+ return canScrollUp ? /* @__PURE__ */ jsxRuntime.jsx(
1936
+ SelectScrollButtonImpl,
1937
+ {
1938
+ ...props,
1939
+ ref: composedRefs,
1940
+ onAutoScroll: () => {
1941
+ const { viewport, selectedItem } = contentContext;
1942
+ if (viewport && selectedItem) {
1943
+ viewport.scrollTop -= selectedItem.offsetHeight;
1944
+ }
1945
+ }
1946
+ }
1947
+ ) : null;
1948
+ }
1949
+ );
1950
+ SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
1951
+ const SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
1952
+ const SelectScrollDownButton = React__namespace.forwardRef(
1953
+ (props, forwardedRef) => {
1954
+ const contentContext = useSelectContentContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
1955
+ const viewportContext = useSelectViewportContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
1956
+ const [canScrollDown, setCanScrollDown] = React__namespace.useState(false);
1957
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, viewportContext.onScrollButtonChange);
1958
+ reactUseLayoutEffect.useLayoutEffect(() => {
1959
+ if (contentContext.viewport && contentContext.isPositioned) {
1960
+ const viewport = contentContext.viewport;
1961
+ const handleScroll = () => {
1962
+ const maxScroll = viewport.scrollHeight - viewport.clientHeight;
1963
+ const canScrollDown2 = Math.ceil(viewport.scrollTop) < maxScroll;
1964
+ setCanScrollDown(canScrollDown2);
1965
+ };
1966
+ handleScroll();
1967
+ viewport.addEventListener("scroll", handleScroll);
1968
+ return () => viewport.removeEventListener("scroll", handleScroll);
1969
+ }
1970
+ }, [contentContext.viewport, contentContext.isPositioned]);
1971
+ return canScrollDown ? /* @__PURE__ */ jsxRuntime.jsx(
1972
+ SelectScrollButtonImpl,
1973
+ {
1974
+ ...props,
1975
+ ref: composedRefs,
1976
+ onAutoScroll: () => {
1977
+ const { viewport, selectedItem } = contentContext;
1978
+ if (viewport && selectedItem) {
1979
+ viewport.scrollTop += selectedItem.offsetHeight;
1980
+ }
1981
+ }
1982
+ }
1983
+ ) : null;
1984
+ }
1985
+ );
1986
+ SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
1987
+ const SelectScrollButtonImpl = React__namespace.forwardRef(
1988
+ (props, forwardedRef) => {
1989
+ const { __scopeSelect, onAutoScroll, ...scrollIndicatorProps } = props;
1990
+ const contentContext = useSelectContentContext("SelectScrollButton", __scopeSelect);
1991
+ const autoScrollTimerRef = React__namespace.useRef(null);
1992
+ const getItems = useCollection(__scopeSelect);
1993
+ const clearAutoScrollTimer = React__namespace.useCallback(() => {
1994
+ if (autoScrollTimerRef.current !== null) {
1995
+ window.clearInterval(autoScrollTimerRef.current);
1996
+ autoScrollTimerRef.current = null;
1997
+ }
1998
+ }, []);
1999
+ React__namespace.useEffect(() => {
2000
+ return () => clearAutoScrollTimer();
2001
+ }, [clearAutoScrollTimer]);
2002
+ reactUseLayoutEffect.useLayoutEffect(() => {
2003
+ const activeItem = getItems().find((item) => item.ref.current === document.activeElement);
2004
+ activeItem?.ref.current?.scrollIntoView({ block: "nearest" });
2005
+ }, [getItems]);
2006
+ return /* @__PURE__ */ jsxRuntime.jsx(
2007
+ reactPrimitive.Primitive.div,
2008
+ {
2009
+ "aria-hidden": true,
2010
+ ...scrollIndicatorProps,
2011
+ ref: forwardedRef,
2012
+ style: { flexShrink: 0, ...scrollIndicatorProps.style },
2013
+ onPointerMove: primitive.composeEventHandlers(scrollIndicatorProps.onPointerMove, () => {
2014
+ contentContext.onItemLeave?.();
2015
+ if (autoScrollTimerRef.current === null) {
2016
+ autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
2017
+ }
2018
+ }),
2019
+ onPointerLeave: primitive.composeEventHandlers(scrollIndicatorProps.onPointerLeave, () => {
2020
+ clearAutoScrollTimer();
2021
+ })
2022
+ }
2023
+ );
2024
+ }
2025
+ );
2026
+ SelectScrollButtonImpl.displayName = "SelectScrollButtonImpl";
2027
+ const SEPARATOR_NAME = "SelectSeparator";
2028
+ const SelectSeparator = React__namespace.forwardRef(
2029
+ (props, forwardedRef) => {
2030
+ const { __scopeSelect, ...separatorProps } = props;
2031
+ return /* @__PURE__ */ jsxRuntime.jsx(reactPrimitive.Primitive.div, { "aria-hidden": true, ...separatorProps, ref: forwardedRef });
2032
+ }
2033
+ );
2034
+ SelectSeparator.displayName = SEPARATOR_NAME;
2035
+ const ARROW_NAME = "SelectArrow";
2036
+ const SelectArrow = React__namespace.forwardRef(
2037
+ (props, forwardedRef) => {
2038
+ const { __scopeSelect, ...arrowProps } = props;
2039
+ const popperScope = usePopperScope(__scopeSelect);
2040
+ const context = useSelectContext(ARROW_NAME, __scopeSelect);
2041
+ const contentContext = useSelectContentContext(ARROW_NAME, __scopeSelect);
2042
+ return context.open && contentContext.position === "popper" ? /* @__PURE__ */ jsxRuntime.jsx(PopperPrimitive__namespace.Arrow, { ...popperScope, ...arrowProps, ref: forwardedRef }) : null;
2043
+ }
2044
+ );
2045
+ SelectArrow.displayName = ARROW_NAME;
2046
+ const BUBBLE_SELECT_NAME = "BubbleSelect";
2047
+ const BubbleSelect = React__namespace.forwardRef(
2048
+ (props, forwardedRef) => {
2049
+ const { value, ...selectProps } = props;
2050
+ const ref = React__namespace.useRef(null);
2051
+ const composedRefs = reactComposeRefs.useComposedRefs(forwardedRef, ref);
2052
+ const prevValue = reactUsePrevious.usePrevious(value);
2053
+ const context = useSelectContext(BUBBLE_SELECT_NAME, void 0);
2054
+ React__namespace.useEffect(() => {
2055
+ const select = ref.current;
2056
+ const selectProto = window.HTMLSelectElement.prototype;
2057
+ const descriptor = Object.getOwnPropertyDescriptor(selectProto, "value");
2058
+ const setValue = descriptor.set;
2059
+ if (prevValue !== value && setValue) {
2060
+ const event = new Event("change", { bubbles: true });
2061
+ setValue.call(select, value);
2062
+ select.dispatchEvent(event);
2063
+ }
2064
+ }, [prevValue, value]);
2065
+ let defaultValue = value;
2066
+ if (context.multi && !Array.isArray(value)) {
2067
+ defaultValue = [];
2068
+ }
2069
+ return /* @__PURE__ */ jsxRuntime.jsx(reactVisuallyHidden.VisuallyHidden, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2070
+ "select",
2071
+ {
2072
+ ...selectProps,
2073
+ multiple: context.multi ? true : void 0,
2074
+ ref: composedRefs,
2075
+ defaultValue
2076
+ }
2077
+ ) });
2078
+ }
2079
+ );
2080
+ BubbleSelect.displayName = "BubbleSelect";
2081
+ function useTypeaheadSearch(onSearchChange) {
2082
+ const handleSearchChange = reactUseCallbackRef.useCallbackRef(onSearchChange);
2083
+ const searchRef = React__namespace.useRef("");
2084
+ const timerRef = React__namespace.useRef(0);
2085
+ const handleTypeaheadSearch = React__namespace.useCallback(
2086
+ (key) => {
2087
+ const search = searchRef.current + key;
2088
+ handleSearchChange(search);
2089
+ (function updateSearch(value) {
2090
+ searchRef.current = value;
2091
+ window.clearTimeout(timerRef.current);
2092
+ if (value !== "")
2093
+ timerRef.current = window.setTimeout(() => updateSearch(""), 1e3);
2094
+ })(search);
2095
+ },
2096
+ [handleSearchChange]
2097
+ );
2098
+ const resetTypeahead = React__namespace.useCallback(() => {
2099
+ searchRef.current = "";
2100
+ window.clearTimeout(timerRef.current);
2101
+ }, []);
2102
+ React__namespace.useEffect(() => {
2103
+ return () => window.clearTimeout(timerRef.current);
2104
+ }, []);
2105
+ return [searchRef, handleTypeaheadSearch, resetTypeahead];
2106
+ }
2107
+ function findNextItem(items, search, currentItem) {
2108
+ const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
2109
+ const normalizedSearch = isRepeated ? search[0] : search;
2110
+ const currentItemIndex = currentItem ? items.indexOf(currentItem) : -1;
2111
+ let wrappedItems = wrapArray(items, Math.max(currentItemIndex, 0));
2112
+ const excludeCurrentItem = normalizedSearch.length === 1;
2113
+ if (excludeCurrentItem)
2114
+ wrappedItems = wrappedItems.filter((v) => v !== currentItem);
2115
+ const nextItem = wrappedItems.find((item) => item.textValue.toLowerCase().startsWith(normalizedSearch.toLowerCase()));
2116
+ return nextItem !== currentItem ? nextItem : void 0;
2117
+ }
2118
+ function wrapArray(array, startIndex) {
2119
+ return array.map((_, index) => array[(startIndex + index) % array.length]);
2120
+ }
2121
+ const toggleArrayValue = (value, array = []) => {
2122
+ if (Array.isArray(value)) {
2123
+ return value.reduce((acc, val) => toggleArrayValue(val, acc), array);
2124
+ }
2125
+ const index = array.indexOf(value);
2126
+ if (index === -1) {
2127
+ return [...array, value];
2128
+ }
2129
+ return [...array.slice(0, index), ...array.slice(index + 1)];
2130
+ };
2131
+ const Root = Select;
2132
+ const Trigger = SelectTrigger;
2133
+ const Value = SelectValue;
2134
+ const Icon = SelectIcon;
2135
+ const Portal = SelectPortal;
2136
+ const Content = SelectContent;
2137
+ const Viewport = SelectViewport;
2138
+ const Group = SelectGroup;
2139
+ const Label = SelectLabel;
2140
+ const Item = SelectItem;
2141
+ const ItemText = SelectItemText;
2142
+ const ItemIndicator = SelectItemIndicator;
2143
+ const ScrollUpButton = SelectScrollUpButton;
2144
+ const ScrollDownButton = SelectScrollDownButton;
2145
+ const Separator = SelectSeparator;
2146
+ const Arrow = SelectArrow;
2147
+ const Select$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2148
+ __proto__: null,
2149
+ Arrow,
2150
+ Content,
2151
+ Group,
2152
+ Icon,
2153
+ Item,
2154
+ ItemIndicator,
2155
+ ItemText,
2156
+ Label,
2157
+ Portal,
2158
+ Root,
2159
+ ScrollDownButton,
2160
+ ScrollUpButton,
2161
+ Select,
2162
+ SelectArrow,
2163
+ SelectContent,
2164
+ SelectGroup,
2165
+ SelectIcon,
2166
+ SelectItem,
2167
+ SelectItemIndicator,
2168
+ SelectItemText,
2169
+ SelectLabel,
2170
+ SelectPortal,
2171
+ SelectScrollDownButton,
2172
+ SelectScrollUpButton,
2173
+ SelectSeparator,
2174
+ SelectTrigger,
2175
+ SelectValue,
2176
+ SelectViewport,
2177
+ Separator,
2178
+ Trigger,
2179
+ Value,
2180
+ Viewport,
2181
+ createSelectScope
2182
+ }, Symbol.toStringTag, { value: "Module" }));
2183
+ Object.defineProperty(exports, "composeEventHandlers", {
2184
+ enumerable: true,
2185
+ get: () => primitive.composeEventHandlers
2186
+ });
2187
+ Object.defineProperty(exports, "useCallbackRef", {
2188
+ enumerable: true,
2189
+ get: () => reactUseCallbackRef.useCallbackRef
2190
+ });
2191
+ exports.Combobox = Combobox$1;
2192
+ exports.Select = Select$1;
2193
+ exports.createCollection = createCollection;
2194
+ exports.useCollator = useCollator;
2195
+ exports.useFilter = useFilter;
2196
+ //# sourceMappingURL=index.js.map