@dxos/react-ui-searchlist 0.8.4-main.3a94e84 → 0.8.4-main.3eb6e50203

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.
Files changed (78) hide show
  1. package/dist/lib/browser/index.mjs +739 -291
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +739 -291
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/Combobox/Combobox.d.ts +84 -0
  8. package/dist/types/src/components/Combobox/Combobox.d.ts.map +1 -0
  9. package/dist/types/src/components/Combobox/Combobox.stories.d.ts +21 -0
  10. package/dist/types/src/components/Combobox/Combobox.stories.d.ts.map +1 -0
  11. package/dist/types/src/components/Combobox/index.d.ts +2 -0
  12. package/dist/types/src/components/Combobox/index.d.ts.map +1 -0
  13. package/dist/types/src/components/Listbox/Listbox.d.ts +31 -0
  14. package/dist/types/src/components/Listbox/Listbox.d.ts.map +1 -0
  15. package/dist/types/src/components/Listbox/Listbox.stories.d.ts +21 -0
  16. package/dist/types/src/components/Listbox/Listbox.stories.d.ts.map +1 -0
  17. package/dist/types/src/components/Listbox/index.d.ts +2 -0
  18. package/dist/types/src/components/Listbox/index.d.ts.map +1 -0
  19. package/dist/types/src/components/SearchList/SearchList.d.ts +88 -0
  20. package/dist/types/src/components/SearchList/SearchList.d.ts.map +1 -0
  21. package/dist/types/src/components/SearchList/SearchList.stories.d.ts +28 -0
  22. package/dist/types/src/components/SearchList/SearchList.stories.d.ts.map +1 -0
  23. package/dist/types/src/components/SearchList/context.d.ts +33 -0
  24. package/dist/types/src/components/SearchList/context.d.ts.map +1 -0
  25. package/dist/types/src/components/SearchList/hooks/index.d.ts +5 -0
  26. package/dist/types/src/components/SearchList/hooks/index.d.ts.map +1 -0
  27. package/dist/types/src/components/SearchList/hooks/useGlobalFilter.d.ts +34 -0
  28. package/dist/types/src/components/SearchList/hooks/useGlobalFilter.d.ts.map +1 -0
  29. package/dist/types/src/components/SearchList/hooks/useSearchListInput.d.ts +12 -0
  30. package/dist/types/src/components/SearchList/hooks/useSearchListInput.d.ts.map +1 -0
  31. package/dist/types/src/components/SearchList/hooks/useSearchListItem.d.ts +10 -0
  32. package/dist/types/src/components/SearchList/hooks/useSearchListItem.d.ts.map +1 -0
  33. package/dist/types/src/components/SearchList/hooks/useSearchListResults.d.ts +36 -0
  34. package/dist/types/src/components/SearchList/hooks/useSearchListResults.d.ts.map +1 -0
  35. package/dist/types/src/components/SearchList/index.d.ts +3 -0
  36. package/dist/types/src/components/SearchList/index.d.ts.map +1 -0
  37. package/dist/types/src/components/index.d.ts +2 -0
  38. package/dist/types/src/components/index.d.ts.map +1 -1
  39. package/dist/types/src/index.d.ts +0 -1
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/translations.d.ts +4 -2
  42. package/dist/types/src/translations.d.ts.map +1 -1
  43. package/dist/types/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +23 -17
  45. package/src/components/Combobox/Combobox.stories.tsx +62 -0
  46. package/src/components/Combobox/Combobox.tsx +348 -0
  47. package/src/components/Combobox/index.ts +5 -0
  48. package/src/components/Listbox/Listbox.stories.tsx +53 -0
  49. package/src/components/Listbox/Listbox.tsx +214 -0
  50. package/src/components/Listbox/index.ts +5 -0
  51. package/src/components/SearchList/SearchList.stories.tsx +532 -0
  52. package/src/components/SearchList/SearchList.tsx +560 -0
  53. package/src/components/SearchList/context.ts +43 -0
  54. package/src/components/SearchList/hooks/index.ts +8 -0
  55. package/src/components/SearchList/hooks/useGlobalFilter.tsx +61 -0
  56. package/src/components/SearchList/hooks/useSearchListInput.ts +14 -0
  57. package/src/components/SearchList/hooks/useSearchListItem.ts +14 -0
  58. package/src/components/SearchList/hooks/useSearchListResults.ts +104 -0
  59. package/src/components/SearchList/index.ts +6 -0
  60. package/src/components/index.ts +2 -0
  61. package/src/index.ts +0 -1
  62. package/src/translations.ts +4 -2
  63. package/src/types/command-score.d.ts +16 -0
  64. package/dist/types/src/components/SearchList.d.ts +0 -44
  65. package/dist/types/src/components/SearchList.d.ts.map +0 -1
  66. package/dist/types/src/components/SearchList.stories.d.ts +0 -15
  67. package/dist/types/src/components/SearchList.stories.d.ts.map +0 -1
  68. package/dist/types/src/composites/PopoverCombobox.d.ts +0 -32
  69. package/dist/types/src/composites/PopoverCombobox.d.ts.map +0 -1
  70. package/dist/types/src/composites/PopoverCombobox.stories.d.ts +0 -28
  71. package/dist/types/src/composites/PopoverCombobox.stories.d.ts.map +0 -1
  72. package/dist/types/src/composites/index.d.ts +0 -2
  73. package/dist/types/src/composites/index.d.ts.map +0 -1
  74. package/src/components/SearchList.stories.tsx +0 -47
  75. package/src/components/SearchList.tsx +0 -250
  76. package/src/composites/PopoverCombobox.stories.tsx +0 -44
  77. package/src/composites/PopoverCombobox.tsx +0 -208
  78. package/src/composites/index.ts +0 -5
