@arun-dev/headless 4.7.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1109 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/combobox/index.ts
21
+ var combobox_exports = {};
22
+ __export(combobox_exports, {
23
+ Combobox: () => index_parts_exports,
24
+ defaultFilter: () => defaultFilter
25
+ });
26
+ module.exports = __toCommonJS(combobox_exports);
27
+
28
+ // src/combobox/index.parts.ts
29
+ var index_parts_exports = {};
30
+ __export(index_parts_exports, {
31
+ Chip: () => ComboboxChip,
32
+ ChipRemove: () => ComboboxChipRemove,
33
+ Clear: () => ComboboxClear,
34
+ Empty: () => ComboboxEmpty,
35
+ Input: () => ComboboxInput,
36
+ InputGroup: () => ComboboxInputGroup,
37
+ Item: () => ComboboxItem,
38
+ List: () => ComboboxList,
39
+ Popup: () => ComboboxPopup,
40
+ Root: () => ComboboxRoot,
41
+ Status: () => ComboboxStatus,
42
+ Trigger: () => ComboboxTrigger,
43
+ Value: () => ComboboxValue
44
+ });
45
+
46
+ // src/combobox/ComboboxRoot.tsx
47
+ var import_react3 = require("react");
48
+
49
+ // src/core/anchoring.ts
50
+ function anchorNameFor(id) {
51
+ return `--hl-anchor-${id.replace(/[^a-zA-Z0-9_-]/g, "")}`;
52
+ }
53
+ var POSITION_AREA = {
54
+ bottom: { start: "bottom span-right", center: "bottom", end: "bottom span-left" },
55
+ top: { start: "top span-right", center: "top", end: "top span-left" },
56
+ right: { start: "right span-bottom", center: "right", end: "right span-top" },
57
+ left: { start: "left span-bottom", center: "left", end: "left span-top" }
58
+ };
59
+ function anchoredPopupStyle(anchorName, side, align) {
60
+ return {
61
+ positionAnchor: anchorName,
62
+ positionArea: POSITION_AREA[side][align],
63
+ // Flip across the axis it opens on; the other axis is left alone.
64
+ positionTryFallbacks: side === "top" || side === "bottom" ? "flip-block" : "flip-inline"
65
+ };
66
+ }
67
+ function anchoredDataAttributes(side, align) {
68
+ return { "data-side": side, "data-align": align };
69
+ }
70
+
71
+ // src/core/rovingFocus.ts
72
+ function byDocumentOrder(a, b) {
73
+ const x = a.ref.current;
74
+ const y = b.ref.current;
75
+ if (!x || !y) return 0;
76
+ return x.compareDocumentPosition(y) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
77
+ }
78
+ function rovingIndex(key, {
79
+ count,
80
+ current,
81
+ orientation,
82
+ rtl
83
+ }) {
84
+ if (count === 0) return null;
85
+ const [prevKey, nextKey] = orientation === "vertical" ? ["ArrowUp", "ArrowDown"] : rtl ? ["ArrowRight", "ArrowLeft"] : ["ArrowLeft", "ArrowRight"];
86
+ switch (key) {
87
+ case nextKey:
88
+ return current < 0 ? 0 : (current + 1) % count;
89
+ case prevKey:
90
+ return current < 0 ? count - 1 : (current - 1 + count) % count;
91
+ case "Home":
92
+ return 0;
93
+ case "End":
94
+ return count - 1;
95
+ default:
96
+ return null;
97
+ }
98
+ }
99
+
100
+ // src/core/useControlled.ts
101
+ var import_react = require("react");
102
+ function useControlled({
103
+ controlled,
104
+ default: defaultValue,
105
+ name = "Component",
106
+ state = "value"
107
+ }) {
108
+ const { current: isControlled } = (0, import_react.useRef)(controlled !== void 0);
109
+ const [uncontrolled, setUncontrolled] = (0, import_react.useState)(defaultValue);
110
+ const defaultRef = (0, import_react.useRef)(defaultValue);
111
+ const value = isControlled ? controlled : uncontrolled;
112
+ if (process.env.NODE_ENV !== "production") {
113
+ if (isControlled !== (controlled !== void 0)) {
114
+ console.error(
115
+ `${name}: cannot switch between controlled and uncontrolled \`${state}\`. Decide which one this component is for the whole of its life.`
116
+ );
117
+ }
118
+ if (!isControlled && defaultRef.current !== defaultValue) {
119
+ console.error(
120
+ `${name}: cannot change the default \`${state}\` after mount. It is only read once, so later changes are silently ignored.`
121
+ );
122
+ }
123
+ }
124
+ const setValue = (0, import_react.useCallback)(
125
+ (next) => {
126
+ if (!isControlled) setUncontrolled(next);
127
+ },
128
+ [isControlled]
129
+ );
130
+ return [value, setValue];
131
+ }
132
+
133
+ // src/combobox/defaultFilter.ts
134
+ function fold(text) {
135
+ return text.normalize("NFD").replace(/\p{M}/gu, "").toLocaleLowerCase();
136
+ }
137
+ function defaultFilter(items, query, itemToString) {
138
+ const needle = fold(query.trim());
139
+ if (needle === "") return [...items];
140
+ return items.filter((item) => fold(itemToString(item)).includes(needle));
141
+ }
142
+
143
+ // src/combobox/ComboboxRootContext.ts
144
+ var import_react2 = require("react");
145
+ function createHighlightStore() {
146
+ let current = { index: -1, reason: "none" };
147
+ const listeners = /* @__PURE__ */ new Set();
148
+ return {
149
+ get: () => current,
150
+ set(next) {
151
+ if (next.index === current.index && next.reason === current.reason) return;
152
+ current = next;
153
+ for (const listener of listeners) listener();
154
+ },
155
+ subscribe(listener) {
156
+ listeners.add(listener);
157
+ return () => listeners.delete(listener);
158
+ }
159
+ };
160
+ }
161
+ var ComboboxRootContext = (0, import_react2.createContext)(null);
162
+ function useComboboxRootContext(part) {
163
+ const context = (0, import_react2.useContext)(ComboboxRootContext);
164
+ if (context === null) {
165
+ throw new Error(`<Combobox.${part}> must be rendered inside <Combobox.Root>.`);
166
+ }
167
+ return context;
168
+ }
169
+
170
+ // src/combobox/ComboboxRoot.tsx
171
+ var import_jsx_runtime = require("react/jsx-runtime");
172
+ function defaultItemToString(item) {
173
+ if (typeof item === "string") return item;
174
+ if (item !== null && typeof item === "object" && "label" in item) return String(item.label);
175
+ return String(item);
176
+ }
177
+ function ComboboxRoot({
178
+ items,
179
+ itemToString: itemToStringProp,
180
+ itemToKey: itemToKeyProp,
181
+ filter,
182
+ multiple: multipleProp,
183
+ value: valueProp,
184
+ defaultValue,
185
+ onValueChange,
186
+ inputValue: inputValueProp,
187
+ defaultInputValue,
188
+ onInputValueChange,
189
+ open: openProp,
190
+ defaultOpen,
191
+ onOpenChange,
192
+ onItemHighlighted,
193
+ onLoadMore,
194
+ loading = false,
195
+ disabled = false,
196
+ name,
197
+ form,
198
+ children
199
+ }) {
200
+ const multiple = multipleProp === true;
201
+ const itemToString = itemToStringProp ?? defaultItemToString;
202
+ const itemToKey = itemToKeyProp ?? itemToString;
203
+ const [value, setValueState] = useControlled({
204
+ controlled: valueProp,
205
+ default: defaultValue ?? (multiple ? [] : null),
206
+ name: "Combobox.Root",
207
+ state: "value"
208
+ });
209
+ const selectedItems = (0, import_react3.useMemo)(
210
+ () => multiple ? value : value == null ? [] : [value],
211
+ [multiple, value]
212
+ );
213
+ const selectedKeys = (0, import_react3.useMemo)(
214
+ () => new Set(selectedItems.map((item) => itemToKey(item))),
215
+ [selectedItems, itemToKey]
216
+ );
217
+ const selectedLabel = !multiple && selectedItems[0] != null ? itemToString(selectedItems[0]) : "";
218
+ const [inputValue, setInputValueState] = useControlled({
219
+ controlled: inputValueProp,
220
+ default: defaultInputValue ?? selectedLabel,
221
+ name: "Combobox.Root",
222
+ state: "inputValue"
223
+ });
224
+ const [open, setOpenState] = useControlled({
225
+ controlled: openProp,
226
+ default: defaultOpen ?? false,
227
+ name: "Combobox.Root",
228
+ state: "open"
229
+ });
230
+ const query = !multiple && inputValue === selectedLabel ? "" : inputValue;
231
+ const deferredQuery = (0, import_react3.useDeferredValue)(query);
232
+ const filteredItems = (0, import_react3.useMemo)(() => {
233
+ if (filter === null) return items;
234
+ const run = filter ?? defaultFilter;
235
+ return run(items, deferredQuery, itemToString);
236
+ }, [items, filter, deferredQuery, itemToString]);
237
+ const indexByKey = (0, import_react3.useMemo)(
238
+ () => new Map(filteredItems.map((item, index) => [itemToKey(item), index])),
239
+ [filteredItems, itemToKey]
240
+ );
241
+ const [highlight] = (0, import_react3.useState)(createHighlightStore);
242
+ const setHighlight = (0, import_react3.useCallback)(
243
+ (index, reason) => {
244
+ if (highlight.get().index === index && highlight.get().reason === reason) return;
245
+ highlight.set({ index, reason });
246
+ onItemHighlighted?.(filteredItems[index], { index, reason });
247
+ },
248
+ [highlight, filteredItems, onItemHighlighted]
249
+ );
250
+ (0, import_react3.useEffect)(() => {
251
+ if (highlight.get().index !== -1) setHighlight(-1, "none");
252
+ }, [filteredItems]);
253
+ const setValue = (0, import_react3.useCallback)(
254
+ (next, reason) => {
255
+ setValueState(next);
256
+ onValueChange?.(next, {
257
+ reason
258
+ });
259
+ },
260
+ [setValueState, onValueChange]
261
+ );
262
+ const setInputValue = (0, import_react3.useCallback)(
263
+ (next, reason) => {
264
+ if (next === inputValue) return;
265
+ setInputValueState(next);
266
+ onInputValueChange?.(next, { reason });
267
+ },
268
+ [inputValue, setInputValueState, onInputValueChange]
269
+ );
270
+ const setOpen = (0, import_react3.useCallback)(
271
+ (next, reason) => {
272
+ if (next === open) return;
273
+ setOpenState(next);
274
+ onOpenChange?.(next, { reason });
275
+ if (!next) setHighlight(-1, "none");
276
+ },
277
+ [open, setOpenState, onOpenChange, setHighlight]
278
+ );
279
+ const close = (0, import_react3.useCallback)(
280
+ (reason) => {
281
+ setOpen(false, reason);
282
+ setInputValue(selectedLabel, reason);
283
+ },
284
+ [setOpen, setInputValue, selectedLabel]
285
+ );
286
+ const select = (0, import_react3.useCallback)(
287
+ (item) => {
288
+ const key = itemToKey(item);
289
+ if (multiple) {
290
+ const current = value;
291
+ setValue(
292
+ selectedKeys.has(key) ? current.filter((i) => itemToKey(i) !== key) : [...current, item],
293
+ "item-press"
294
+ );
295
+ setInputValue("", "item-press");
296
+ } else {
297
+ if (!selectedKeys.has(key)) setValue(item, "item-press");
298
+ setInputValue(itemToString(item), "item-press");
299
+ }
300
+ setOpen(false, "item-press");
301
+ },
302
+ [multiple, value, selectedKeys, itemToKey, itemToString, setValue, setInputValue, setOpen]
303
+ );
304
+ const remove = (0, import_react3.useCallback)(
305
+ (item, reason) => {
306
+ if (!multiple) return;
307
+ const key = itemToKey(item);
308
+ setValue(
309
+ value.filter((i) => itemToKey(i) !== key),
310
+ reason
311
+ );
312
+ },
313
+ [multiple, value, itemToKey, setValue]
314
+ );
315
+ const clearSelection = (0, import_react3.useCallback)(
316
+ (reason) => setValue(multiple ? [] : null, reason),
317
+ [multiple, setValue]
318
+ );
319
+ const clear = (0, import_react3.useCallback)(() => {
320
+ setInputValue("", "clear");
321
+ clearSelection("clear");
322
+ setHighlight(-1, "none");
323
+ }, [setInputValue, clearSelection, setHighlight]);
324
+ const selectedKey = !multiple && selectedItems[0] != null ? itemToKey(selectedItems[0]) : null;
325
+ const lastSelectedKeyRef = (0, import_react3.useRef)(selectedKey);
326
+ (0, import_react3.useEffect)(() => {
327
+ if (lastSelectedKeyRef.current === selectedKey) return;
328
+ lastSelectedKeyRef.current = selectedKey;
329
+ setInputValueState(selectedLabel);
330
+ }, [selectedKey]);
331
+ const [chips, setChips] = (0, import_react3.useState)([]);
332
+ const registerChip = (0, import_react3.useCallback)((entry) => {
333
+ setChips((current) => [...current, entry].sort(byDocumentOrder));
334
+ return () => setChips((current) => current.filter((c) => c !== entry));
335
+ }, []);
336
+ const [disabledKeys] = (0, import_react3.useState)(() => /* @__PURE__ */ new Set());
337
+ const [insideRefs] = (0, import_react3.useState)(() => /* @__PURE__ */ new Set());
338
+ const registerInside = (0, import_react3.useCallback)(
339
+ (ref) => {
340
+ insideRefs.add(ref);
341
+ return () => {
342
+ insideRefs.delete(ref);
343
+ };
344
+ },
345
+ [insideRefs]
346
+ );
347
+ const [hasGroup, setHasGroup] = (0, import_react3.useState)(false);
348
+ const registerGroup = (0, import_react3.useCallback)(() => {
349
+ setHasGroup(true);
350
+ return () => setHasGroup(false);
351
+ }, []);
352
+ const inputRef = (0, import_react3.useRef)(null);
353
+ const popupRef = (0, import_react3.useRef)(null);
354
+ const { current: initial } = (0, import_react3.useRef)({ value, inputValue });
355
+ (0, import_react3.useEffect)(() => {
356
+ const owner = inputRef.current?.form;
357
+ if (!owner) return;
358
+ function onReset(event) {
359
+ queueMicrotask(() => {
360
+ if (event.defaultPrevented) return;
361
+ if (value !== initial.value) setValue(initial.value, "form-reset");
362
+ setInputValue(initial.inputValue, "form-reset");
363
+ });
364
+ }
365
+ owner.addEventListener("reset", onReset);
366
+ return () => owner.removeEventListener("reset", onReset);
367
+ }, [value, initial, setValue, setInputValue]);
368
+ const isInside = (0, import_react3.useCallback)(
369
+ (node) => [inputRef, popupRef, ...insideRefs, ...chips.map((chip) => chip.ref)].some(
370
+ (ref) => ref.current?.contains(node) ?? false
371
+ ),
372
+ [insideRefs, chips]
373
+ );
374
+ const id = (0, import_react3.useId)();
375
+ const context = (0, import_react3.useMemo)(
376
+ () => ({
377
+ open,
378
+ multiple,
379
+ disabled,
380
+ inputValue,
381
+ loading,
382
+ filteredItems,
383
+ itemToString,
384
+ itemToKey,
385
+ indexByKey,
386
+ selectedKeys,
387
+ selectedItems,
388
+ disabledKeys,
389
+ highlight,
390
+ setHighlight,
391
+ setOpen,
392
+ setInputValue,
393
+ select,
394
+ remove,
395
+ clearSelection,
396
+ clear,
397
+ close,
398
+ registerChip,
399
+ chips,
400
+ registerInside,
401
+ isInside,
402
+ hasGroup,
403
+ registerGroup,
404
+ onLoadMore,
405
+ inputId: `${id}-input`,
406
+ listId: `${id}-list`,
407
+ optionId: (index) => `${id}-option-${index}`,
408
+ anchorName: anchorNameFor(id),
409
+ inputRef,
410
+ popupRef
411
+ }),
412
+ [
413
+ open,
414
+ multiple,
415
+ disabled,
416
+ inputValue,
417
+ loading,
418
+ filteredItems,
419
+ itemToString,
420
+ itemToKey,
421
+ indexByKey,
422
+ selectedKeys,
423
+ selectedItems,
424
+ disabledKeys,
425
+ highlight,
426
+ setHighlight,
427
+ setOpen,
428
+ setInputValue,
429
+ select,
430
+ remove,
431
+ clearSelection,
432
+ clear,
433
+ close,
434
+ registerChip,
435
+ chips,
436
+ registerInside,
437
+ isInside,
438
+ hasGroup,
439
+ registerGroup,
440
+ onLoadMore,
441
+ id
442
+ ]
443
+ );
444
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ComboboxRootContext.Provider, { value: context, children: [
445
+ children,
446
+ name !== void 0 && (multiple ? selectedItems : [selectedItems[0] ?? null]).map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
447
+ "input",
448
+ {
449
+ type: "hidden",
450
+ name,
451
+ form,
452
+ disabled,
453
+ value: item === null ? "" : itemToKey(item)
454
+ },
455
+ item === null ? index : itemToKey(item)
456
+ ))
457
+ ] });
458
+ }
459
+
460
+ // src/combobox/ComboboxInput.tsx
461
+ var import_react5 = require("react");
462
+
463
+ // src/core/useRender.ts
464
+ var import_react4 = require("react");
465
+
466
+ // src/core/mergeProps.ts
467
+ function isEventHandler(key) {
468
+ return key.length > 2 && key.startsWith("on") && key[2] === key[2]?.toUpperCase();
469
+ }
470
+ function mergeRefs(...refs) {
471
+ return (node) => {
472
+ const cleanups = refs.map((ref) => {
473
+ if (typeof ref === "function") {
474
+ const result = ref(node);
475
+ return typeof result === "function" ? result : () => ref(null);
476
+ }
477
+ if (ref && typeof ref === "object") {
478
+ ref.current = node;
479
+ return () => {
480
+ ref.current = null;
481
+ };
482
+ }
483
+ return void 0;
484
+ });
485
+ return () => {
486
+ cleanups.forEach((cleanup) => {
487
+ if (typeof cleanup === "function") cleanup();
488
+ });
489
+ };
490
+ };
491
+ }
492
+ function isSyntheticEvent(event) {
493
+ return typeof event === "object" && event !== null && "nativeEvent" in event;
494
+ }
495
+ function makeEventPreventable(event) {
496
+ if (Object.prototype.hasOwnProperty.call(event, "preventComponentHandler")) return;
497
+ const target = event;
498
+ target.preventComponentHandler = () => {
499
+ target.componentHandlerPrevented = true;
500
+ };
501
+ }
502
+ function isComponentHandlerPrevented(event) {
503
+ return typeof event === "object" && event !== null && event.componentHandlerPrevented === true;
504
+ }
505
+ function chainHandlers(earlier, value) {
506
+ return (...args) => {
507
+ const event = args[0];
508
+ if (isSyntheticEvent(event)) makeEventPreventable(event);
509
+ value(...args);
510
+ if (isComponentHandlerPrevented(event)) return;
511
+ earlier(...args);
512
+ };
513
+ }
514
+ function mergeProps(...objects) {
515
+ const merged = {};
516
+ for (const props of objects) {
517
+ if (!props) continue;
518
+ for (const key of Object.keys(props)) {
519
+ const value = props[key];
520
+ if (value === void 0) continue;
521
+ if (isEventHandler(key) && typeof value === "function") {
522
+ const earlier = merged[key];
523
+ merged[key] = typeof earlier === "function" ? chainHandlers(earlier, value) : value;
524
+ } else if (key === "className") {
525
+ merged.className = merged.className ? `${String(merged.className)} ${String(value)}` : value;
526
+ } else if (key === "style") {
527
+ merged.style = { ...merged.style, ...value };
528
+ } else if (key === "ref") {
529
+ merged.ref = merged.ref ? mergeRefs(merged.ref, value) : value;
530
+ } else {
531
+ merged[key] = value;
532
+ }
533
+ }
534
+ }
535
+ return merged;
536
+ }
537
+
538
+ // src/core/useRender.ts
539
+ function useRender({
540
+ render,
541
+ defaultTagName,
542
+ props,
543
+ consumerProps
544
+ }) {
545
+ const merged = mergeProps(props, consumerProps);
546
+ if ((0, import_react4.isValidElement)(render)) {
547
+ return (0, import_react4.cloneElement)(render, mergeProps(merged, render.props));
548
+ }
549
+ return (0, import_react4.createElement)(defaultTagName, merged);
550
+ }
551
+
552
+ // src/combobox/comboboxDataAttributes.ts
553
+ function comboboxDataAttributes({ open, disabled }) {
554
+ return {
555
+ "data-open": open ? "" : void 0,
556
+ "data-closed": open ? void 0 : "",
557
+ "data-disabled": disabled ? "" : void 0
558
+ };
559
+ }
560
+ function comboboxItemDataAttributes({
561
+ selected,
562
+ highlighted,
563
+ disabled
564
+ }) {
565
+ return {
566
+ "data-selected": selected ? "" : void 0,
567
+ "data-highlighted": highlighted ? "" : void 0,
568
+ "data-disabled": disabled ? "" : void 0
569
+ };
570
+ }
571
+ function comboboxClearDataAttributes(visible) {
572
+ return { "data-visible": visible ? "" : void 0 };
573
+ }
574
+
575
+ // src/combobox/ComboboxInput.tsx
576
+ function ComboboxInput({ className, render, ...rest }) {
577
+ const {
578
+ open,
579
+ multiple,
580
+ disabled,
581
+ inputValue,
582
+ filteredItems,
583
+ itemToKey,
584
+ selectedItems,
585
+ selectedKeys,
586
+ disabledKeys,
587
+ highlight,
588
+ setHighlight,
589
+ setOpen,
590
+ setInputValue,
591
+ select,
592
+ remove,
593
+ clearSelection,
594
+ close,
595
+ chips,
596
+ inputId,
597
+ listId,
598
+ optionId,
599
+ anchorName,
600
+ hasGroup,
601
+ inputRef,
602
+ popupRef
603
+ } = useComboboxRootContext("Input");
604
+ const highlighted = (0, import_react5.useSyncExternalStore)(
605
+ highlight.subscribe,
606
+ () => highlight.get().index,
607
+ () => -1
608
+ );
609
+ function enabledIndices() {
610
+ const indices = [];
611
+ filteredItems.forEach((item, index) => {
612
+ if (!disabledKeys.has(itemToKey(item))) indices.push(index);
613
+ });
614
+ return indices;
615
+ }
616
+ function openingIndex(key, enabled) {
617
+ if (!multiple && selectedItems[0] != null) {
618
+ const selected = enabled.find((i) => selectedKeys.has(itemToKey(filteredItems[i])));
619
+ if (selected !== void 0) return selected;
620
+ }
621
+ return (key === "ArrowDown" ? enabled[0] : enabled.at(-1)) ?? -1;
622
+ }
623
+ function moveHighlight(key) {
624
+ const enabled = enabledIndices();
625
+ const next = rovingIndex(key, {
626
+ count: enabled.length,
627
+ current: enabled.indexOf(highlighted),
628
+ orientation: "vertical",
629
+ rtl: false
630
+ });
631
+ if (next !== null) setHighlight(enabled[next] ?? -1, "keyboard");
632
+ }
633
+ return useRender({
634
+ render,
635
+ defaultTagName: "input",
636
+ props: {
637
+ id: inputId,
638
+ type: "text",
639
+ role: "combobox",
640
+ autoComplete: "off",
641
+ "aria-autocomplete": "list",
642
+ "aria-expanded": open,
643
+ "aria-controls": listId,
644
+ "aria-activedescendant": open && highlighted >= 0 ? optionId(highlighted) : void 0,
645
+ disabled: disabled || void 0,
646
+ value: inputValue,
647
+ ...comboboxDataAttributes({ open, multiple, disabled }),
648
+ // The anchor, unless an InputGroup around it is.
649
+ style: hasGroup ? void 0 : { anchorName },
650
+ className,
651
+ ref: inputRef,
652
+ onChange(event) {
653
+ const text = event.target.value;
654
+ setInputValue(text, "input");
655
+ if (!multiple && text === "" && selectedItems.length > 0) clearSelection("input");
656
+ setOpen(true, "input");
657
+ },
658
+ onClick() {
659
+ if (!disabled) setOpen(true, "input-press");
660
+ },
661
+ onKeyDown(event) {
662
+ const { key } = event;
663
+ if (key === "ArrowDown" || key === "ArrowUp") {
664
+ event.preventDefault();
665
+ if (!open) {
666
+ setOpen(true, "keyboard");
667
+ if (!event.altKey) setHighlight(openingIndex(key, enabledIndices()), "keyboard");
668
+ return;
669
+ }
670
+ moveHighlight(key);
671
+ return;
672
+ }
673
+ if ((key === "Home" || key === "End") && open) {
674
+ event.preventDefault();
675
+ moveHighlight(key);
676
+ return;
677
+ }
678
+ if (key === "Enter") {
679
+ if (!open || highlighted < 0) return;
680
+ event.preventDefault();
681
+ const item = filteredItems[highlighted];
682
+ if (!disabledKeys.has(itemToKey(item))) select(item);
683
+ return;
684
+ }
685
+ if (key === "Escape") {
686
+ if (!open) return;
687
+ event.preventDefault();
688
+ close("escape");
689
+ return;
690
+ }
691
+ if (!multiple) return;
692
+ if (key === "Backspace" && inputValue === "" && selectedItems.length > 0) {
693
+ remove(selectedItems.at(-1), "chip-remove");
694
+ return;
695
+ }
696
+ const input = event.currentTarget;
697
+ if (key === "ArrowLeft" && chips.length > 0 && input.selectionStart === 0 && input.selectionEnd === 0) {
698
+ event.preventDefault();
699
+ chips.at(-1)?.ref.current?.focus();
700
+ }
701
+ },
702
+ onBlur(event) {
703
+ const next = event.relatedTarget;
704
+ if (next && popupRef.current?.contains(next)) return;
705
+ if (next && chips.some((chip) => chip.ref.current === next)) {
706
+ setOpen(false, "blur");
707
+ return;
708
+ }
709
+ close("blur");
710
+ }
711
+ },
712
+ consumerProps: rest
713
+ });
714
+ }
715
+
716
+ // src/combobox/ComboboxInputGroup.tsx
717
+ var import_react6 = require("react");
718
+ function ComboboxInputGroup({
719
+ className,
720
+ children,
721
+ render,
722
+ ...rest
723
+ }) {
724
+ const { open, multiple, disabled, anchorName, registerGroup, registerInside, inputRef } = useComboboxRootContext("InputGroup");
725
+ const elementRef = (0, import_react6.useRef)(null);
726
+ (0, import_react6.useLayoutEffect)(() => registerGroup(), [registerGroup]);
727
+ (0, import_react6.useLayoutEffect)(() => registerInside(elementRef), [registerInside]);
728
+ return useRender({
729
+ render,
730
+ defaultTagName: "div",
731
+ props: {
732
+ ...comboboxDataAttributes({ open, multiple, disabled }),
733
+ style: { anchorName },
734
+ className,
735
+ children,
736
+ ref: elementRef,
737
+ onMouseDown(event) {
738
+ if (event.target !== event.currentTarget || disabled) return;
739
+ event.preventDefault();
740
+ inputRef.current?.focus();
741
+ }
742
+ },
743
+ consumerProps: rest
744
+ });
745
+ }
746
+
747
+ // src/combobox/ComboboxTrigger.tsx
748
+ var import_react7 = require("react");
749
+ function ComboboxTrigger({ className, children, render, ...rest }) {
750
+ const { open, multiple, disabled, setOpen, close, listId, inputRef, registerInside } = useComboboxRootContext("Trigger");
751
+ const elementRef = (0, import_react7.useRef)(null);
752
+ (0, import_react7.useLayoutEffect)(() => registerInside(elementRef), [registerInside]);
753
+ return useRender({
754
+ render,
755
+ defaultTagName: "button",
756
+ props: {
757
+ type: "button",
758
+ tabIndex: -1,
759
+ "aria-expanded": open,
760
+ "aria-controls": listId,
761
+ disabled: disabled || void 0,
762
+ ...comboboxDataAttributes({ open, multiple, disabled }),
763
+ className,
764
+ children,
765
+ ref: elementRef,
766
+ onMouseDown(event) {
767
+ event.preventDefault();
768
+ },
769
+ onClick() {
770
+ if (open) close("trigger-press");
771
+ else setOpen(true, "trigger-press");
772
+ inputRef.current?.focus();
773
+ }
774
+ },
775
+ consumerProps: rest
776
+ });
777
+ }
778
+
779
+ // src/combobox/ComboboxClear.tsx
780
+ var import_react8 = require("react");
781
+ function ComboboxClear({ className, children, render, ...rest }) {
782
+ const { disabled, selectedItems, clear, inputRef, registerInside } = useComboboxRootContext("Clear");
783
+ const elementRef = (0, import_react8.useRef)(null);
784
+ (0, import_react8.useLayoutEffect)(() => registerInside(elementRef), [registerInside]);
785
+ return useRender({
786
+ render,
787
+ defaultTagName: "button",
788
+ props: {
789
+ type: "button",
790
+ tabIndex: -1,
791
+ disabled: disabled || void 0,
792
+ ...comboboxClearDataAttributes(selectedItems.length > 0),
793
+ className,
794
+ children,
795
+ ref: elementRef,
796
+ onMouseDown(event) {
797
+ event.preventDefault();
798
+ },
799
+ onClick() {
800
+ if (disabled) return;
801
+ clear();
802
+ inputRef.current?.focus();
803
+ }
804
+ },
805
+ consumerProps: rest
806
+ });
807
+ }
808
+
809
+ // src/combobox/ComboboxPopup.tsx
810
+ var import_react9 = require("react");
811
+ function ComboboxPopup({
812
+ side = "bottom",
813
+ align = "start",
814
+ className,
815
+ children,
816
+ render,
817
+ ...rest
818
+ }) {
819
+ const { open, multiple, disabled, setOpen, close, isInside, anchorName, inputRef, popupRef } = useComboboxRootContext("Popup");
820
+ (0, import_react9.useEffect)(() => {
821
+ if (!open) return;
822
+ function onPointerDown(event) {
823
+ if (event.target instanceof Node && isInside(event.target)) return;
824
+ close("outside-press");
825
+ }
826
+ document.addEventListener("pointerdown", onPointerDown, true);
827
+ return () => document.removeEventListener("pointerdown", onPointerDown, true);
828
+ }, [open, isInside, close]);
829
+ const [, resync] = (0, import_react9.useReducer)((n) => n + 1, 0);
830
+ (0, import_react9.useEffect)(() => {
831
+ const popup = popupRef.current;
832
+ if (!popup || typeof popup.showPopover !== "function") return;
833
+ const shown = popup.matches(":popover-open");
834
+ if (open && !shown) {
835
+ popup.showPopover({ source: inputRef.current ?? void 0 });
836
+ if (!popup.matches(":popover-open")) setOpen(false, "outside-press");
837
+ } else if (!open && shown) {
838
+ popup.hidePopover();
839
+ }
840
+ });
841
+ return useRender({
842
+ render,
843
+ defaultTagName: "div",
844
+ props: {
845
+ popover: "manual",
846
+ ...anchoredDataAttributes(side, align),
847
+ ...comboboxDataAttributes({ open, multiple, disabled }),
848
+ style: anchoredPopupStyle(anchorName, side, align),
849
+ className,
850
+ children,
851
+ ref: popupRef,
852
+ onMouseDown(event) {
853
+ event.preventDefault();
854
+ },
855
+ onToggle(event) {
856
+ if (event.target !== event.currentTarget) return;
857
+ if (event.nativeEvent.newState !== "closed") return;
858
+ close("outside-press");
859
+ resync();
860
+ }
861
+ },
862
+ consumerProps: rest
863
+ });
864
+ }
865
+
866
+ // src/combobox/ComboboxList.tsx
867
+ var import_react10 = require("react");
868
+ var import_jsx_runtime2 = require("react/jsx-runtime");
869
+ function ComboboxList({
870
+ className,
871
+ children,
872
+ render,
873
+ ...rest
874
+ }) {
875
+ const { multiple, loading, filteredItems, onLoadMore, listId } = useComboboxRootContext("List");
876
+ const content = typeof children === "function" ? filteredItems.map((item, index) => children(item, index)) : children;
877
+ return useRender({
878
+ render,
879
+ defaultTagName: "div",
880
+ props: {
881
+ id: listId,
882
+ role: "listbox",
883
+ "aria-multiselectable": multiple || void 0,
884
+ "aria-busy": loading || void 0,
885
+ className,
886
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
887
+ content,
888
+ onLoadMore && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LoadMoreSentinel, {})
889
+ ] })
890
+ },
891
+ consumerProps: rest
892
+ });
893
+ }
894
+ function LoadMoreSentinel() {
895
+ const { open, loading, filteredItems, onLoadMore } = useComboboxRootContext("List");
896
+ const ref = (0, import_react10.useRef)(null);
897
+ const onLoadMoreRef = (0, import_react10.useRef)(onLoadMore);
898
+ onLoadMoreRef.current = onLoadMore;
899
+ (0, import_react10.useEffect)(() => {
900
+ const element = ref.current;
901
+ if (!element || !open || loading || typeof IntersectionObserver === "undefined") return;
902
+ const observer = new IntersectionObserver((entries) => {
903
+ if (entries.some((entry) => entry.isIntersecting)) onLoadMoreRef.current?.();
904
+ });
905
+ observer.observe(element);
906
+ return () => observer.disconnect();
907
+ }, [open, loading, filteredItems.length]);
908
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref, "aria-hidden": "true", "data-load-more": "", style: { blockSize: 1 } });
909
+ }
910
+
911
+ // src/combobox/ComboboxItem.tsx
912
+ var import_react11 = require("react");
913
+ function ComboboxItem({
914
+ value,
915
+ disabled = false,
916
+ className,
917
+ children,
918
+ render,
919
+ ...rest
920
+ }) {
921
+ const {
922
+ itemToKey,
923
+ indexByKey,
924
+ selectedKeys,
925
+ disabledKeys,
926
+ highlight,
927
+ setHighlight,
928
+ select,
929
+ optionId
930
+ } = useComboboxRootContext("Item");
931
+ const key = itemToKey(value);
932
+ const index = indexByKey.get(key) ?? -1;
933
+ const selected = selectedKeys.has(key);
934
+ const highlighted = (0, import_react11.useSyncExternalStore)(
935
+ highlight.subscribe,
936
+ () => index >= 0 && highlight.get().index === index,
937
+ () => false
938
+ );
939
+ const elementRef = (0, import_react11.useRef)(null);
940
+ (0, import_react11.useLayoutEffect)(() => {
941
+ if (!disabled) return;
942
+ disabledKeys.add(key);
943
+ return () => {
944
+ disabledKeys.delete(key);
945
+ };
946
+ }, [disabled, disabledKeys, key]);
947
+ (0, import_react11.useEffect)(() => {
948
+ if (highlighted && highlight.get().reason === "keyboard") {
949
+ elementRef.current?.scrollIntoView?.({ block: "nearest" });
950
+ }
951
+ }, [highlighted, highlight]);
952
+ return useRender({
953
+ render,
954
+ defaultTagName: "div",
955
+ props: {
956
+ id: index >= 0 ? optionId(index) : void 0,
957
+ role: "option",
958
+ "aria-selected": selected,
959
+ "aria-disabled": disabled || void 0,
960
+ ...comboboxItemDataAttributes({ selected, highlighted, disabled }),
961
+ className,
962
+ children,
963
+ ref: elementRef,
964
+ onMouseDown(event) {
965
+ event.preventDefault();
966
+ },
967
+ onPointerMove() {
968
+ if (!disabled && !highlighted && index >= 0) setHighlight(index, "pointer");
969
+ },
970
+ onClick() {
971
+ if (!disabled) select(value);
972
+ }
973
+ },
974
+ consumerProps: rest
975
+ });
976
+ }
977
+
978
+ // src/combobox/ComboboxEmpty.tsx
979
+ function ComboboxEmpty({ className, children, render, ...rest }) {
980
+ const { filteredItems, loading } = useComboboxRootContext("Empty");
981
+ const element = useRender({
982
+ render,
983
+ defaultTagName: "div",
984
+ props: { className, children },
985
+ consumerProps: rest
986
+ });
987
+ return filteredItems.length === 0 && !loading ? element : null;
988
+ }
989
+
990
+ // src/combobox/ComboboxStatus.tsx
991
+ function ComboboxStatus({ className, children, render, ...rest }) {
992
+ useComboboxRootContext("Status");
993
+ return useRender({
994
+ render,
995
+ defaultTagName: "div",
996
+ props: { role: "status", "aria-live": "polite", "aria-atomic": true, className, children },
997
+ consumerProps: rest
998
+ });
999
+ }
1000
+
1001
+ // src/combobox/ComboboxChip.tsx
1002
+ var import_react12 = require("react");
1003
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1004
+ var ComboboxChipContext = (0, import_react12.createContext)(null);
1005
+ function useComboboxChipContext() {
1006
+ const context = (0, import_react12.useContext)(ComboboxChipContext);
1007
+ if (context === null) {
1008
+ throw new Error("<Combobox.ChipRemove> must be rendered inside <Combobox.Chip>.");
1009
+ }
1010
+ return context;
1011
+ }
1012
+ function ComboboxChip({
1013
+ value,
1014
+ className,
1015
+ children,
1016
+ render,
1017
+ ...rest
1018
+ }) {
1019
+ const { disabled, itemToKey, remove, registerChip, chips, inputRef } = useComboboxRootContext("Chip");
1020
+ const key = itemToKey(value);
1021
+ const elementRef = (0, import_react12.useRef)(null);
1022
+ (0, import_react12.useLayoutEffect)(() => registerChip({ key, ref: elementRef }), [registerChip, key]);
1023
+ const chipContext = (0, import_react12.useMemo)(() => ({ value }), [value]);
1024
+ function focusAt(index) {
1025
+ const chip = chips[index];
1026
+ if (chip) chip.ref.current?.focus();
1027
+ else inputRef.current?.focus();
1028
+ }
1029
+ const element = useRender({
1030
+ render,
1031
+ defaultTagName: "div",
1032
+ props: {
1033
+ tabIndex: -1,
1034
+ "data-disabled": disabled ? "" : void 0,
1035
+ className,
1036
+ children,
1037
+ ref: elementRef,
1038
+ onKeyDown(event) {
1039
+ const index = chips.findIndex((chip) => chip.ref.current === elementRef.current);
1040
+ switch (event.key) {
1041
+ case "ArrowLeft":
1042
+ event.preventDefault();
1043
+ if (index > 0) focusAt(index - 1);
1044
+ return;
1045
+ case "ArrowRight":
1046
+ event.preventDefault();
1047
+ focusAt(index + 1);
1048
+ return;
1049
+ case "Backspace":
1050
+ case "Delete":
1051
+ event.preventDefault();
1052
+ if (disabled) return;
1053
+ remove(value, "chip-remove");
1054
+ focusAt(index + 1 < chips.length ? index + 1 : chips.length);
1055
+ return;
1056
+ case "Escape":
1057
+ inputRef.current?.focus();
1058
+ return;
1059
+ }
1060
+ }
1061
+ },
1062
+ consumerProps: rest
1063
+ });
1064
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ComboboxChipContext.Provider, { value: chipContext, children: element });
1065
+ }
1066
+
1067
+ // src/combobox/ComboboxChipRemove.tsx
1068
+ function ComboboxChipRemove({
1069
+ className,
1070
+ children,
1071
+ render,
1072
+ ...rest
1073
+ }) {
1074
+ const { disabled, remove, inputRef } = useComboboxRootContext("ChipRemove");
1075
+ const { value } = useComboboxChipContext();
1076
+ return useRender({
1077
+ render,
1078
+ defaultTagName: "button",
1079
+ props: {
1080
+ type: "button",
1081
+ tabIndex: -1,
1082
+ disabled: disabled || void 0,
1083
+ className,
1084
+ children,
1085
+ onMouseDown(event) {
1086
+ event.preventDefault();
1087
+ },
1088
+ onClick() {
1089
+ if (disabled) return;
1090
+ remove(value, "chip-remove");
1091
+ inputRef.current?.focus();
1092
+ }
1093
+ },
1094
+ consumerProps: rest
1095
+ });
1096
+ }
1097
+
1098
+ // src/combobox/ComboboxValue.tsx
1099
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1100
+ function ComboboxValue({ children }) {
1101
+ const { multiple, selectedItems, itemToString } = useComboboxRootContext("Value");
1102
+ const value = multiple ? selectedItems : selectedItems[0] ?? null;
1103
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: children(value, { itemToString }) });
1104
+ }
1105
+ // Annotate the CommonJS export names for ESM import in node:
1106
+ 0 && (module.exports = {
1107
+ Combobox,
1108
+ defaultFilter
1109
+ });