@dxos/react-ui-searchlist 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae

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