@yamada-ui/autocomplete 0.1.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,1685 @@
1
+ // src/autocomplete-list.tsx
2
+ import { forwardRef as forwardRef8 } from "@yamada-ui/core";
3
+ import { PopoverContent } from "@yamada-ui/popover";
4
+ import { cx as cx8 } from "@yamada-ui/utils";
5
+
6
+ // src/use-autocomplete.tsx
7
+ import { layoutStylesProperties } from "@yamada-ui/core";
8
+ import {
9
+ formControlProperties,
10
+ useFormControlProps
11
+ } from "@yamada-ui/form-control";
12
+ import { useControllableState } from "@yamada-ui/use-controllable-state";
13
+ import { createDescendant } from "@yamada-ui/use-descendant";
14
+ import { useOutsideClick } from "@yamada-ui/use-outside-click";
15
+ import {
16
+ ariaAttr,
17
+ createContext,
18
+ dataAttr,
19
+ funcAll,
20
+ getEventRelatedTarget,
21
+ handlerAll as handlerAll2,
22
+ isArray,
23
+ isContains,
24
+ isHTMLElement,
25
+ mergeRefs,
26
+ omitObject,
27
+ pickObject,
28
+ splitObject,
29
+ useUnmountEffect,
30
+ useUpdateEffect,
31
+ getValidChildren as getValidChildren2,
32
+ isUndefined
33
+ } from "@yamada-ui/utils";
34
+ import {
35
+ useCallback,
36
+ useEffect,
37
+ useRef as useRef2,
38
+ useState
39
+ } from "react";
40
+
41
+ // src/autocomplete.tsx
42
+ import {
43
+ ui as ui2,
44
+ forwardRef as forwardRef2,
45
+ useMultiComponentStyle,
46
+ omitThemeProps
47
+ } from "@yamada-ui/core";
48
+ import { Popover, PopoverTrigger } from "@yamada-ui/popover";
49
+ import { cx as cx2 } from "@yamada-ui/utils";
50
+
51
+ // src/autocomplete-icon.tsx
52
+ import { ui, forwardRef } from "@yamada-ui/core";
53
+ import { ChevronIcon, CloseIcon } from "@yamada-ui/icon";
54
+ import { useClickable } from "@yamada-ui/use-clickable";
55
+ import { cx, getValidChildren, isValidElement } from "@yamada-ui/utils";
56
+ import { cloneElement, useRef } from "react";
57
+ import { jsx } from "react/jsx-runtime";
58
+ var AutocompleteIcon = forwardRef(
59
+ ({ className, children, __css, ...rest }, ref) => {
60
+ const { styles } = useAutocompleteContext();
61
+ const css = {
62
+ position: "absolute",
63
+ top: "50%",
64
+ transform: "translateY(-50%)",
65
+ display: "inline-flex",
66
+ alignItems: "center",
67
+ justifyContent: "center",
68
+ pointerEvents: "none",
69
+ cursor: "pointer",
70
+ ...styles.icon,
71
+ ...__css
72
+ };
73
+ const validChildren = getValidChildren(children);
74
+ const cloneChildren = validChildren.map(
75
+ (child) => cloneElement(child, {
76
+ focusable: false,
77
+ "aria-hidden": true,
78
+ style: {
79
+ maxWidth: "1em",
80
+ maxHeight: "1em",
81
+ color: "currentColor"
82
+ }
83
+ })
84
+ );
85
+ return /* @__PURE__ */ jsx(ui.div, { ref, className: cx("ui-autocomplete-icon", className), __css: css, ...rest, children: isValidElement(children) ? cloneChildren : /* @__PURE__ */ jsx(ChevronIcon, {}) });
86
+ }
87
+ );
88
+ var AutocompleteClearIcon = ({
89
+ className,
90
+ children,
91
+ ...props
92
+ }) => {
93
+ const ref = useRef(null);
94
+ const { styles } = useAutocompleteContext();
95
+ const isDisabled = props.disabled;
96
+ const rest = useClickable({
97
+ ref,
98
+ isDisabled,
99
+ ...props
100
+ });
101
+ return /* @__PURE__ */ jsx(
102
+ AutocompleteIcon,
103
+ {
104
+ className: cx("ui-autocomplete-clear-icon", className),
105
+ __css: styles.clearIcon,
106
+ ...rest,
107
+ children: children != null ? children : /* @__PURE__ */ jsx(CloseIcon, { w: "0.5em", h: "0.5em" })
108
+ }
109
+ );
110
+ };
111
+ var AutocompleteItemIcon = forwardRef(
112
+ ({ className, ...rest }, ref) => {
113
+ const { styles } = useAutocompleteContext();
114
+ const css = {
115
+ flexShrink: 0,
116
+ display: "inline-flex",
117
+ justifyContent: "center",
118
+ alignItems: "center",
119
+ fontSize: "0.85em",
120
+ ...styles.itemIcon
121
+ };
122
+ return /* @__PURE__ */ jsx(
123
+ ui.span,
124
+ {
125
+ ref,
126
+ className: cx("ui-autocomplete-item-icon", className),
127
+ __css: css,
128
+ ...rest
129
+ }
130
+ );
131
+ }
132
+ );
133
+
134
+ // src/autocomplete.tsx
135
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
136
+ var Autocomplete = forwardRef2((props, ref) => {
137
+ const [styles, mergedProps] = useMultiComponentStyle("Select", props);
138
+ let {
139
+ className,
140
+ defaultValue = "",
141
+ color,
142
+ h,
143
+ height,
144
+ minH,
145
+ minHeight,
146
+ containerProps,
147
+ listProps,
148
+ inputProps,
149
+ iconProps,
150
+ children,
151
+ ...computedProps
152
+ } = omitThemeProps(mergedProps);
153
+ const {
154
+ descendants,
155
+ formControlProps,
156
+ getPopoverProps,
157
+ getContainerProps,
158
+ getFieldProps,
159
+ createOption,
160
+ isEmpty,
161
+ inputValue,
162
+ computedChildren,
163
+ ...rest
164
+ } = useAutocomplete({ ...computedProps, defaultValue, children });
165
+ h = h != null ? h : height;
166
+ minH = minH != null ? minH : minHeight;
167
+ const css = {
168
+ position: "relative",
169
+ w: "100%",
170
+ h: "fit-content",
171
+ color,
172
+ ...styles.container
173
+ };
174
+ return /* @__PURE__ */ jsx2(AutocompleteDescendantsContextProvider, { value: descendants, children: /* @__PURE__ */ jsx2(
175
+ AutocompleteProvider,
176
+ {
177
+ value: { ...rest, formControlProps, inputValue, createOption, isEmpty, styles },
178
+ children: /* @__PURE__ */ jsx2(Popover, { ...getPopoverProps(), children: /* @__PURE__ */ jsxs(
179
+ ui2.div,
180
+ {
181
+ className: cx2("ui-autocomplete", className),
182
+ __css: css,
183
+ ...getContainerProps(containerProps),
184
+ children: [
185
+ /* @__PURE__ */ jsx2(
186
+ AutocompleteField,
187
+ {
188
+ h,
189
+ minH,
190
+ inputProps,
191
+ ...getFieldProps({}, ref)
192
+ }
193
+ ),
194
+ /* @__PURE__ */ jsx2(AutocompleteIcon, { ...iconProps, ...formControlProps }),
195
+ !isEmpty ? /* @__PURE__ */ jsxs(AutocompleteList, { ...listProps, children: [
196
+ createOption ? /* @__PURE__ */ jsx2(AutocompleteCreate, {}) : /* @__PURE__ */ jsx2(AutocompleteEmpty, {}),
197
+ children != null ? children : computedChildren
198
+ ] }) : /* @__PURE__ */ jsx2(AutocompleteList, { ...listProps, children: createOption && inputValue ? /* @__PURE__ */ jsx2(AutocompleteCreate, {}) : /* @__PURE__ */ jsx2(AutocompleteEmpty, {}) })
199
+ ]
200
+ }
201
+ ) })
202
+ }
203
+ ) });
204
+ });
205
+ var AutocompleteField = forwardRef2(
206
+ ({ className, h, minH, placeholder, inputProps, ...rest }, ref) => {
207
+ const { displayValue, inputValue, styles } = useAutocompleteContext();
208
+ const { getInputProps } = useAutocompleteInput();
209
+ const css = {
210
+ paddingEnd: "2rem",
211
+ h,
212
+ minH,
213
+ display: "flex",
214
+ alignItems: "center",
215
+ ...styles.field,
216
+ cursor: "text"
217
+ };
218
+ return /* @__PURE__ */ jsx2(PopoverTrigger, { children: /* @__PURE__ */ jsx2(ui2.div, { className: cx2("ui-autocomplete-field", className), __css: css, ...rest, children: /* @__PURE__ */ jsx2(
219
+ ui2.input,
220
+ {
221
+ className: "ui-autocomplete-input",
222
+ display: "inline-block",
223
+ w: "full",
224
+ placeholder,
225
+ ...getInputProps(inputProps, ref),
226
+ value: inputValue || displayValue || ""
227
+ }
228
+ ) }) });
229
+ }
230
+ );
231
+
232
+ // src/autocomplete-option-group.tsx
233
+ import { ui as ui3, forwardRef as forwardRef3 } from "@yamada-ui/core";
234
+ import { cx as cx3 } from "@yamada-ui/utils";
235
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
236
+ var AutocompleteOptionGroup = forwardRef3(
237
+ ({ className, color, h, height, minH, minHeight, children, ...rest }, ref) => {
238
+ const { styles } = useAutocompleteContext();
239
+ const { label, getContainerProps, getGroupProps } = useAutocompleteOptionGroup(rest);
240
+ h = h != null ? h : height;
241
+ minH = minH != null ? minH : minHeight;
242
+ return /* @__PURE__ */ jsxs2(
243
+ ui3.li,
244
+ {
245
+ className: "ui-autocomplete-group-container",
246
+ __css: { w: "100%", h: "fit-content", color },
247
+ ...getContainerProps(),
248
+ children: [
249
+ /* @__PURE__ */ jsx3(
250
+ ui3.span,
251
+ {
252
+ className: cx3("ui-autocomplete-group-label"),
253
+ __css: styles.groupLabel,
254
+ noOfLines: 1,
255
+ children: label
256
+ }
257
+ ),
258
+ /* @__PURE__ */ jsx3(
259
+ ui3.ul,
260
+ {
261
+ ...getGroupProps({}, ref),
262
+ className: cx3("ui-autocomplete-group", className),
263
+ __css: { h, minH, ...styles.group },
264
+ children
265
+ }
266
+ )
267
+ ]
268
+ }
269
+ );
270
+ }
271
+ );
272
+
273
+ // src/autocomplete-option.tsx
274
+ import { ui as ui4, forwardRef as forwardRef4 } from "@yamada-ui/core";
275
+ import { cx as cx4 } from "@yamada-ui/utils";
276
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
277
+ var AutocompleteOption = forwardRef4(
278
+ ({ className, icon, ...rest }, ref) => {
279
+ const { styles } = useAutocompleteContext();
280
+ const { isSelected, customIcon, children, getOptionProps } = useAutocompleteOption(rest);
281
+ icon = icon != null ? icon : customIcon;
282
+ const css = {
283
+ textDecoration: "none",
284
+ color: "inherit",
285
+ userSelect: "none",
286
+ display: "flex",
287
+ width: "100%",
288
+ alignItems: "center",
289
+ textAlign: "start",
290
+ flex: "0 0 auto",
291
+ outline: 0,
292
+ gap: "0.75rem",
293
+ ...styles.item
294
+ };
295
+ return /* @__PURE__ */ jsxs3(
296
+ ui4.li,
297
+ {
298
+ className: cx4("ui-autocomplete-item", className),
299
+ __css: css,
300
+ ...getOptionProps({}, ref),
301
+ children: [
302
+ icon !== null ? /* @__PURE__ */ jsx4(AutocompleteItemIcon, { opacity: isSelected ? 1 : 0, children: icon || /* @__PURE__ */ jsx4(CheckIcon, {}) }) : null,
303
+ icon ? /* @__PURE__ */ jsx4(ui4.span, { style: { pointerEvents: "none", flex: 1 }, noOfLines: 1, children }) : children
304
+ ]
305
+ }
306
+ );
307
+ }
308
+ );
309
+ var CheckIcon = () => /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 14 14", width: "1em", height: "1em", children: /* @__PURE__ */ jsx4(
310
+ "polygon",
311
+ {
312
+ fill: "currentColor",
313
+ points: "5.5 11.9993304 14 3.49933039 12.5 2 5.5 8.99933039 1.5 4.9968652 0 6.49933039"
314
+ }
315
+ ) });
316
+
317
+ // src/autocomplete-create.tsx
318
+ import { ui as ui5, forwardRef as forwardRef5 } from "@yamada-ui/core";
319
+ import { cx as cx5, runIfFunc } from "@yamada-ui/utils";
320
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
321
+ var AutocompleteCreate = forwardRef5(
322
+ ({ className, icon, children, ...rest }, ref) => {
323
+ const { inputValue, styles } = useAutocompleteContext();
324
+ const { getCreateProps } = useAutocompleteCreate();
325
+ children != null ? children : children = inputValue;
326
+ const css = {
327
+ textDecoration: "none",
328
+ color: "inherit",
329
+ userSelect: "none",
330
+ display: "flex",
331
+ width: "100%",
332
+ alignItems: "center",
333
+ textAlign: "start",
334
+ flex: "0 0 auto",
335
+ outline: 0,
336
+ gap: "0.75rem",
337
+ ...styles.item
338
+ };
339
+ return /* @__PURE__ */ jsxs4(
340
+ ui5.li,
341
+ {
342
+ className: cx5("ui-autocomplete-create", className),
343
+ __css: css,
344
+ ...getCreateProps(rest, ref),
345
+ children: [
346
+ icon !== null ? /* @__PURE__ */ jsx5(AutocompleteItemIcon, { children: icon || /* @__PURE__ */ jsx5(PlusIcon, {}) }) : null,
347
+ icon ? /* @__PURE__ */ jsx5(ui5.span, { style: { pointerEvents: "none", flex: 1 }, noOfLines: 1, children: runIfFunc(children, inputValue) }) : runIfFunc(children, inputValue)
348
+ ]
349
+ }
350
+ );
351
+ }
352
+ );
353
+ var PlusIcon = () => /* @__PURE__ */ jsx5("svg", { viewBox: "0 0 45.402 45.402", width: "1em", height: "1em", children: /* @__PURE__ */ jsx5(
354
+ "path",
355
+ {
356
+ fill: "currentColor",
357
+ d: "M41.267,18.557H26.832V4.134C26.832,1.851,24.99,0,22.707,0c-2.283,0-4.124,1.851-4.124,4.135v14.432H4.141 c-2.283,0-4.139,1.851-4.138,4.135c-0.001,1.141,0.46,2.187,1.207,2.934c0.748,0.749,1.78,1.222,2.92,1.222h14.453V41.27 c0,1.142,0.453,2.176,1.201,2.922c0.748,0.748,1.777,1.211,2.919,1.211c2.282,0,4.129-1.851,4.129-4.133V26.857h14.435 c2.283,0,4.134-1.867,4.133-4.15C45.399,20.425,43.548,18.557,41.267,18.557z"
358
+ }
359
+ ) });
360
+
361
+ // src/autocomplete-empty.tsx
362
+ import { ui as ui6, forwardRef as forwardRef6 } from "@yamada-ui/core";
363
+ import { cx as cx6 } from "@yamada-ui/utils";
364
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
365
+ var AutocompleteEmpty = forwardRef6(
366
+ ({ className, icon, children, ...rest }, ref) => {
367
+ const { emptyMessage, styles } = useAutocompleteContext();
368
+ const { getEmptyProps } = useAutocompleteEmpty();
369
+ children != null ? children : children = emptyMessage;
370
+ const css = {
371
+ textDecoration: "none",
372
+ color: "inherit",
373
+ userSelect: "none",
374
+ display: "flex",
375
+ width: "100%",
376
+ alignItems: "center",
377
+ textAlign: "start",
378
+ flex: "0 0 auto",
379
+ outline: 0,
380
+ gap: "0.75rem",
381
+ pointerEvents: "none",
382
+ ...styles.item
383
+ };
384
+ return /* @__PURE__ */ jsxs5(
385
+ ui6.li,
386
+ {
387
+ className: cx6("ui-autocomplete-empty", className),
388
+ __css: css,
389
+ ...getEmptyProps(rest, ref),
390
+ children: [
391
+ icon !== null ? /* @__PURE__ */ jsx6(AutocompleteItemIcon, { children: icon || /* @__PURE__ */ jsx6(MinusIcon, {}) }) : null,
392
+ icon ? /* @__PURE__ */ jsx6(ui6.span, { style: { pointerEvents: "none", flex: 1 }, noOfLines: 1, children }) : children
393
+ ]
394
+ }
395
+ );
396
+ }
397
+ );
398
+ var MinusIcon = () => /* @__PURE__ */ jsx6("svg", { viewBox: "0 0 448 512", width: "1em", height: "1em", children: /* @__PURE__ */ jsx6(
399
+ "path",
400
+ {
401
+ fill: "currentColor",
402
+ d: "M432 256c0 17.7-14.3 32-32 32L48 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z"
403
+ }
404
+ ) });
405
+
406
+ // src/multi-autocomplete.tsx
407
+ import {
408
+ ui as ui7,
409
+ forwardRef as forwardRef7,
410
+ useMultiComponentStyle as useMultiComponentStyle2,
411
+ omitThemeProps as omitThemeProps2
412
+ } from "@yamada-ui/core";
413
+ import { Popover as Popover2, PopoverTrigger as PopoverTrigger2 } from "@yamada-ui/popover";
414
+ import { cx as cx7, handlerAll } from "@yamada-ui/utils";
415
+ import { cloneElement as cloneElement2, useMemo } from "react";
416
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
417
+ var MultiAutocomplete = forwardRef7((props, ref) => {
418
+ const [styles, mergedProps] = useMultiComponentStyle2("Select", props);
419
+ let {
420
+ className,
421
+ defaultValue = [],
422
+ component,
423
+ separator,
424
+ isClearable = true,
425
+ color,
426
+ h,
427
+ height,
428
+ minH,
429
+ minHeight,
430
+ closeOnSelect = false,
431
+ keepPlaceholder = false,
432
+ containerProps,
433
+ listProps,
434
+ inputProps,
435
+ iconProps,
436
+ clearIconProps,
437
+ children,
438
+ ...computedProps
439
+ } = omitThemeProps2(mergedProps);
440
+ const {
441
+ value,
442
+ descendants,
443
+ formControlProps,
444
+ getPopoverProps,
445
+ getContainerProps,
446
+ getFieldProps,
447
+ createOption,
448
+ isEmpty,
449
+ inputValue,
450
+ computedChildren,
451
+ onClear,
452
+ ...rest
453
+ } = useAutocomplete({
454
+ ...computedProps,
455
+ defaultValue,
456
+ closeOnSelect,
457
+ children
458
+ });
459
+ h = h != null ? h : height;
460
+ minH = minH != null ? minH : minHeight;
461
+ const css = {
462
+ position: "relative",
463
+ w: "100%",
464
+ h: "fit-content",
465
+ color,
466
+ ...styles.container
467
+ };
468
+ return /* @__PURE__ */ jsx7(AutocompleteDescendantsContextProvider, { value: descendants, children: /* @__PURE__ */ jsx7(
469
+ AutocompleteProvider,
470
+ {
471
+ value: {
472
+ ...rest,
473
+ value,
474
+ formControlProps,
475
+ inputValue,
476
+ createOption,
477
+ isEmpty,
478
+ styles
479
+ },
480
+ children: /* @__PURE__ */ jsx7(Popover2, { ...getPopoverProps(), children: /* @__PURE__ */ jsxs6(ui7.div, { className: "ui-autocomplete", __css: css, ...getContainerProps(containerProps), children: [
481
+ /* @__PURE__ */ jsx7(
482
+ MultiAutocompleteField,
483
+ {
484
+ component,
485
+ separator,
486
+ keepPlaceholder,
487
+ h,
488
+ minH,
489
+ inputProps,
490
+ ...getFieldProps({}, ref)
491
+ }
492
+ ),
493
+ isClearable && value.length ? /* @__PURE__ */ jsx7(
494
+ AutocompleteClearIcon,
495
+ {
496
+ ...clearIconProps,
497
+ onClick: handlerAll(clearIconProps == null ? void 0 : clearIconProps.onClick, onClear),
498
+ ...formControlProps
499
+ }
500
+ ) : /* @__PURE__ */ jsx7(AutocompleteIcon, { ...iconProps, ...formControlProps }),
501
+ !isEmpty ? /* @__PURE__ */ jsxs6(AutocompleteList, { ...listProps, children: [
502
+ createOption ? /* @__PURE__ */ jsx7(AutocompleteCreate, {}) : /* @__PURE__ */ jsx7(AutocompleteEmpty, {}),
503
+ children != null ? children : computedChildren
504
+ ] }) : /* @__PURE__ */ jsx7(AutocompleteList, { ...listProps, children: createOption && inputValue ? /* @__PURE__ */ jsx7(AutocompleteCreate, {}) : /* @__PURE__ */ jsx7(AutocompleteEmpty, {}) })
505
+ ] }) })
506
+ }
507
+ ) });
508
+ });
509
+ var MultiAutocompleteField = forwardRef7(
510
+ ({
511
+ className,
512
+ component,
513
+ separator = ",",
514
+ keepPlaceholder,
515
+ h,
516
+ minH,
517
+ placeholder,
518
+ inputProps,
519
+ ...rest
520
+ }, ref) => {
521
+ const { value, displayValue, inputValue, onChange, isOpen, inputRef, styles } = useAutocompleteContext();
522
+ const { getInputProps } = useAutocompleteInput();
523
+ const cloneChildren = useMemo(() => {
524
+ if (!(displayValue == null ? void 0 : displayValue.length))
525
+ return null;
526
+ if (component) {
527
+ return displayValue.map((displayValue2, index) => {
528
+ const onRemove = (e) => {
529
+ e.stopPropagation();
530
+ onChange(value[index]);
531
+ if (inputRef.current)
532
+ inputRef.current.focus();
533
+ };
534
+ const el = component({
535
+ value: value[index],
536
+ displayValue: displayValue2,
537
+ index,
538
+ onRemove
539
+ });
540
+ const style = {
541
+ cursor: "default",
542
+ marginBlockStart: "0.125rem",
543
+ marginBlockEnd: "0.125rem",
544
+ marginInlineEnd: "0.25rem"
545
+ };
546
+ return el ? cloneElement2(el, { style }) : null;
547
+ });
548
+ } else {
549
+ return displayValue.map((value2, index) => {
550
+ const isLast = displayValue.length === index + 1;
551
+ return /* @__PURE__ */ jsxs6(ui7.span, { display: "inline-block", me: "0.25rem", children: [
552
+ value2,
553
+ !isLast || isOpen ? separator : null
554
+ ] }, index);
555
+ });
556
+ }
557
+ }, [displayValue, component, value, onChange, isOpen, inputRef, separator]);
558
+ const css = {
559
+ paddingEnd: "2rem",
560
+ h,
561
+ minH,
562
+ display: "flex",
563
+ flexWrap: "wrap",
564
+ alignItems: "center",
565
+ ...styles.field,
566
+ cursor: "text"
567
+ };
568
+ return /* @__PURE__ */ jsx7(PopoverTrigger2, { children: /* @__PURE__ */ jsxs6(
569
+ ui7.div,
570
+ {
571
+ className: cx7("ui-autocomplete-field", className),
572
+ __css: css,
573
+ py: (displayValue == null ? void 0 : displayValue.length) && component ? "0.125rem" : void 0,
574
+ ...rest,
575
+ children: [
576
+ cloneChildren,
577
+ /* @__PURE__ */ jsx7(
578
+ ui7.input,
579
+ {
580
+ className: "ui-autocomplete-input",
581
+ display: "inline-block",
582
+ flex: "1",
583
+ overflow: "hidden",
584
+ marginBlockStart: "0.125rem",
585
+ marginBlockEnd: "0.125rem",
586
+ placeholder: !displayValue || keepPlaceholder && isOpen ? placeholder : void 0,
587
+ ...getInputProps(inputProps, ref),
588
+ value: inputValue
589
+ }
590
+ )
591
+ ]
592
+ }
593
+ ) });
594
+ }
595
+ );
596
+
597
+ // src/use-autocomplete.tsx
598
+ import { jsx as jsx8 } from "react/jsx-runtime";
599
+ var kanaMap = {
600
+ \uFF76\uFF9E: "\u30AC",
601
+ \uFF77\uFF9E: "\u30AE",
602
+ \uFF78\uFF9E: "\u30B0",
603
+ \uFF79\uFF9E: "\u30B2",
604
+ \uFF7A\uFF9E: "\u30B4",
605
+ \uFF7B\uFF9E: "\u30B6",
606
+ \uFF7C\uFF9E: "\u30B8",
607
+ \uFF7D\uFF9E: "\u30BA",
608
+ \uFF7E\uFF9E: "\u30BC",
609
+ \uFF7F\uFF9E: "\u30BE",
610
+ \uFF80\uFF9E: "\u30C0",
611
+ \uFF81\uFF9E: "\u30C2",
612
+ \uFF82\uFF9E: "\u30C5",
613
+ \uFF83\uFF9E: "\u30C7",
614
+ \uFF84\uFF9E: "\u30C9",
615
+ \uFF8A\uFF9E: "\u30D0",
616
+ \uFF8B\uFF9E: "\u30D3",
617
+ \uFF8C\uFF9E: "\u30D6",
618
+ \uFF8D\uFF9E: "\u30D9",
619
+ \uFF8E\uFF9E: "\u30DC",
620
+ \uFF8A\uFF9F: "\u30D1",
621
+ \uFF8B\uFF9F: "\u30D4",
622
+ \uFF8C\uFF9F: "\u30D7",
623
+ \uFF8D\uFF9F: "\u30DA",
624
+ \uFF8E\uFF9F: "\u30DD",
625
+ \uFF73\uFF9E: "\u30F4",
626
+ \uFF9C\uFF9E: "\u30F7",
627
+ \uFF66\uFF9E: "\u30FA",
628
+ \uFF71: "\u30A2",
629
+ \uFF72: "\u30A4",
630
+ \uFF73: "\u30A6",
631
+ \uFF74: "\u30A8",
632
+ \uFF75: "\u30AA",
633
+ \uFF76: "\u30AB",
634
+ \uFF77: "\u30AD",
635
+ \uFF78: "\u30AF",
636
+ \uFF79: "\u30B1",
637
+ \uFF7A: "\u30B3",
638
+ \uFF7B: "\u30B5",
639
+ \uFF7C: "\u30B7",
640
+ \uFF7D: "\u30B9",
641
+ \uFF7E: "\u30BB",
642
+ \uFF7F: "\u30BD",
643
+ \uFF80: "\u30BF",
644
+ \uFF81: "\u30C1",
645
+ \uFF82: "\u30C4",
646
+ \uFF83: "\u30C6",
647
+ \uFF84: "\u30C8",
648
+ \uFF85: "\u30CA",
649
+ \uFF86: "\u30CB",
650
+ \uFF87: "\u30CC",
651
+ \uFF88: "\u30CD",
652
+ \uFF89: "\u30CE",
653
+ \uFF8A: "\u30CF",
654
+ \uFF8B: "\u30D2",
655
+ \uFF8C: "\u30D5",
656
+ \uFF8D: "\u30D8",
657
+ \uFF8E: "\u30DB",
658
+ \uFF8F: "\u30DE",
659
+ \uFF90: "\u30DF",
660
+ \uFF91: "\u30E0",
661
+ \uFF92: "\u30E1",
662
+ \uFF93: "\u30E2",
663
+ \uFF94: "\u30E4",
664
+ \uFF95: "\u30E6",
665
+ \uFF96: "\u30E8",
666
+ \uFF97: "\u30E9",
667
+ \uFF98: "\u30EA",
668
+ \uFF99: "\u30EB",
669
+ \uFF9A: "\u30EC",
670
+ \uFF9B: "\u30ED",
671
+ \uFF9C: "\u30EF",
672
+ \uFF66: "\u30F2",
673
+ \uFF9D: "\u30F3",
674
+ \uFF67: "\u30A1",
675
+ \uFF68: "\u30A3",
676
+ \uFF69: "\u30A5",
677
+ \uFF6A: "\u30A7",
678
+ \uFF6B: "\u30A9",
679
+ \uFF6F: "\u30C3",
680
+ \uFF6C: "\u30E3",
681
+ \uFF6D: "\u30E5",
682
+ \uFF6E: "\u30E7",
683
+ "\uFF61": "\u3002",
684
+ "\uFF64": "\u3001",
685
+ \uFF70: "\u30FC",
686
+ "\uFF62": "\u300C",
687
+ "\uFF63": "\u300D",
688
+ "\uFF65": "\u30FB"
689
+ };
690
+ var defaultFormat = (value) => {
691
+ value = value.replace(/[!-~]/g, (v) => String.fromCharCode(v.charCodeAt(0) - 65248));
692
+ const reg = new RegExp("(" + Object.keys(kanaMap).join("|") + ")", "g");
693
+ value = value.replace(reg, (v) => kanaMap[v]).replace(/゙/g, "\u309B").replace(/゚/g, "\u309C");
694
+ value = value.toUpperCase();
695
+ return value;
696
+ };
697
+ var flattenData = (data) => {
698
+ const filterData = (data2) => data2.map((data3) => {
699
+ const { value, isDisabled, isFocusable } = data3;
700
+ const trulyDisabled = !!isDisabled && !isFocusable;
701
+ const isMulti = isArray(value);
702
+ if (trulyDisabled)
703
+ return;
704
+ if (!isMulti) {
705
+ return data3;
706
+ } else {
707
+ return filterData(value);
708
+ }
709
+ }).filter(Boolean);
710
+ return filterData(data).flat(Infinity);
711
+ };
712
+ var isTargetOption = (target) => {
713
+ var _a;
714
+ return isHTMLElement(target) && !!((_a = target == null ? void 0 : target.getAttribute("role")) == null ? void 0 : _a.startsWith("autocomplete-item"));
715
+ };
716
+ var {
717
+ DescendantsContextProvider: AutocompleteDescendantsContextProvider,
718
+ useDescendantsContext: useAutocompleteDescendantsContext,
719
+ useDescendants: useAutocompleteDescendants,
720
+ useDescendant: useAutocompleteDescendant
721
+ } = createDescendant();
722
+ var [AutocompleteProvider, useAutocompleteContext] = createContext({
723
+ name: "AutocompleteContext",
724
+ errorMessage: `useAutocompleteContext returned is 'undefined'. Seems you forgot to wrap the components in "<Autocomplete />" or "<MultiAutocomplete />"`
725
+ });
726
+ var useAutocomplete = ({
727
+ defaultIsOpen,
728
+ closeOnSelect = true,
729
+ omitSelectedValues = false,
730
+ maxSelectedValues,
731
+ closeOnBlur = true,
732
+ closeOnEsc = true,
733
+ createOption = false,
734
+ createOrder = "first",
735
+ createSecondOrder = "first",
736
+ emptyMessage = "No results found",
737
+ format = defaultFormat,
738
+ placement = "bottom-start",
739
+ duration = 0.2,
740
+ optionProps,
741
+ placeholder,
742
+ children,
743
+ ...rest
744
+ }) => {
745
+ rest = useFormControlProps(rest);
746
+ const { id } = rest;
747
+ const formControlProps = pickObject(rest, formControlProperties);
748
+ const [containerProps, inputProps] = splitObject(
749
+ omitObject(rest, ["id", "value", "onChange", "month", "onChangeMonth"]),
750
+ layoutStylesProperties
751
+ );
752
+ const descendants = useAutocompleteDescendants();
753
+ const containerRef = useRef2(null);
754
+ const listRef = useRef2(null);
755
+ const inputRef = useRef2(null);
756
+ const timeoutIds = useRef2(/* @__PURE__ */ new Set([]));
757
+ const isComposition = useRef2(false);
758
+ const [data, setData] = useState(rest.data);
759
+ const [value, setValue] = useControllableState({
760
+ value: rest.value,
761
+ defaultValue: rest.defaultValue,
762
+ onChange: rest.onChange
763
+ });
764
+ const [displayValue, setDisplayValue] = useState(void 0);
765
+ const [inputValue, setInputValue] = useState("");
766
+ const [focusedIndex, setFocusedIndex] = useState(-1);
767
+ const [isAllSelected, setIsAllSelected] = useState(false);
768
+ const [isHit, setIsHit] = useState(true);
769
+ const [isOpen, setIsOpen] = useState(defaultIsOpen != null ? defaultIsOpen : false);
770
+ const isFocused = focusedIndex > -1;
771
+ const isCreate = focusedIndex === -2 && createOption;
772
+ const isMulti = isArray(value);
773
+ const isEmptyValue = !isMulti ? !value : !value.length;
774
+ if (createOption && !isUndefined(children)) {
775
+ console.warn(
776
+ `${!isMulti ? "Autocomplete" : "MultiAutocomplete"}: ${!isMulti ? "Autocomplete" : "MultiAutocomplete"} internally prefers 'children'. If 'createOption' is true, it will not be reflected correctly. If want to reflect, please set 'data' in props.`
777
+ );
778
+ }
779
+ const selectedValues = descendants.enabledValues(
780
+ ({ node }) => {
781
+ var _a;
782
+ return isMulti && value.includes((_a = node.dataset.value) != null ? _a : "");
783
+ }
784
+ );
785
+ const selectedIndexes = selectedValues.map(({ index }) => index);
786
+ const enabledValues = descendants.enabledValues(
787
+ ({ node, index }) => "target" in node.dataset && !selectedIndexes.includes(index)
788
+ );
789
+ const validChildren = getValidChildren2(children);
790
+ const computedChildren = data == null ? void 0 : data.map(({ label, value: value2, ...props }, i) => {
791
+ if (!isArray(value2)) {
792
+ return /* @__PURE__ */ jsx8(AutocompleteOption, { value: value2, ...props, children: label }, i);
793
+ } else {
794
+ return /* @__PURE__ */ jsx8(AutocompleteOptionGroup, { label, ...props, children: value2.map(
795
+ ({ label: label2, value: value3, ...props2 }, i2) => !isArray(value3) ? /* @__PURE__ */ jsx8(AutocompleteOption, { value: value3, ...props2, children: label2 }, i2) : null
796
+ ) }, i);
797
+ }
798
+ });
799
+ const isEmpty = !validChildren.length && !(computedChildren == null ? void 0 : computedChildren.length);
800
+ const onOpen = useCallback(() => {
801
+ var _a;
802
+ if (formControlProps.disabled || formControlProps.readOnly)
803
+ return;
804
+ if (!createOption && (isEmpty || isAllSelected))
805
+ return;
806
+ setIsOpen(true);
807
+ if (inputRef.current)
808
+ inputRef.current.focus();
809
+ (_a = rest.onOpen) == null ? void 0 : _a.call(rest);
810
+ }, [createOption, formControlProps, isAllSelected, isEmpty, rest]);
811
+ const onClose = useCallback(() => {
812
+ var _a;
813
+ setIsOpen(false);
814
+ (_a = rest.onClose) == null ? void 0 : _a.call(rest);
815
+ }, [rest]);
816
+ const onFocusFirst = useCallback(() => {
817
+ const id2 = setTimeout(() => {
818
+ if (isEmpty || isAllSelected)
819
+ return;
820
+ const first = descendants.enabledfirstValue(({ node }) => "target" in node.dataset);
821
+ if (!first)
822
+ return;
823
+ if (!isMulti || !omitSelectedValues) {
824
+ setFocusedIndex(first.index);
825
+ } else {
826
+ if (selectedIndexes.includes(first.index)) {
827
+ const enabledFirst = enabledValues[0];
828
+ setFocusedIndex(enabledFirst.index);
829
+ } else {
830
+ setFocusedIndex(first.index);
831
+ }
832
+ }
833
+ });
834
+ timeoutIds.current.add(id2);
835
+ }, [
836
+ descendants,
837
+ enabledValues,
838
+ isAllSelected,
839
+ isEmpty,
840
+ isMulti,
841
+ omitSelectedValues,
842
+ selectedIndexes
843
+ ]);
844
+ const onFocusLast = useCallback(() => {
845
+ const id2 = setTimeout(() => {
846
+ if (isEmpty || isAllSelected)
847
+ return;
848
+ const last = descendants.enabledlastValue(({ node }) => "target" in node.dataset);
849
+ if (!last)
850
+ return;
851
+ if (!isMulti || !omitSelectedValues) {
852
+ setFocusedIndex(last.index);
853
+ } else {
854
+ if (selectedIndexes.includes(last.index)) {
855
+ const enabledlast = enabledValues.reverse()[0];
856
+ setFocusedIndex(enabledlast.index);
857
+ } else {
858
+ setFocusedIndex(last.index);
859
+ }
860
+ }
861
+ });
862
+ timeoutIds.current.add(id2);
863
+ }, [
864
+ descendants,
865
+ enabledValues,
866
+ isAllSelected,
867
+ isEmpty,
868
+ isMulti,
869
+ omitSelectedValues,
870
+ selectedIndexes
871
+ ]);
872
+ const onFocusSelected = useCallback(() => {
873
+ const id2 = setTimeout(() => {
874
+ const values = descendants.enabledValues();
875
+ const selected = values.find(
876
+ ({ node }) => {
877
+ var _a;
878
+ return !isMulti ? node.dataset.value === value : value.includes((_a = node.dataset.value) != null ? _a : "");
879
+ }
880
+ );
881
+ if (selected)
882
+ setFocusedIndex(selected.index);
883
+ });
884
+ timeoutIds.current.add(id2);
885
+ }, [descendants, isMulti, value]);
886
+ const onFocusNext = useCallback(
887
+ (index = focusedIndex) => {
888
+ const id2 = setTimeout(() => {
889
+ var _a;
890
+ const next = descendants.enabledNextValue(index, ({ node }) => "target" in node.dataset);
891
+ if (!next)
892
+ return;
893
+ if (!isMulti || !omitSelectedValues) {
894
+ setFocusedIndex(next.index);
895
+ } else {
896
+ if (selectedIndexes.includes(next.index)) {
897
+ const enabledNext = (_a = enabledValues.find(({ index: index2 }) => next.index < index2)) != null ? _a : enabledValues[0];
898
+ setFocusedIndex(enabledNext.index);
899
+ } else {
900
+ setFocusedIndex(next.index);
901
+ }
902
+ }
903
+ });
904
+ timeoutIds.current.add(id2);
905
+ },
906
+ [descendants, enabledValues, focusedIndex, isMulti, omitSelectedValues, selectedIndexes]
907
+ );
908
+ const onFocusPrev = useCallback(
909
+ (index = focusedIndex) => {
910
+ const id2 = setTimeout(() => {
911
+ var _a;
912
+ const prev = descendants.enabledPrevValue(index, ({ node }) => "target" in node.dataset);
913
+ if (!prev)
914
+ return;
915
+ if (!isMulti || !omitSelectedValues) {
916
+ setFocusedIndex(prev.index);
917
+ } else {
918
+ if (selectedIndexes.includes(prev.index)) {
919
+ const enabledPrev = (_a = enabledValues.reverse().find(({ index: index2 }) => index2 < prev.index)) != null ? _a : enabledValues[0];
920
+ setFocusedIndex(enabledPrev.index);
921
+ } else {
922
+ setFocusedIndex(prev.index);
923
+ }
924
+ }
925
+ });
926
+ timeoutIds.current.add(id2);
927
+ },
928
+ [descendants, enabledValues, focusedIndex, isMulti, omitSelectedValues, selectedIndexes]
929
+ );
930
+ const onFocusFirstOrSelected = isEmptyValue || omitSelectedValues ? onFocusFirst : onFocusSelected;
931
+ const onFocusLastOrSelected = isEmptyValue || omitSelectedValues ? onFocusLast : onFocusSelected;
932
+ const pickOptions = useCallback(
933
+ (value2) => {
934
+ const values = descendants.values();
935
+ let isHit2 = false;
936
+ let isFocused2 = false;
937
+ values.forEach(({ node, index }) => {
938
+ var _a;
939
+ if (format((_a = node.textContent) != null ? _a : "").includes(value2)) {
940
+ isHit2 = true;
941
+ const isDisabled = "disabled" in node.dataset;
942
+ node.dataset.target = "";
943
+ if (!isFocused2 && !isDisabled) {
944
+ isFocused2 = true;
945
+ setFocusedIndex(index);
946
+ }
947
+ } else {
948
+ delete node.dataset.target;
949
+ }
950
+ });
951
+ setIsHit(isHit2);
952
+ },
953
+ [descendants, format]
954
+ );
955
+ const rebirthOptions = useCallback(
956
+ (runFocus = true) => {
957
+ const values = descendants.values();
958
+ values.forEach(({ node }) => {
959
+ node.dataset.target = "";
960
+ });
961
+ if (runFocus)
962
+ onFocusFirst();
963
+ setIsHit(true);
964
+ },
965
+ [descendants, onFocusFirst]
966
+ );
967
+ const onChangeDisplayValue = useCallback(
968
+ (newValue, runOmit = true) => {
969
+ const enabledValues2 = descendants.enabledValues();
970
+ const selectedValues2 = enabledValues2.filter(({ node }) => node.dataset.value === newValue).map(({ node }) => {
971
+ var _a;
972
+ return (_a = node.textContent) != null ? _a : "";
973
+ });
974
+ setDisplayValue((prev) => {
975
+ if (!isMulti) {
976
+ return selectedValues2[0];
977
+ } else {
978
+ selectedValues2.forEach((selectedValue) => {
979
+ const isSelected = isArray(prev) && prev.includes(selectedValue != null ? selectedValue : "");
980
+ if (!isSelected) {
981
+ prev = [...isArray(prev) ? prev : [], selectedValue];
982
+ } else if (runOmit) {
983
+ prev = isArray(prev) ? prev.filter((value2) => value2 !== selectedValue) : void 0;
984
+ }
985
+ });
986
+ return prev;
987
+ }
988
+ });
989
+ },
990
+ [descendants, isMulti]
991
+ );
992
+ const onChange = useCallback(
993
+ (newValue) => {
994
+ setValue((prev) => {
995
+ if (!isArray(prev)) {
996
+ return newValue;
997
+ } else {
998
+ const isSelected = prev.includes(newValue);
999
+ if (!isSelected) {
1000
+ return [...prev, newValue];
1001
+ } else {
1002
+ return prev.filter((value2) => value2 !== newValue);
1003
+ }
1004
+ }
1005
+ });
1006
+ onChangeDisplayValue(newValue);
1007
+ setInputValue("");
1008
+ rebirthOptions(false);
1009
+ },
1010
+ [onChangeDisplayValue, rebirthOptions, setValue]
1011
+ );
1012
+ const onSelect = useCallback(() => {
1013
+ var _a, _b;
1014
+ let enabledValue = descendants.value(focusedIndex);
1015
+ if ("disabled" in ((_a = enabledValue == null ? void 0 : enabledValue.node.dataset) != null ? _a : {}))
1016
+ enabledValue = void 0;
1017
+ if (!enabledValue)
1018
+ return;
1019
+ const value2 = (_b = enabledValue.node.dataset.value) != null ? _b : "";
1020
+ onChange(value2);
1021
+ if (closeOnSelect)
1022
+ onClose();
1023
+ if (omitSelectedValues)
1024
+ onFocusNext();
1025
+ }, [closeOnSelect, descendants, focusedIndex, omitSelectedValues, onChange, onClose, onFocusNext]);
1026
+ const onSearch = useCallback(
1027
+ (ev) => {
1028
+ var _a;
1029
+ if (!isOpen)
1030
+ onOpen();
1031
+ (_a = rest.onSearch) == null ? void 0 : _a.call(rest, ev);
1032
+ const value2 = ev.target.value;
1033
+ const computedValue = format(value2);
1034
+ if (computedValue) {
1035
+ pickOptions(computedValue);
1036
+ } else {
1037
+ rebirthOptions();
1038
+ }
1039
+ setInputValue(value2);
1040
+ },
1041
+ [isOpen, onOpen, format, rest, pickOptions, rebirthOptions]
1042
+ );
1043
+ const onCompositionStart = useCallback(() => {
1044
+ isComposition.current = true;
1045
+ }, []);
1046
+ const onCompositionEnd = useCallback(() => {
1047
+ isComposition.current = false;
1048
+ }, []);
1049
+ const onCreate = useCallback(() => {
1050
+ var _a;
1051
+ if (!listRef.current)
1052
+ return;
1053
+ const newOption = { label: inputValue, value: inputValue };
1054
+ let newData = [];
1055
+ if (data)
1056
+ newData = data;
1057
+ if (createOrder === "first") {
1058
+ newData = [newOption, ...newData];
1059
+ } else if (createOrder === "last") {
1060
+ newData = [...newData, newOption];
1061
+ } else {
1062
+ const i = newData.findIndex(({ label }) => label === createOrder);
1063
+ if (i !== -1 && isArray(newData[i].value)) {
1064
+ if (createSecondOrder === "first") {
1065
+ newData[i].value = [newOption, ...newData[i].value];
1066
+ } else {
1067
+ newData[i].value = [...newData[i].value, newOption];
1068
+ }
1069
+ } else {
1070
+ console.warn(
1071
+ `${!isMulti ? "Autocomplete" : "MultiAutocomplete"}: '${createOrder}' specified in createOrder does not exist in the option group.`
1072
+ );
1073
+ }
1074
+ }
1075
+ setData(newData);
1076
+ onChange(inputValue);
1077
+ rebirthOptions(false);
1078
+ const index = flattenData(newData).findIndex(({ value: value2 }) => value2 === inputValue);
1079
+ setFocusedIndex(index);
1080
+ (_a = rest.onCreate) == null ? void 0 : _a.call(rest, newOption, newData);
1081
+ }, [inputValue, data, createOrder, onChange, rebirthOptions, rest, createSecondOrder, isMulti]);
1082
+ const onDelete = useCallback(() => {
1083
+ if (!isMulti) {
1084
+ onChange("");
1085
+ } else {
1086
+ onChange(value[value.length - 1]);
1087
+ }
1088
+ }, [isMulti, onChange, value]);
1089
+ const onClear = useCallback(
1090
+ (ev) => {
1091
+ ev.stopPropagation();
1092
+ setValue([]);
1093
+ setDisplayValue(void 0);
1094
+ setInputValue("");
1095
+ rebirthOptions();
1096
+ if (inputRef.current)
1097
+ inputRef.current.focus();
1098
+ },
1099
+ [setDisplayValue, setInputValue, setValue, rebirthOptions, inputRef]
1100
+ );
1101
+ const onClick = useCallback(() => {
1102
+ if (isOpen) {
1103
+ if (inputRef.current)
1104
+ inputRef.current.focus();
1105
+ } else {
1106
+ onOpen();
1107
+ onFocusFirstOrSelected();
1108
+ }
1109
+ }, [isOpen, onFocusFirstOrSelected, onOpen]);
1110
+ const onFocus = useCallback(() => {
1111
+ if (isOpen)
1112
+ return;
1113
+ onOpen();
1114
+ onFocusFirstOrSelected();
1115
+ }, [isOpen, onFocusFirstOrSelected, onOpen]);
1116
+ const onBlur = useCallback(
1117
+ (ev) => {
1118
+ const relatedTarget = getEventRelatedTarget(ev);
1119
+ if (isContains(containerRef.current, relatedTarget))
1120
+ return;
1121
+ if (!closeOnBlur && isHit)
1122
+ return;
1123
+ setInputValue("");
1124
+ if (isOpen)
1125
+ onClose();
1126
+ },
1127
+ [closeOnBlur, isHit, isOpen, onClose]
1128
+ );
1129
+ const onKeyDown = useCallback(
1130
+ (ev) => {
1131
+ if (ev.key === " ")
1132
+ ev.key = ev.code;
1133
+ if (formControlProps.disabled || formControlProps.readOnly)
1134
+ return;
1135
+ if (isComposition.current)
1136
+ return;
1137
+ const enabledDelete = displayValue === inputValue || !inputValue.length;
1138
+ const actions = {
1139
+ ArrowDown: isFocused ? () => onFocusNext() : !isOpen ? funcAll(onOpen, onFocusFirstOrSelected) : void 0,
1140
+ ArrowUp: isFocused ? () => onFocusPrev() : !isOpen ? funcAll(onOpen, onFocusLastOrSelected) : void 0,
1141
+ Space: isCreate ? onCreate : isFocused ? onSelect : !isOpen ? funcAll(onOpen, onFocusFirstOrSelected) : void 0,
1142
+ Enter: isCreate ? onCreate : isFocused ? onSelect : !isOpen ? funcAll(onOpen, onFocusFirstOrSelected) : void 0,
1143
+ Home: isOpen ? onFocusFirst : void 0,
1144
+ End: isOpen ? onFocusLast : void 0,
1145
+ Escape: closeOnEsc ? onClose : void 0,
1146
+ Backspace: !isEmptyValue && enabledDelete ? onDelete : void 0
1147
+ };
1148
+ const action = actions[ev.key];
1149
+ if (!action)
1150
+ return;
1151
+ ev.preventDefault();
1152
+ ev.stopPropagation();
1153
+ action(ev);
1154
+ },
1155
+ [
1156
+ formControlProps,
1157
+ displayValue,
1158
+ inputValue,
1159
+ onOpen,
1160
+ isFocused,
1161
+ onFocusFirstOrSelected,
1162
+ onFocusNext,
1163
+ onFocusLastOrSelected,
1164
+ onFocusPrev,
1165
+ isCreate,
1166
+ onCreate,
1167
+ onSelect,
1168
+ isOpen,
1169
+ onFocusFirst,
1170
+ onFocusLast,
1171
+ closeOnEsc,
1172
+ onClose,
1173
+ isEmptyValue,
1174
+ onDelete
1175
+ ]
1176
+ );
1177
+ useEffect(() => {
1178
+ if (!isMulti)
1179
+ return;
1180
+ if (!omitSelectedValues && isUndefined(maxSelectedValues))
1181
+ return;
1182
+ const isAll = value.length > 0 && value.length === descendants.count();
1183
+ const isMax = value.length === maxSelectedValues;
1184
+ if (isAll || isMax) {
1185
+ onClose();
1186
+ setIsAllSelected(true);
1187
+ } else {
1188
+ setIsAllSelected(false);
1189
+ }
1190
+ }, [omitSelectedValues, value, descendants, isMulti, onClose, maxSelectedValues]);
1191
+ useUpdateEffect(() => {
1192
+ if (isOpen)
1193
+ return;
1194
+ setFocusedIndex(-1);
1195
+ setInputValue("");
1196
+ }, [isOpen]);
1197
+ useUpdateEffect(() => {
1198
+ if (!isHit)
1199
+ setFocusedIndex(-2);
1200
+ }, [isHit]);
1201
+ useUnmountEffect(() => {
1202
+ timeoutIds.current.forEach((id2) => clearTimeout(id2));
1203
+ timeoutIds.current.clear();
1204
+ });
1205
+ useOutsideClick({
1206
+ ref: containerRef,
1207
+ handler: onClose,
1208
+ enabled: closeOnBlur || !isHit
1209
+ });
1210
+ const getPopoverProps = useCallback(
1211
+ (props) => ({
1212
+ ...rest,
1213
+ ...props,
1214
+ isOpen,
1215
+ onOpen,
1216
+ onClose,
1217
+ placement,
1218
+ duration,
1219
+ trigger: "never",
1220
+ closeOnButton: false
1221
+ }),
1222
+ [duration, isOpen, onClose, onOpen, placement, rest]
1223
+ );
1224
+ const getContainerProps = useCallback(
1225
+ (props = {}, ref = null) => ({
1226
+ ref: mergeRefs(containerRef, ref),
1227
+ ...containerProps,
1228
+ ...props,
1229
+ ...formControlProps,
1230
+ onClick: handlerAll2(props.onClick, rest.onClick, onClick),
1231
+ onFocus: handlerAll2(props.onFocus, rest.onFocus, onFocus),
1232
+ onBlur: handlerAll2(props.onBlur, rest.onBlur, onBlur)
1233
+ }),
1234
+ [containerProps, formControlProps, onBlur, onClick, onFocus, rest]
1235
+ );
1236
+ const getFieldProps = useCallback(
1237
+ (props = {}, ref = null) => ({
1238
+ ref,
1239
+ tabIndex: -1,
1240
+ ...props,
1241
+ ...formControlProps,
1242
+ placeholder,
1243
+ "data-active": dataAttr(isOpen),
1244
+ "aria-expanded": dataAttr(isOpen),
1245
+ onKeyDown: handlerAll2(props.onKeyDown, rest.onKeyDown, onKeyDown)
1246
+ }),
1247
+ [formControlProps, placeholder, isOpen, rest, onKeyDown]
1248
+ );
1249
+ return {
1250
+ id,
1251
+ descendants,
1252
+ value,
1253
+ displayValue,
1254
+ inputValue,
1255
+ isHit,
1256
+ isEmpty,
1257
+ computedChildren,
1258
+ focusedIndex,
1259
+ omitSelectedValues,
1260
+ closeOnSelect,
1261
+ createOption,
1262
+ emptyMessage,
1263
+ isOpen,
1264
+ isAllSelected,
1265
+ listRef,
1266
+ inputRef,
1267
+ optionProps,
1268
+ formControlProps,
1269
+ setFocusedIndex,
1270
+ onChangeDisplayValue,
1271
+ onChange,
1272
+ onSearch,
1273
+ onCreate,
1274
+ onClear,
1275
+ onCompositionStart,
1276
+ onCompositionEnd,
1277
+ pickOptions,
1278
+ rebirthOptions,
1279
+ onOpen,
1280
+ onClose,
1281
+ onFocusFirst,
1282
+ onFocusLast,
1283
+ onFocusSelected,
1284
+ onFocusNext,
1285
+ onFocusPrev,
1286
+ getPopoverProps,
1287
+ getContainerProps,
1288
+ getFieldProps,
1289
+ inputProps
1290
+ };
1291
+ };
1292
+ var useAutocompleteInput = () => {
1293
+ const {
1294
+ id,
1295
+ inputRef,
1296
+ onSearch,
1297
+ onCompositionStart,
1298
+ onCompositionEnd,
1299
+ isAllSelected,
1300
+ formControlProps,
1301
+ inputProps
1302
+ } = useAutocompleteContext();
1303
+ useUpdateEffect(() => {
1304
+ if (isAllSelected && inputRef.current)
1305
+ inputRef.current.blur();
1306
+ }, [isAllSelected]);
1307
+ const getInputProps = useCallback(
1308
+ (props = {}, ref = null) => ({
1309
+ ref: mergeRefs(inputRef, ref),
1310
+ ...formControlProps,
1311
+ ...inputProps,
1312
+ ...props,
1313
+ id,
1314
+ cursor: formControlProps.readOnly ? "default" : "text",
1315
+ pointerEvents: formControlProps.disabled || isAllSelected ? "none" : "auto",
1316
+ tabIndex: isAllSelected ? -1 : 0,
1317
+ onChange: handlerAll2(props.onChange, onSearch),
1318
+ onCompositionStart: handlerAll2(
1319
+ props.onCompositionStart,
1320
+ inputProps.onCompositionStart,
1321
+ onCompositionStart
1322
+ ),
1323
+ onCompositionEnd: handlerAll2(
1324
+ props.onCompositionEnd,
1325
+ inputProps.onCompositionEnd,
1326
+ onCompositionEnd
1327
+ )
1328
+ }),
1329
+ [
1330
+ inputProps,
1331
+ inputRef,
1332
+ formControlProps,
1333
+ id,
1334
+ isAllSelected,
1335
+ onSearch,
1336
+ onCompositionStart,
1337
+ onCompositionEnd
1338
+ ]
1339
+ );
1340
+ return {
1341
+ getInputProps
1342
+ };
1343
+ };
1344
+ var useAutocompleteList = () => {
1345
+ const { focusedIndex, isOpen, listRef, rebirthOptions } = useAutocompleteContext();
1346
+ const descendants = useAutocompleteDescendantsContext();
1347
+ const beforeFocusedIndex = useRef2(-1);
1348
+ const selectedValue = descendants.value(focusedIndex);
1349
+ const onAnimationComplete = useCallback(() => {
1350
+ if (!isOpen)
1351
+ rebirthOptions(false);
1352
+ }, [isOpen, rebirthOptions]);
1353
+ useEffect(() => {
1354
+ if (!listRef.current || !selectedValue)
1355
+ return;
1356
+ const parent = listRef.current;
1357
+ const child = selectedValue.node;
1358
+ const parentHeight = parent.clientHeight;
1359
+ const viewTop = parent.scrollTop;
1360
+ const viewBottom = viewTop + parentHeight;
1361
+ const childHeight = child.clientHeight;
1362
+ const childTop = child.offsetTop;
1363
+ const childBottom = childTop + childHeight;
1364
+ const isInView = viewTop <= childTop && childBottom <= viewBottom;
1365
+ const isScrollBottom = beforeFocusedIndex.current < selectedValue.index;
1366
+ if (!isInView) {
1367
+ if (childBottom <= parentHeight) {
1368
+ listRef.current.scrollTo({ top: 0 });
1369
+ } else {
1370
+ if (!isScrollBottom) {
1371
+ listRef.current.scrollTo({ top: childTop + 1 });
1372
+ } else {
1373
+ listRef.current.scrollTo({ top: childBottom - parentHeight });
1374
+ }
1375
+ }
1376
+ }
1377
+ beforeFocusedIndex.current = selectedValue.index;
1378
+ }, [listRef, selectedValue]);
1379
+ useUpdateEffect(() => {
1380
+ if (!isOpen)
1381
+ beforeFocusedIndex.current = -1;
1382
+ }, [isOpen]);
1383
+ const getListProps = useCallback(
1384
+ (props = {}, ref = null) => ({
1385
+ as: "ul",
1386
+ ref: mergeRefs(listRef, ref),
1387
+ role: "select",
1388
+ tabIndex: -1,
1389
+ ...props,
1390
+ onAnimationComplete: handlerAll2(props.onAnimationComplete, onAnimationComplete)
1391
+ }),
1392
+ [listRef, onAnimationComplete]
1393
+ );
1394
+ return {
1395
+ getListProps
1396
+ };
1397
+ };
1398
+ var useAutocompleteOptionGroup = ({ label, ...rest }) => {
1399
+ const { value, omitSelectedValues } = useAutocompleteContext();
1400
+ const isMulti = isArray(value);
1401
+ const descendants = useAutocompleteDescendantsContext();
1402
+ const values = descendants.values();
1403
+ const selectedValues = isMulti && omitSelectedValues ? descendants.values(({ node }) => {
1404
+ var _a;
1405
+ return value.includes((_a = node.dataset.value) != null ? _a : "");
1406
+ }) : [];
1407
+ const selectedIndexes = selectedValues.map(({ index }) => index);
1408
+ const childValues = values.filter(
1409
+ ({ node, index }) => {
1410
+ var _a;
1411
+ return ((_a = node.parentElement) == null ? void 0 : _a.dataset.label) === label && !selectedIndexes.includes(index) && "target" in node.dataset;
1412
+ }
1413
+ );
1414
+ const isEmpty = !childValues.length;
1415
+ const computedRest = splitObject(rest, layoutStylesProperties);
1416
+ const getContainerProps = useCallback(
1417
+ (props = {}, ref = null) => {
1418
+ const style = {
1419
+ border: "0px",
1420
+ clip: "rect(0px, 0px, 0px, 0px)",
1421
+ height: "1px",
1422
+ width: "1px",
1423
+ margin: "-1px",
1424
+ padding: "0px",
1425
+ overflow: "hidden",
1426
+ whiteSpace: "nowrap",
1427
+ position: "absolute"
1428
+ };
1429
+ return {
1430
+ ref,
1431
+ ...props,
1432
+ ...computedRest[0],
1433
+ style: isEmpty ? style : void 0,
1434
+ "data-label": label,
1435
+ role: "autocomplete-group-container"
1436
+ };
1437
+ },
1438
+ [computedRest, isEmpty, label]
1439
+ );
1440
+ const getGroupProps = useCallback(
1441
+ (props = {}, ref = null) => ({
1442
+ ref,
1443
+ ...props,
1444
+ ...computedRest[1],
1445
+ "data-label": label,
1446
+ role: "autocomplete-group"
1447
+ }),
1448
+ [computedRest, label]
1449
+ );
1450
+ return {
1451
+ label,
1452
+ getContainerProps,
1453
+ getGroupProps
1454
+ };
1455
+ };
1456
+ var useAutocompleteOption = (props) => {
1457
+ var _a, _b, _c, _d;
1458
+ const {
1459
+ value,
1460
+ omitSelectedValues,
1461
+ onChange,
1462
+ onChangeDisplayValue,
1463
+ focusedIndex,
1464
+ setFocusedIndex,
1465
+ onClose,
1466
+ closeOnSelect: generalCloseOnSelect,
1467
+ optionProps,
1468
+ inputRef,
1469
+ onFocusNext
1470
+ } = useAutocompleteContext();
1471
+ let {
1472
+ icon: customIcon,
1473
+ isDisabled,
1474
+ isFocusable,
1475
+ closeOnSelect: customCloseOnSelect,
1476
+ children,
1477
+ ...computedProps
1478
+ } = { ...optionProps, ...props };
1479
+ const trulyDisabled = !!isDisabled && !isFocusable;
1480
+ const itemRef = useRef2(null);
1481
+ const { index, register, descendants } = useAutocompleteDescendant({ disabled: trulyDisabled });
1482
+ const values = descendants.values();
1483
+ const frontValues = values.slice(0, index);
1484
+ const isMulti = isArray(value);
1485
+ const isDuplicated = !isMulti ? frontValues.some(({ node }) => {
1486
+ var _a2;
1487
+ return node.dataset.value === ((_a2 = computedProps.value) != null ? _a2 : "");
1488
+ }) : false;
1489
+ const isSelected = !isDuplicated && (!isMulti ? ((_a = computedProps.value) != null ? _a : "") === value : value.includes((_b = computedProps.value) != null ? _b : ""));
1490
+ const isTarget = "target" in ((_d = (_c = itemRef.current) == null ? void 0 : _c.dataset) != null ? _d : {});
1491
+ const isFocused = index === focusedIndex;
1492
+ const onClick = useCallback(
1493
+ (ev) => {
1494
+ var _a2;
1495
+ ev.stopPropagation();
1496
+ if (isDisabled) {
1497
+ if (inputRef.current)
1498
+ inputRef.current.focus();
1499
+ return;
1500
+ }
1501
+ if (!isTargetOption(ev.currentTarget)) {
1502
+ if (inputRef.current)
1503
+ inputRef.current.focus();
1504
+ return;
1505
+ }
1506
+ setFocusedIndex(index);
1507
+ onChange((_a2 = computedProps.value) != null ? _a2 : "");
1508
+ if (inputRef.current)
1509
+ inputRef.current.focus();
1510
+ if (customCloseOnSelect != null ? customCloseOnSelect : generalCloseOnSelect)
1511
+ onClose();
1512
+ if (omitSelectedValues)
1513
+ onFocusNext(index);
1514
+ },
1515
+ [
1516
+ onFocusNext,
1517
+ omitSelectedValues,
1518
+ isDisabled,
1519
+ computedProps,
1520
+ setFocusedIndex,
1521
+ index,
1522
+ onChange,
1523
+ customCloseOnSelect,
1524
+ generalCloseOnSelect,
1525
+ onClose,
1526
+ inputRef
1527
+ ]
1528
+ );
1529
+ useEffect(() => {
1530
+ var _a2;
1531
+ if (isSelected)
1532
+ onChangeDisplayValue((_a2 = computedProps.value) != null ? _a2 : "", false);
1533
+ }, [computedProps, isSelected, onChangeDisplayValue]);
1534
+ const getOptionProps = useCallback(
1535
+ (props2 = {}, ref = null) => {
1536
+ var _a2;
1537
+ const style = {
1538
+ border: "0px",
1539
+ clip: "rect(0px, 0px, 0px, 0px)",
1540
+ height: "1px",
1541
+ width: "1px",
1542
+ margin: "-1px",
1543
+ padding: "0px",
1544
+ overflow: "hidden",
1545
+ whiteSpace: "nowrap",
1546
+ position: "absolute"
1547
+ };
1548
+ return {
1549
+ ref: mergeRefs(itemRef, ref, register),
1550
+ ...omitObject(computedProps, ["value"]),
1551
+ ...props2,
1552
+ role: "autocomplete-item",
1553
+ tabIndex: -1,
1554
+ style: !isTarget || omitSelectedValues && isSelected ? style : void 0,
1555
+ "data-target": dataAttr(true),
1556
+ "data-value": (_a2 = computedProps.value) != null ? _a2 : "",
1557
+ "data-focus": dataAttr(isFocused),
1558
+ "data-disabled": dataAttr(isDisabled),
1559
+ "aria-checked": ariaAttr(isSelected),
1560
+ "aria-disabled": ariaAttr(isDisabled),
1561
+ onClick: handlerAll2(computedProps.onClick, props2.onClick, onClick)
1562
+ };
1563
+ },
1564
+ [
1565
+ computedProps,
1566
+ isDisabled,
1567
+ isFocused,
1568
+ isSelected,
1569
+ isTarget,
1570
+ omitSelectedValues,
1571
+ onClick,
1572
+ register
1573
+ ]
1574
+ );
1575
+ return {
1576
+ isSelected,
1577
+ isFocused,
1578
+ customIcon,
1579
+ children,
1580
+ getOptionProps
1581
+ };
1582
+ };
1583
+ var useAutocompleteCreate = () => {
1584
+ const { isHit, onCreate } = useAutocompleteContext();
1585
+ const getCreateProps = useCallback(
1586
+ (props = {}, ref = null) => {
1587
+ const style = {
1588
+ border: "0px",
1589
+ clip: "rect(0px, 0px, 0px, 0px)",
1590
+ height: "1px",
1591
+ width: "1px",
1592
+ margin: "-1px",
1593
+ padding: "0px",
1594
+ overflow: "hidden",
1595
+ whiteSpace: "nowrap",
1596
+ position: "absolute"
1597
+ };
1598
+ return {
1599
+ ref,
1600
+ ...props,
1601
+ tabIndex: -1,
1602
+ style: isHit ? style : void 0,
1603
+ "data-focus": dataAttr(!isHit),
1604
+ onClick: handlerAll2(props.onClick, onCreate)
1605
+ };
1606
+ },
1607
+ [isHit, onCreate]
1608
+ );
1609
+ return { getCreateProps };
1610
+ };
1611
+ var useAutocompleteEmpty = () => {
1612
+ const { isHit, isEmpty } = useAutocompleteContext();
1613
+ const getEmptyProps = useCallback(
1614
+ (props = {}, ref = null) => {
1615
+ const style = {
1616
+ border: "0px",
1617
+ clip: "rect(0px, 0px, 0px, 0px)",
1618
+ height: "1px",
1619
+ width: "1px",
1620
+ margin: "-1px",
1621
+ padding: "0px",
1622
+ overflow: "hidden",
1623
+ whiteSpace: "nowrap",
1624
+ position: "absolute"
1625
+ };
1626
+ return {
1627
+ ref,
1628
+ ...props,
1629
+ tabIndex: -1,
1630
+ style: isHit && !isEmpty ? style : void 0
1631
+ };
1632
+ },
1633
+ [isHit, isEmpty]
1634
+ );
1635
+ return { getEmptyProps };
1636
+ };
1637
+
1638
+ // src/autocomplete-list.tsx
1639
+ import { jsx as jsx9 } from "react/jsx-runtime";
1640
+ var AutocompleteList = forwardRef8(
1641
+ ({ className, w, width, minW, minWidth, ...rest }, ref) => {
1642
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1643
+ const { styles } = useAutocompleteContext();
1644
+ const { getListProps } = useAutocompleteList();
1645
+ w = (_d = w != null ? w : width) != null ? _d : (_c = (_a = styles.list) == null ? void 0 : _a.w) != null ? _c : (_b = styles.list) == null ? void 0 : _b.width;
1646
+ minW = (_h = minW != null ? minW : minWidth) != null ? _h : (_g = (_e = styles.list) == null ? void 0 : _e.minW) != null ? _g : (_f = styles.list) == null ? void 0 : _f.minWidth;
1647
+ const css = { ...styles.list };
1648
+ return /* @__PURE__ */ jsx9(
1649
+ PopoverContent,
1650
+ {
1651
+ className: cx8("ui-autocomplete-list", className),
1652
+ w,
1653
+ minW,
1654
+ __css: css,
1655
+ ...getListProps(rest, ref)
1656
+ }
1657
+ );
1658
+ }
1659
+ );
1660
+
1661
+ export {
1662
+ AutocompleteList,
1663
+ Autocomplete,
1664
+ AutocompleteOptionGroup,
1665
+ AutocompleteOption,
1666
+ AutocompleteEmpty,
1667
+ MultiAutocomplete,
1668
+ AutocompleteDescendantsContextProvider,
1669
+ useAutocompleteDescendantsContext,
1670
+ useAutocompleteDescendants,
1671
+ useAutocompleteDescendant,
1672
+ AutocompleteProvider,
1673
+ useAutocompleteContext,
1674
+ useAutocomplete,
1675
+ useAutocompleteInput,
1676
+ useAutocompleteList,
1677
+ useAutocompleteOptionGroup,
1678
+ useAutocompleteOption,
1679
+ useAutocompleteCreate,
1680
+ useAutocompleteEmpty,
1681
+ AutocompleteIcon,
1682
+ AutocompleteClearIcon,
1683
+ AutocompleteItemIcon,
1684
+ AutocompleteCreate
1685
+ };