@@ -1,320 +1,768 @@
1
- // src/components/SearchList.tsx
2
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
3
- import { createContext } from "@radix-ui/react-context";
1
+ // src/components/Combobox/Combobox.tsx
2
+ import { createContext as createContext3 } from "@radix-ui/react-context";
3
+ import { useControllableState as useControllableState2 } from "@radix-ui/react-use-controllable-state";
4
+ import React3, { forwardRef as forwardRef2, useCallback as useCallback3 } from "react";
5
+ import { Button, Icon as Icon2, Popover } from "@dxos/react-ui";
6
+ import { useId } from "@dxos/react-ui";
7
+ import { mx as mx2, staticPlaceholderText } from "@dxos/ui-theme";
8
+
9
+ // src/components/SearchList/SearchList.tsx
4
10
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
5
- import { CommandEmpty, CommandInput, CommandItem, CommandList, CommandRoot } from "cmdk";
6
- import React, { forwardRef, useCallback } from "react";
7
- import { Button, Icon, useDensityContext, useElevationContext, useId, useThemeContext } from "@dxos/react-ui";
8
- import { mx, staticPlaceholderText } from "@dxos/react-ui-theme";
9
- var COMBOBOX_NAME = "Combobox";
10
- var COMBOBOX_TRIGGER_NAME = "ComboboxTrigger";
11
- var SEARCHLIST_NAME = "SearchList";
12
- var SEARCHLIST_ITEM_NAME = "SearchListItem";
13
- var [ComboboxProvider, useComboboxContext] = createContext(COMBOBOX_NAME, {});
14
- var SearchListRoot = /* @__PURE__ */ forwardRef(({ children, classNames, ...props }, forwardedRef) => {
15
- var _effect = _useSignals();
16
- try {
17
- return /* @__PURE__ */ React.createElement(CommandRoot, {
18
- ...props,
19
- className: mx("", classNames),
20
- ref: forwardedRef
21
- }, children);
22
- } finally {
23
- _effect.f();
24
- }
25
- });
26
- SearchListRoot.displayName = SEARCHLIST_NAME;
27
- var SearchListInput = /* @__PURE__ */ forwardRef(({ children, classNames, density: propsDensity, elevation: propsElevation, variant, ...props }, forwardedRef) => {
28
- var _effect = _useSignals();
29
- try {
30
- const { hasIosKeyboard } = useThemeContext();
31
- const { tx } = useThemeContext();
32
- const density = useDensityContext(propsDensity);
33
- const elevation = useElevationContext(propsElevation);
34
- return /* @__PURE__ */ React.createElement(CommandInput, {
35
- ...props,
36
- className: tx("input.input", "input", {
37
- variant,
38
- disabled: props.disabled,
39
- density,
40
- elevation
41
- }, "mbe-cardSpacingBlock", classNames),
42
- ...props.autoFocus && !hasIosKeyboard && {
43
- autoFocus: true
44
- },
45
- ref: forwardedRef
46
- });
47
- } finally {
48
- _effect.f();
11
+ import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
12
+ import { Icon, useDensityContext, useElevationContext, useThemeContext, useTranslation } from "@dxos/react-ui";
13
+ import { descriptionText, mx } from "@dxos/ui-theme";
14
+
15
+ // src/translations.ts
16
+ var translationKey = "@dxos/react-ui-searchlist";
17
+ var translations = [
18
+ {
19
+ "en-US": {
20
+ [translationKey]: {
21
+ "search.placeholder": "Search..."
22
+ }
23
+ }
49
24
  }
25
+ ];
26
+
27
+ // src/components/SearchList/context.ts
28
+ import { createContext } from "@radix-ui/react-context";
29
+ var [SearchListItemContextProvider, useSearchListItemContext] = createContext("SearchListItem");
30
+ var [SearchListInputContextProvider, useSearchListInputContext] = createContext("SearchListInput");
31
+
32
+ // src/components/SearchList/SearchList.tsx
33
+ var SearchListRoot = ({ children, value: valueProp, defaultValue = "", debounceMs = 200, onSearch }) => {
34
+ const [query = "", setQuery] = useControllableState({
35
+ prop: valueProp,
36
+ defaultProp: defaultValue,
37
+ onChange: void 0
38
+ });
39
+ const [selectedValue, setSelectedValue] = useState(void 0);
40
+ const itemsRef = useRef(/* @__PURE__ */ new Map());
41
+ const debounceRef = useRef(null);
42
+ const handleQueryChange = useCallback((newQuery) => {
43
+ setQuery(newQuery);
44
+ if (debounceRef.current) {
45
+ clearTimeout(debounceRef.current);
46
+ }
47
+ debounceRef.current = setTimeout(() => {
48
+ onSearch?.(newQuery);
49
+ }, debounceMs);
50
+ }, [
51
+ setQuery,
52
+ onSearch,
53
+ debounceMs
54
+ ]);
55
+ const [itemVersion, setItemVersion] = useState(0);
56
+ useEffect(() => {
57
+ return () => {
58
+ if (debounceRef.current) {
59
+ clearTimeout(debounceRef.current);
60
+ }
61
+ };
62
+ }, []);
63
+ useEffect(() => {
64
+ const currentItem = selectedValue !== void 0 ? itemsRef.current.get(selectedValue) : void 0;
65
+ const isSelectionValid = currentItem !== void 0 && !currentItem.disabled;
66
+ if (!isSelectionValid && itemsRef.current.size > 0) {
67
+ const entries = Array.from(itemsRef.current.entries()).filter(([, data]) => !data.disabled);
68
+ if (entries.length > 0) {
69
+ entries.sort(([, a], [, b]) => {
70
+ const position = a.element.compareDocumentPosition(b.element);
71
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
72
+ return -1;
73
+ }
74
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) {
75
+ return 1;
76
+ }
77
+ return 0;
78
+ });
79
+ const firstValue = entries[0]?.[0];
80
+ if (firstValue !== void 0 && firstValue !== selectedValue) {
81
+ setSelectedValue(firstValue);
82
+ }
83
+ } else if (selectedValue !== void 0) {
84
+ setSelectedValue(void 0);
85
+ }
86
+ }
87
+ }, [
88
+ itemVersion,
89
+ selectedValue
90
+ ]);
91
+ const registerItem = useCallback((value, element, onSelect, disabled) => {
92
+ if (element) {
93
+ itemsRef.current.set(value, {
94
+ element,
95
+ onSelect,
96
+ disabled
97
+ });
98
+ setItemVersion((v) => v + 1);
99
+ }
100
+ }, []);
101
+ const unregisterItem = useCallback((value) => {
102
+ itemsRef.current.delete(value);
103
+ setItemVersion((v) => v + 1);
104
+ }, []);
105
+ const getItemValues = useCallback(() => {
106
+ return Array.from(itemsRef.current.entries()).filter(([, data]) => !data.disabled).sort(([, a], [, b]) => {
107
+ const position = a.element.compareDocumentPosition(b.element);
108
+ return position & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : position & Node.DOCUMENT_POSITION_PRECEDING ? 1 : 0;
109
+ }).map(([value]) => value);
110
+ }, []);
111
+ const triggerSelect = useCallback(() => {
112
+ if (selectedValue !== void 0) {
113
+ const item = itemsRef.current.get(selectedValue);
114
+ item?.onSelect?.();
115
+ }
116
+ }, [
117
+ selectedValue
118
+ ]);
119
+ const itemContextValue = useMemo(() => ({
120
+ selectedValue,
121
+ onSelectedValueChange: setSelectedValue,
122
+ registerItem,
123
+ unregisterItem
124
+ }), [
125
+ selectedValue,
126
+ registerItem,
127
+ unregisterItem
128
+ ]);
129
+ const inputContextValue = useMemo(() => ({
130
+ query,
131
+ onQueryChange: handleQueryChange,
132
+ selectedValue,
133
+ onSelectedValueChange: setSelectedValue,
134
+ getItemValues,
135
+ triggerSelect
136
+ }), [
137
+ query,
138
+ handleQueryChange,
139
+ selectedValue,
140
+ getItemValues,
141
+ triggerSelect
142
+ ]);
143
+ return /* @__PURE__ */ React.createElement(SearchListInputContextProvider, {
144
+ query: inputContextValue.query,
145
+ onQueryChange: inputContextValue.onQueryChange,
146
+ selectedValue: inputContextValue.selectedValue,
147
+ onSelectedValueChange: inputContextValue.onSelectedValueChange,
148
+ getItemValues: inputContextValue.getItemValues,
149
+ triggerSelect: inputContextValue.triggerSelect
150
+ }, /* @__PURE__ */ React.createElement(SearchListItemContextProvider, {
151
+ selectedValue: itemContextValue.selectedValue,
152
+ onSelectedValueChange: itemContextValue.onSelectedValueChange,
153
+ registerItem: itemContextValue.registerItem,
154
+ unregisterItem: itemContextValue.unregisterItem
155
+ }, children));
156
+ };
157
+ SearchListRoot.displayName = "SearchList.Root";
158
+ var SearchListContent = /* @__PURE__ */ forwardRef(({ classNames, children }, forwardedRef) => {
159
+ return /* @__PURE__ */ React.createElement("div", {
160
+ role: "none",
161
+ // TODO(burdon): Remove p-1 hack.
162
+ className: mx("flex flex-col gap-2 bs-full is-full min-bs-0 overflow-hidden p-1", classNames),
163
+ ref: forwardedRef
164
+ }, children);
50
165
  });
51
- var SearchListContent = /* @__PURE__ */ forwardRef(({ children, classNames, ...props }, forwardedRef) => {
52
- var _effect = _useSignals();
53
- try {
54
- return /* @__PURE__ */ React.createElement(CommandList, {
55
- ...props,
56
- className: mx(classNames),
57
- ref: forwardedRef
58
- }, children);
59
- } finally {
60
- _effect.f();
61
- }
166
+ SearchListContent.displayName = "SearchList.Content";
167
+ var SearchListViewport = /* @__PURE__ */ forwardRef(({ classNames, children }, forwardedRef) => {
168
+ return /* @__PURE__ */ React.createElement("div", {
169
+ role: "listbox",
170
+ className: mx("bs-full is-full min-bs-0 overflow-y-auto", classNames),
171
+ ref: forwardedRef
172
+ }, children);
62
173
  });
63
- var SearchListEmpty = /* @__PURE__ */ forwardRef(({ children, classNames, ...props }, forwardedRef) => {
64
- var _effect = _useSignals();
65
- try {
66
- return /* @__PURE__ */ React.createElement(CommandEmpty, {
67
- ...props,
68
- className: mx(classNames),
69
- ref: forwardedRef
70
- }, children);
71
- } finally {
72
- _effect.f();
73
- }
174
+ SearchListViewport.displayName = "SearchList.Viewport";
175
+ var SearchListInput = /* @__PURE__ */ forwardRef(({ classNames, density: propsDensity, elevation: propsElevation, variant, placeholder, onChange, ...props }, forwardedRef) => {
176
+ const { query, onQueryChange, selectedValue, onSelectedValueChange, getItemValues, triggerSelect } = useSearchListInputContext("SearchList.Input");
177
+ const { t } = useTranslation(translationKey);
178
+ const { hasIosKeyboard, tx } = useThemeContext();
179
+ const density = useDensityContext(propsDensity);
180
+ const elevation = useElevationContext(propsElevation);
181
+ const defaultPlaceholder = t("search.placeholder");
182
+ const handleChange = useCallback((event) => {
183
+ onQueryChange(event.target.value);
184
+ onChange?.(event);
185
+ }, [
186
+ onQueryChange,
187
+ onChange
188
+ ]);
189
+ const handleKeyDown = useCallback((event) => {
190
+ const values = getItemValues();
191
+ if (values.length === 0) {
192
+ if (event.key === "Escape") {
193
+ onQueryChange("");
194
+ }
195
+ return;
196
+ }
197
+ const currentIndex = selectedValue !== void 0 ? values.indexOf(selectedValue) : -1;
198
+ switch (event.key) {
199
+ case "ArrowDown": {
200
+ event.preventDefault();
201
+ const nextIndex = currentIndex === -1 ? 0 : Math.min(currentIndex + 1, values.length - 1);
202
+ const nextValue = values[nextIndex];
203
+ if (nextValue !== void 0) {
204
+ onSelectedValueChange(nextValue);
205
+ }
206
+ break;
207
+ }
208
+ case "ArrowUp": {
209
+ event.preventDefault();
210
+ const prevIndex = currentIndex === -1 ? values.length - 1 : Math.max(currentIndex - 1, 0);
211
+ const prevValue = values[prevIndex];
212
+ if (prevValue !== void 0) {
213
+ onSelectedValueChange(prevValue);
214
+ }
215
+ break;
216
+ }
217
+ case "Enter": {
218
+ if (selectedValue !== void 0) {
219
+ event.preventDefault();
220
+ triggerSelect();
221
+ }
222
+ break;
223
+ }
224
+ case "Home": {
225
+ event.preventDefault();
226
+ const firstValue = values[0];
227
+ if (firstValue !== void 0) {
228
+ onSelectedValueChange(firstValue);
229
+ }
230
+ break;
231
+ }
232
+ case "End": {
233
+ event.preventDefault();
234
+ const lastValue = values[values.length - 1];
235
+ if (lastValue !== void 0) {
236
+ onSelectedValueChange(lastValue);
237
+ }
238
+ break;
239
+ }
240
+ case "Escape": {
241
+ event.preventDefault();
242
+ if (selectedValue !== void 0) {
243
+ onSelectedValueChange(void 0);
244
+ } else {
245
+ onQueryChange("");
246
+ }
247
+ break;
248
+ }
249
+ }
250
+ }, [
251
+ selectedValue,
252
+ onSelectedValueChange,
253
+ getItemValues,
254
+ triggerSelect,
255
+ onQueryChange
256
+ ]);
257
+ return /* @__PURE__ */ React.createElement("input", {
258
+ ...props,
259
+ ...props.autoFocus && !hasIosKeyboard && {
260
+ autoFocus: true
261
+ },
262
+ type: "text",
263
+ placeholder: placeholder ?? defaultPlaceholder,
264
+ className: tx("input.input", {
265
+ variant,
266
+ disabled: props.disabled,
267
+ density,
268
+ elevation
269
+ }, classNames),
270
+ value: query,
271
+ onChange: handleChange,
272
+ onKeyDown: handleKeyDown,
273
+ ref: forwardedRef
274
+ });
74
275
  });
75
- var SearchListItem = /* @__PURE__ */ forwardRef(({ children, classNames, onSelect, ...props }, forwardedRef) => {
76
- var _effect = _useSignals();
77
- try {
78
- const { onValueChange, onOpenChange } = useComboboxContext(SEARCHLIST_ITEM_NAME);
79
- const handleSelect = useCallback((nextValue) => {
80
- onValueChange?.(nextValue);
81
- onOpenChange?.(false);
82
- onSelect?.(nextValue);
83
- }, [
84
- onValueChange,
85
- onOpenChange,
86
- onSelect
87
- ]);
88
- return /* @__PURE__ */ React.createElement(CommandItem, {
89
- ...props,
90
- onSelect: handleSelect,
91
- className: mx("p-1 rounded select-none cursor-pointer data-[selected]:bg-hoverOverlay", classNames),
92
- ref: forwardedRef
93
- }, children);
94
- } finally {
95
- _effect.f();
96
- }
276
+ SearchListInput.displayName = "SearchList.Input";
277
+ var SearchListItem = /* @__PURE__ */ forwardRef(({ classNames, value, label, icon, checked, suffix, onSelect, disabled }, forwardedRef) => {
278
+ const { selectedValue, registerItem, unregisterItem } = useSearchListItemContext("SearchList.Item");
279
+ const internalRef = useRef(null);
280
+ const isSelected = selectedValue === value && !disabled;
281
+ useEffect(() => {
282
+ const element = internalRef.current;
283
+ if (element) {
284
+ registerItem(value, element, onSelect, disabled);
285
+ }
286
+ return () => unregisterItem(value);
287
+ }, [
288
+ value,
289
+ onSelect,
290
+ disabled,
291
+ registerItem,
292
+ unregisterItem
293
+ ]);
294
+ useEffect(() => {
295
+ if (isSelected && internalRef.current) {
296
+ internalRef.current.scrollIntoView({
297
+ block: "nearest",
298
+ behavior: "smooth"
299
+ });
300
+ }
301
+ }, [
302
+ isSelected
303
+ ]);
304
+ const handleClick = useCallback(() => {
305
+ if (!disabled) {
306
+ onSelect?.();
307
+ }
308
+ }, [
309
+ onSelect,
310
+ disabled
311
+ ]);
312
+ return /* @__PURE__ */ React.createElement("div", {
313
+ ref: (node) => {
314
+ internalRef.current = node;
315
+ if (typeof forwardedRef === "function") {
316
+ forwardedRef(node);
317
+ } else if (forwardedRef) {
318
+ forwardedRef.current = node;
319
+ }
320
+ },
321
+ role: "option",
322
+ "aria-selected": isSelected,
323
+ "aria-disabled": disabled,
324
+ "data-selected": isSelected,
325
+ "data-disabled": disabled,
326
+ "data-value": value,
327
+ tabIndex: -1,
328
+ className: mx("flex gap-2 items-center", "plb-1 pli-2 rounded-sm select-none cursor-pointer data-[selected=true]:bg-hoverOverlay hover:bg-hoverOverlay", disabled && "opacity-50 cursor-not-allowed hover:bg-transparent data-[selected=true]:bg-transparent", classNames),
329
+ onClick: handleClick
330
+ }, icon && /* @__PURE__ */ React.createElement(Icon, {
331
+ icon,
332
+ size: 5
333
+ }), /* @__PURE__ */ React.createElement("span", {
334
+ className: "is-0 grow truncate"
335
+ }, label), suffix && /* @__PURE__ */ React.createElement("span", {
336
+ className: mx("shrink-0", descriptionText)
337
+ }, suffix), checked && /* @__PURE__ */ React.createElement(Icon, {
338
+ icon: "ph--check--regular",
339
+ size: 5
340
+ }));
97
341
  });
98
- SearchListItem.displayName = SEARCHLIST_ITEM_NAME;
99
- var ComboboxRoot = ({ modalId: propsModalId, open: propsOpen, defaultOpen, onOpenChange: propsOnOpenChange, value: propsValue, defaultValue, onValueChange: propsOnValueChange, placeholder, children }) => {
100
- var _effect = _useSignals();
101
- try {
102
- const modalId = useId(COMBOBOX_NAME, propsModalId);
103
- const [open = false, onOpenChange] = useControllableState({
104
- prop: propsOpen,
105
- onChange: propsOnOpenChange,
106
- defaultProp: defaultOpen
107
- });
108
- const [value = "", onValueChange] = useControllableState({
109
- prop: propsValue,
110
- onChange: propsOnValueChange,
111
- defaultProp: defaultValue
112
- });
113
- return /* @__PURE__ */ React.createElement(ComboboxProvider, {
114
- isCombobox: true,
115
- modalId,
116
- open,
117
- onOpenChange,
118
- value,
119
- onValueChange,
120
- placeholder
121
- }, children);
122
- } finally {
123
- _effect.f();
124
- }
342
+ SearchListItem.displayName = "SearchList.Item";
343
+ var SearchListEmpty = ({ classNames, children }) => {
344
+ return /* @__PURE__ */ React.createElement("div", {
345
+ role: "status",
346
+ className: mx("flex flex-col is-full pli-2 plb-1", classNames)
347
+ }, children);
125
348
  };
126
- ComboboxRoot.displayName = COMBOBOX_NAME;
127
- var ComboboxTrigger = /* @__PURE__ */ forwardRef(({ children, onClick, ...props }, forwardedRef) => {
128
- var _effect = _useSignals();
129
- try {
130
- const { modalId, open, onOpenChange, placeholder, value } = useComboboxContext(COMBOBOX_TRIGGER_NAME);
131
- const handleClick = useCallback((event) => {
132
- onClick?.(event);
133
- onOpenChange?.(true);
134
- }, [
135
- onClick,
136
- onOpenChange
137
- ]);
138
- return /* @__PURE__ */ React.createElement(Button, {
139
- ...props,
140
- role: "combobox",
141
- "aria-expanded": open,
142
- "aria-controls": modalId,
143
- "aria-haspopup": "dialog",
144
- onClick: handleClick,
145
- ref: forwardedRef
146
- }, children ?? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", {
147
- className: mx("font-normal text-start flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
148
- }, value || placeholder), /* @__PURE__ */ React.createElement(Icon, {
149
- icon: "ph--caret-down--bold",
150
- size: 3
151
- })));
152
- } finally {
153
- _effect.f();
154
- }
349
+ SearchListEmpty.displayName = "SearchList.Empty";
350
+ var SearchListGroup = /* @__PURE__ */ forwardRef(({ classNames, heading, children }, forwardedRef) => {
351
+ return /* @__PURE__ */ React.createElement("div", {
352
+ ref: forwardedRef,
353
+ role: "group",
354
+ className: mx("flex flex-col", classNames)
355
+ }, heading && /* @__PURE__ */ React.createElement("div", {
356
+ role: "presentation",
357
+ className: "pli-2 plb-1 text-xs font-medium text-description"
358
+ }, heading), children);
155
359
  });
156
- ComboboxTrigger.displayName = COMBOBOX_TRIGGER_NAME;
360
+ SearchListGroup.displayName = "SearchList.Group";
157
361
  var SearchList = {
158
362
  Root: SearchListRoot,
159
- Input: SearchListInput,
160
363
  Content: SearchListContent,
364
+ Viewport: SearchListViewport,
365
+ Input: SearchListInput,
366
+ Item: SearchListItem,
161
367
  Empty: SearchListEmpty,
162
- Item: SearchListItem
368
+ Group: SearchListGroup
163
369
  };
164
- var Combobox = {
165
- Root: ComboboxRoot,
166
- Trigger: ComboboxTrigger,
167
- useComboboxContext
370
+
371
+ // src/components/SearchList/hooks/useGlobalFilter.tsx
372
+ import React2, { createContext as createContext2, useContext, useMemo as useMemo2 } from "react";
373
+ var GlobalFilterContext = /* @__PURE__ */ createContext2({});
374
+ var GlobalFilterProvider = ({ children, filter }) => {
375
+ const value = useMemo2(() => ({
376
+ filter
377
+ }), [
378
+ filter
379
+ ]);
380
+ return /* @__PURE__ */ React2.createElement(GlobalFilterContext.Provider, {
381
+ value
382
+ }, children);
383
+ };
384
+ var useGlobalFilter = () => {
385
+ return useContext(GlobalFilterContext);
386
+ };
387
+ var useGlobalFilteredObjects = (objects) => {
388
+ const { filter } = useGlobalFilter();
389
+ return useMemo2(() => {
390
+ if (!objects) {
391
+ return [];
392
+ }
393
+ if (!filter) {
394
+ return objects;
395
+ }
396
+ return filter(objects);
397
+ }, [
398
+ objects,
399
+ filter
400
+ ]);
168
401
  };
169
402
 
170
- // src/composites/PopoverCombobox.tsx
171
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
172
- import { useControllableState as useControllableState2 } from "@radix-ui/react-use-controllable-state";
173
- import React2, { forwardRef as forwardRef2 } from "react";
174
- import { Popover } from "@dxos/react-ui";
175
- var PopoverComboboxRoot = ({ modal, children, open: propsOpen, onOpenChange: propsOnOpenChange, defaultOpen, ...props }) => {
176
- var _effect = _useSignals2();
177
- try {
178
- const [open, onOpenChange] = useControllableState2({
179
- prop: propsOpen,
180
- onChange: propsOnOpenChange,
181
- defaultProp: defaultOpen
182
- });
183
- return /* @__PURE__ */ React2.createElement(Combobox.Root, {
184
- open,
185
- onOpenChange,
186
- ...props
187
- }, /* @__PURE__ */ React2.createElement(Popover.Root, {
188
- open,
189
- onOpenChange,
190
- modal
191
- }, children));
192
- } finally {
193
- _effect.f();
194
- }
403
+ // src/components/SearchList/hooks/useSearchListInput.ts
404
+ var useSearchListInput = () => {
405
+ const { query, onQueryChange, selectedValue, onSelectedValueChange, getItemValues, triggerSelect } = useSearchListInputContext("useSearchListInput");
406
+ return {
407
+ query,
408
+ onQueryChange,
409
+ selectedValue,
410
+ onSelectedValueChange,
411
+ getItemValues,
412
+ triggerSelect
413
+ };
195
414
  };
196
- var POPOVER_COMBOBOX_CONTENT_NAME = "PopoverComboboxContent";
197
- var PopoverComboboxContent = /* @__PURE__ */ forwardRef2(({ side = "bottom", collisionPadding = 48, sideOffset, align, alignOffset, avoidCollisions, collisionBoundary, arrowPadding, sticky, hideWhenDetached, onOpenAutoFocus, onCloseAutoFocus, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, forceMount, children, classNames, ...props }, forwardedRef) => {
198
- var _effect = _useSignals2();
199
- try {
200
- const { modalId } = Combobox.useComboboxContext(POPOVER_COMBOBOX_CONTENT_NAME);
201
- return /* @__PURE__ */ React2.createElement(Popover.Content, {
202
- side,
203
- sideOffset,
204
- align,
205
- alignOffset,
206
- avoidCollisions,
207
- collisionBoundary,
208
- collisionPadding,
209
- arrowPadding,
210
- sticky,
211
- hideWhenDetached,
212
- onOpenAutoFocus,
213
- onCloseAutoFocus,
214
- onEscapeKeyDown,
215
- onPointerDownOutside,
216
- onFocusOutside,
217
- onInteractOutside,
218
- forceMount,
219
- classNames,
220
- id: modalId,
221
- ref: forwardedRef
222
- }, /* @__PURE__ */ React2.createElement(Popover.Viewport, null, /* @__PURE__ */ React2.createElement(SearchList.Root, {
223
- ...props,
224
- classNames: "contents density-fine",
225
- role: "none"
226
- }, children)));
227
- } finally {
228
- _effect.f();
229
- }
415
+
416
+ // src/components/SearchList/hooks/useSearchListItem.ts
417
+ var useSearchListItem = () => {
418
+ const { selectedValue, registerItem, unregisterItem } = useSearchListItemContext("useSearchListItem");
419
+ return {
420
+ selectedValue,
421
+ registerItem,
422
+ unregisterItem
423
+ };
424
+ };
425
+
426
+ // src/components/SearchList/hooks/useSearchListResults.ts
427
+ import commandScore from "command-score";
428
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo3, useRef as useRef2, useState as useState2 } from "react";
429
+ var useSearchListResults = ({ items, filter, fuzzy = true, extract, minScore = 0 }) => {
430
+ const [query, setQuery] = useState2("");
431
+ const queryRef = useRef2("");
432
+ useEffect2(() => {
433
+ queryRef.current = "";
434
+ setQuery("");
435
+ }, [
436
+ items
437
+ ]);
438
+ const defaultExtract = useCallback2((item) => {
439
+ if (typeof item === "string") {
440
+ return item;
441
+ }
442
+ return item?.label ?? "";
443
+ }, []);
444
+ const extractFn = extract ?? defaultExtract;
445
+ const defaultFilter = useCallback2((item, query2) => {
446
+ const searchable = extractFn(item);
447
+ return searchable.toLowerCase().includes(query2.toLowerCase());
448
+ }, [
449
+ extractFn
450
+ ]);
451
+ const filterFn = filter ?? defaultFilter;
452
+ const handleSearch = useCallback2((searchQuery) => {
453
+ queryRef.current = searchQuery;
454
+ setQuery(searchQuery);
455
+ }, []);
456
+ const results = useMemo3(() => {
457
+ const currentQuery = queryRef.current;
458
+ if (!currentQuery) {
459
+ return items;
460
+ }
461
+ if (fuzzy) {
462
+ const scored = items.map((item) => ({
463
+ item,
464
+ score: commandScore(extractFn(item), currentQuery)
465
+ })).filter(({ score }) => score > minScore).sort((a, b) => b.score - a.score);
466
+ return scored.map(({ item }) => item);
467
+ } else {
468
+ return items.filter((item) => filterFn(item, currentQuery));
469
+ }
470
+ }, [
471
+ items,
472
+ query,
473
+ filterFn,
474
+ fuzzy,
475
+ extractFn,
476
+ minScore
477
+ ]);
478
+ return {
479
+ results,
480
+ handleSearch
481
+ };
482
+ };
483
+
484
+ // src/components/Combobox/Combobox.tsx
485
+ var COMBOBOX_NAME = "Combobox";
486
+ var COMBOBOX_CONTENT_NAME = "ComboboxContent";
487
+ var COMBOBOX_ITEM_NAME = "ComboboxItem";
488
+ var COMBOBOX_TRIGGER_NAME = "ComboboxTrigger";
489
+ var [ComboboxProvider, useComboboxContext] = createContext3(COMBOBOX_NAME, {});
490
+ var ComboboxRoot = ({ modal, modalId: propsModalId, open: propsOpen, defaultOpen, onOpenChange: propsOnOpenChange, value: propsValue, defaultValue, onValueChange: propsOnValueChange, placeholder, children }) => {
491
+ const modalId = useId(COMBOBOX_NAME, propsModalId);
492
+ const [open = false, onOpenChange] = useControllableState2({
493
+ prop: propsOpen,
494
+ onChange: propsOnOpenChange,
495
+ defaultProp: defaultOpen
496
+ });
497
+ const [value = "", onValueChange] = useControllableState2({
498
+ prop: propsValue,
499
+ onChange: propsOnValueChange,
500
+ defaultProp: defaultValue
501
+ });
502
+ return /* @__PURE__ */ React3.createElement(Popover.Root, {
503
+ open,
504
+ onOpenChange,
505
+ modal
506
+ }, /* @__PURE__ */ React3.createElement(ComboboxProvider, {
507
+ isCombobox: true,
508
+ modalId,
509
+ placeholder,
510
+ open,
511
+ onOpenChange,
512
+ value,
513
+ onValueChange
514
+ }, children));
515
+ };
516
+ var ComboboxContent = /* @__PURE__ */ forwardRef2(({ side = "bottom", collisionPadding = 48, sideOffset, align, alignOffset, avoidCollisions, collisionBoundary, arrowPadding, sticky, hideWhenDetached, onOpenAutoFocus, onCloseAutoFocus, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, forceMount, children, classNames, onSearch, value, defaultValue, debounceMs, label }, forwardedRef) => {
517
+ const { modalId } = useComboboxContext(COMBOBOX_CONTENT_NAME);
518
+ return /* @__PURE__ */ React3.createElement(Popover.Content, {
519
+ side,
520
+ sideOffset,
521
+ align,
522
+ alignOffset,
523
+ avoidCollisions,
524
+ collisionBoundary,
525
+ collisionPadding,
526
+ arrowPadding,
527
+ sticky,
528
+ hideWhenDetached,
529
+ onOpenAutoFocus,
530
+ onCloseAutoFocus,
531
+ onEscapeKeyDown,
532
+ onPointerDownOutside,
533
+ onFocusOutside,
534
+ onInteractOutside,
535
+ forceMount,
536
+ classNames: [
537
+ "is-[--radix-popover-trigger-width] max-bs-[--radix-popover-content-available-height] grid grid-rows-[min-content_1fr]",
538
+ classNames
539
+ ],
540
+ id: modalId,
541
+ ref: forwardedRef
542
+ }, /* @__PURE__ */ React3.createElement(SearchList.Root, {
543
+ onSearch,
544
+ value,
545
+ defaultValue,
546
+ debounceMs
547
+ }, /* @__PURE__ */ React3.createElement(SearchList.Content, null, children)));
230
548
  });
231
- PopoverComboboxContent.displayName = POPOVER_COMBOBOX_CONTENT_NAME;
232
- var PopoverComboboxTrigger = /* @__PURE__ */ forwardRef2((props, forwardedRef) => {
233
- var _effect = _useSignals2();
234
- try {
235
- return /* @__PURE__ */ React2.createElement(Popover.Trigger, {
236
- asChild: true
237
- }, /* @__PURE__ */ React2.createElement(Combobox.Trigger, {
238
- ...props,
239
- ref: forwardedRef
240
- }));
241
- } finally {
242
- _effect.f();
243
- }
549
+ ComboboxContent.displayName = COMBOBOX_CONTENT_NAME;
550
+ var ComboboxTrigger = /* @__PURE__ */ forwardRef2(({ children, onClick, ...props }, forwardedRef) => {
551
+ const { modalId, open, onOpenChange, placeholder, value } = useComboboxContext(COMBOBOX_TRIGGER_NAME);
552
+ const handleClick = useCallback3((event) => {
553
+ onClick?.(event);
554
+ onOpenChange?.(true);
555
+ }, [
556
+ onClick,
557
+ onOpenChange
558
+ ]);
559
+ return /* @__PURE__ */ React3.createElement(Popover.Trigger, {
560
+ asChild: true
561
+ }, /* @__PURE__ */ React3.createElement(Button, {
562
+ ...props,
563
+ role: "combobox",
564
+ "aria-expanded": open,
565
+ "aria-controls": modalId,
566
+ "aria-haspopup": "dialog",
567
+ onClick: handleClick,
568
+ ref: forwardedRef
569
+ }, children ?? /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement("span", {
570
+ className: mx2("font-normal text-start flex-1 min-is-0 truncate mie-2", !value && staticPlaceholderText)
571
+ }, value || placeholder), /* @__PURE__ */ React3.createElement(Icon2, {
572
+ icon: "ph--caret-down--bold",
573
+ size: 3
574
+ }))));
244
575
  });
245
- var PopoverComboboxVirtualTrigger = Popover.VirtualTrigger;
246
- var PopoverComboboxInput = /* @__PURE__ */ forwardRef2(({ classNames, ...props }, forwardedRef) => {
247
- var _effect = _useSignals2();
248
- try {
249
- return /* @__PURE__ */ React2.createElement(SearchList.Input, {
250
- ...props,
251
- classNames: [
252
- "mli-cardSpacingChrome mbs-cardSpacingChrome is-[calc(100%-2*var(--dx-cardSpacingChrome))]",
253
- classNames
254
- ],
255
- ref: forwardedRef
256
- });
257
- } finally {
258
- _effect.f();
259
- }
576
+ ComboboxTrigger.displayName = COMBOBOX_TRIGGER_NAME;
577
+ var ComboboxVirtualTrigger = Popover.VirtualTrigger;
578
+ var ComboboxInput = /* @__PURE__ */ forwardRef2(({ classNames, ...props }, forwardedRef) => {
579
+ return /* @__PURE__ */ React3.createElement(SearchList.Input, {
580
+ ...props,
581
+ classNames: [
582
+ "mli-cardSpacingChrome mbs-cardSpacingChrome mbe-0 is-[calc(100%-2*var(--dx-cardSpacingChrome))]",
583
+ classNames
584
+ ],
585
+ ref: forwardedRef
586
+ });
260
587
  });
261
- var PopoverComboboxList = /* @__PURE__ */ forwardRef2(({ constrainInline, constrainBlock, ...props }, forwardedRef) => {
262
- var _effect = _useSignals2();
263
- try {
264
- return /* @__PURE__ */ React2.createElement(Popover.Viewport, {
265
- constrainInline,
266
- constrainBlock
267
- }, /* @__PURE__ */ React2.createElement(SearchList.Content, {
268
- ...props,
269
- ref: forwardedRef
270
- }));
271
- } finally {
272
- _effect.f();
273
- }
588
+ var ComboboxList = /* @__PURE__ */ forwardRef2(({ classNames, ...props }, forwardedRef) => {
589
+ return /* @__PURE__ */ React3.createElement(SearchList.Viewport, {
590
+ ...props,
591
+ classNames: [
592
+ "plb-cardSpacingChrome",
593
+ classNames
594
+ ],
595
+ ref: forwardedRef
596
+ });
274
597
  });
275
- var PopoverComboboxItem = /* @__PURE__ */ forwardRef2(({ classNames, ...props }, forwardedRef) => {
276
- var _effect = _useSignals2();
277
- try {
278
- return /* @__PURE__ */ React2.createElement(SearchList.Item, {
279
- ...props,
280
- classNames: [
281
- "mli-cardSpacingChrome pli-cardSpacingChrome",
282
- classNames
283
- ],
284
- ref: forwardedRef
285
- });
286
- } finally {
287
- _effect.f();
288
- }
598
+ var ComboboxItem = /* @__PURE__ */ forwardRef2(({ classNames, onSelect, value, closeOnSelect = true, ...props }, forwardedRef) => {
599
+ const { onValueChange, onOpenChange } = useComboboxContext(COMBOBOX_ITEM_NAME);
600
+ const handleSelect = useCallback3(() => {
601
+ onSelect?.();
602
+ if (value !== void 0) {
603
+ onValueChange?.(value);
604
+ }
605
+ if (closeOnSelect) {
606
+ onOpenChange?.(false);
607
+ }
608
+ }, [
609
+ onSelect,
610
+ onValueChange,
611
+ onOpenChange,
612
+ value,
613
+ closeOnSelect
614
+ ]);
615
+ return /* @__PURE__ */ React3.createElement(SearchList.Item, {
616
+ ...props,
617
+ value,
618
+ classNames: [
619
+ "mli-cardSpacingChrome pli-cardSpacingChrome",
620
+ classNames
621
+ ],
622
+ onSelect: handleSelect,
623
+ ref: forwardedRef
624
+ });
289
625
  });
290
- var PopoverComboboxArrow = Popover.Arrow;
291
- var PopoverComboboxEmpty = SearchList.Empty;
292
- var PopoverCombobox = {
293
- Root: PopoverComboboxRoot,
294
- Content: PopoverComboboxContent,
295
- Trigger: PopoverComboboxTrigger,
296
- VirtualTrigger: PopoverComboboxVirtualTrigger,
297
- Input: PopoverComboboxInput,
298
- List: PopoverComboboxList,
299
- Item: PopoverComboboxItem,
300
- Arrow: PopoverComboboxArrow,
301
- Empty: PopoverComboboxEmpty
626
+ ComboboxItem.displayName = COMBOBOX_ITEM_NAME;
627
+ var ComboboxArrow = Popover.Arrow;
628
+ var ComboboxEmpty = SearchList.Empty;
629
+ var ComboboxPortal = Popover.Portal;
630
+ var Combobox = {
631
+ Root: ComboboxRoot,
632
+ Portal: ComboboxPortal,
633
+ Content: ComboboxContent,
634
+ Trigger: ComboboxTrigger,
635
+ VirtualTrigger: ComboboxVirtualTrigger,
636
+ Input: ComboboxInput,
637
+ List: ComboboxList,
638
+ Item: ComboboxItem,
639
+ Arrow: ComboboxArrow,
640
+ Empty: ComboboxEmpty
302
641
  };
303
642
 
304
- // src/translations.ts
305
- var translationKey = "react-ui-searchlist";
306
- var translations = [
307
- {
308
- "en-US": {
309
- [translationKey]: {}
310
- }
311
- }
312
- ];
643
+ // src/components/Listbox/Listbox.tsx
644
+ import { useArrowNavigationGroup } from "@fluentui/react-tabster";
645
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
646
+ import { createContextScope } from "@radix-ui/react-context";
647
+ import { useControllableState as useControllableState3 } from "@radix-ui/react-use-controllable-state";
648
+ import React4, { forwardRef as forwardRef3, useCallback as useCallback4, useEffect as useEffect3, useRef as useRef3 } from "react";
649
+ import { Icon as Icon3 } from "@dxos/react-ui";
650
+ import { mx as mx3 } from "@dxos/ui-theme";
651
+ var commandItem = "flex items-center overflow-hidden";
652
+ var LISTBOX_NAME = "Listbox";
653
+ var LISTBOX_OPTION_NAME = "ListboxOption";
654
+ var LISTBOX_OPTION_LABEL_NAME = "ListboxOptionLabel";
655
+ var LISTBOX_OPTION_INDICATOR_NAME = "ListboxOptionIndicator";
656
+ var [createListboxContext, createListboxScope] = createContextScope(LISTBOX_NAME, []);
657
+ var [createListboxOptionContext, createListboxOptionScope] = createContextScope(LISTBOX_OPTION_NAME, [
658
+ createListboxScope
659
+ ]);
660
+ var [ListboxProvider, useListboxContext] = createListboxContext(LISTBOX_NAME);
661
+ var [ListboxOptionProvider, useListboxOptionContext] = createListboxOptionContext(LISTBOX_OPTION_NAME);
662
+ var ListboxRoot = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
663
+ const { __listboxScope, children, classNames, value: propsValue, defaultValue, onValueChange, autoFocus, ...rootProps } = props;
664
+ const arrowGroup = useArrowNavigationGroup({
665
+ axis: "vertical"
666
+ });
667
+ const ref = useRef3(null);
668
+ const rootRef = useComposedRefs(ref, forwardedRef);
669
+ const [selectedValue, setSelectedValue] = useControllableState3({
670
+ prop: propsValue,
671
+ defaultProp: defaultValue,
672
+ onChange: onValueChange
673
+ });
674
+ const handleValueChange = (value) => {
675
+ setSelectedValue(value);
676
+ };
677
+ useEffect3(() => {
678
+ ref.current?.querySelector('[aria-selected="true"]')?.focus();
679
+ }, [
680
+ autoFocus
681
+ ]);
682
+ return /* @__PURE__ */ React4.createElement(ListboxProvider, {
683
+ scope: __listboxScope,
684
+ selectedValue,
685
+ onValueChange: handleValueChange
686
+ }, /* @__PURE__ */ React4.createElement("ul", {
687
+ role: "listbox",
688
+ ...rootProps,
689
+ className: mx3("is-full p-cardSpacingChrome", classNames),
690
+ ref: rootRef,
691
+ ...arrowGroup
692
+ }, children));
693
+ });
694
+ ListboxRoot.displayName = LISTBOX_NAME;
695
+ var ListboxOption = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
696
+ const { __listboxScope, children, classNames, value, ...rootProps } = props;
697
+ const { selectedValue, onValueChange } = useListboxContext(LISTBOX_OPTION_NAME, __listboxScope);
698
+ const isSelected = selectedValue === value;
699
+ const handleSelect = useCallback4(() => {
700
+ onValueChange(value);
701
+ }, [
702
+ value,
703
+ onValueChange
704
+ ]);
705
+ return /* @__PURE__ */ React4.createElement(ListboxOptionProvider, {
706
+ scope: __listboxScope,
707
+ value,
708
+ isSelected
709
+ }, /* @__PURE__ */ React4.createElement("li", {
710
+ role: "option",
711
+ ...rootProps,
712
+ "aria-selected": isSelected,
713
+ tabIndex: 0,
714
+ className: mx3("dx-focus-ring", "plb-1 pli-2 rounded-sm select-none cursor-pointer data-[selected=true]:bg-hoverOverlay hover:bg-hoverOverlay", commandItem, classNames),
715
+ onClick: handleSelect,
716
+ onKeyDown: ({ key }) => {
717
+ if ([
718
+ "Enter",
719
+ " "
720
+ ].includes(key)) {
721
+ handleSelect();
722
+ }
723
+ },
724
+ ref: forwardedRef
725
+ }, children));
726
+ });
727
+ ListboxOption.displayName = LISTBOX_OPTION_NAME;
728
+ var ListboxOptionLabel = /* @__PURE__ */ forwardRef3(({ children, classNames, ...rootProps }, forwardedRef) => {
729
+ return /* @__PURE__ */ React4.createElement("span", {
730
+ ...rootProps,
731
+ className: mx3("grow truncate", classNames),
732
+ ref: forwardedRef
733
+ }, children);
734
+ });
735
+ ListboxOptionLabel.displayName = LISTBOX_OPTION_LABEL_NAME;
736
+ var ListboxOptionIndicator = /* @__PURE__ */ forwardRef3((props, forwardedRef) => {
737
+ const { __listboxOptionScope, classNames, ...rootProps } = props;
738
+ const { isSelected } = useListboxOptionContext(LISTBOX_OPTION_INDICATOR_NAME, __listboxOptionScope);
739
+ return /* @__PURE__ */ React4.createElement(Icon3, {
740
+ icon: "ph--check--regular",
741
+ ...rootProps,
742
+ classNames: mx3(!isSelected && "invisible", classNames),
743
+ ref: forwardedRef
744
+ });
745
+ });
746
+ ListboxOptionIndicator.displayName = LISTBOX_OPTION_INDICATOR_NAME;
747
+ var Listbox = {
748
+ Root: ListboxRoot,
749
+ Option: ListboxOption,
750
+ OptionLabel: ListboxOptionLabel,
751
+ OptionIndicator: ListboxOptionIndicator
752
+ };
313
753
  export {
314
754
  Combobox,
315
- PopoverCombobox,
755
+ GlobalFilterProvider,
756
+ Listbox,
316
757
  SearchList,
758
+ createListboxScope,
317
759
  translationKey,
318
- translations
760
+ translations,
761
+ useGlobalFilter,
762
+ useGlobalFilteredObjects,
763
+ useListboxContext,
764
+ useSearchListInput,
765
+ useSearchListItem,
766
+ useSearchListResults
319
767
  };
320
768
  //# sourceMappingURL=index.mjs.map