@dxos/react-ui-searchlist 0.8.3 → 0.8.4-main.1068cf700f

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 (81) hide show
  1. package/dist/lib/browser/index.mjs +741 -265
  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 +741 -265
  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 +1 -2
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/translations.d.ts +7 -6
  42. package/dist/types/src/translations.d.ts.map +1 -1
  43. package/dist/types/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +24 -20
  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 +1 -2
  62. package/src/translations.ts +8 -4
  63. package/src/types/command-score.d.ts +16 -0
  64. package/dist/lib/node/index.cjs +0 -324
  65. package/dist/lib/node/index.cjs.map +0 -7
  66. package/dist/lib/node/meta.json +0 -1
  67. package/dist/types/src/components/SearchList.d.ts +0 -44
  68. package/dist/types/src/components/SearchList.d.ts.map +0 -1
  69. package/dist/types/src/components/SearchList.stories.d.ts +0 -15
  70. package/dist/types/src/components/SearchList.stories.d.ts.map +0 -1
  71. package/dist/types/src/composites/PopoverCombobox.d.ts +0 -32
  72. package/dist/types/src/composites/PopoverCombobox.d.ts.map +0 -1
  73. package/dist/types/src/composites/PopoverCombobox.stories.d.ts +0 -28
  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/SearchList.stories.tsx +0 -47
  78. package/src/components/SearchList.tsx +0 -250
  79. package/src/composites/PopoverCombobox.stories.tsx +0 -44
  80. package/src/composites/PopoverCombobox.tsx +0 -186
  81. package/src/composites/index.ts +0 -5
package/package.json CHANGED
@@ -1,18 +1,23 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-searchlist",
3
- "version": "0.8.3",
3
+ "version": "0.8.4-main.1068cf700f",
4
4
  "description": "A themed ⌘K-style combobox component, triggered by a button (or keyboard shortcut), where values are queried only within the invoked modal.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
7
11
  "license": "MIT",
8
12
  "author": "DXOS.org",
9
- "sideEffects": true,
13
+ "sideEffects": false,
10
14
  "type": "module",
11
15
  "exports": {
12
16
  ".": {
17
+ "source": "./src/index.ts",
13
18
  "types": "./dist/types/src/index.d.ts",
14
19
  "browser": "./dist/lib/browser/index.mjs",
15
- "node": "./dist/lib/browser/index.mjs"
20
+ "node": "./dist/lib/node-esm/index.mjs"
16
21
  }
17
22
  },
18
23
  "types": "dist/types/src/index.d.ts",
@@ -24,29 +29,28 @@
24
29
  "src"
25
30
  ],
26
31
  "dependencies": {
27
- "@preact-signals/safe-react": "^0.9.0",
32
+ "@fluentui/react-tabster": "9.26.11",
33
+ "@radix-ui/react-compose-refs": "1.1.1",
28
34
  "@radix-ui/react-context": "1.1.1",
29
35
  "@radix-ui/react-use-controllable-state": "1.1.0",
30
- "cmdk": "^0.2.0"
36
+ "command-score": "0.1.2"
31
37
  },
32
38
  "devDependencies": {
33
- "@phosphor-icons/react": "^2.1.5",
34
- "@types/react": "~18.2.0",
35
- "@types/react-dom": "~18.2.0",
36
- "react": "~18.2.0",
37
- "react-dom": "~18.2.0",
38
- "vite": "5.4.7",
39
- "@dxos/random": "0.8.3",
40
- "@dxos/react-ui-theme": "0.8.3",
41
- "@dxos/react-ui": "0.8.3",
42
- "@dxos/storybook-utils": "0.8.3"
39
+ "@types/react": "~19.2.7",
40
+ "@types/react-dom": "~19.2.3",
41
+ "react": "~19.2.3",
42
+ "react-dom": "~19.2.3",
43
+ "vite": "7.1.9",
44
+ "@dxos/random": "0.8.4-main.1068cf700f",
45
+ "@dxos/react-ui": "0.8.4-main.1068cf700f",
46
+ "@dxos/storybook-utils": "0.8.4-main.1068cf700f",
47
+ "@dxos/ui-theme": "0.8.4-main.1068cf700f"
43
48
  },
44
49
  "peerDependencies": {
45
- "@phosphor-icons/react": "^2.1.5",
46
- "react": "~18.2.0",
47
- "react-dom": "~18.2.0",
48
- "@dxos/react-ui": "0.8.3",
49
- "@dxos/react-ui-theme": "0.8.3"
50
+ "react": "~19.2.3",
51
+ "react-dom": "~19.2.3",
52
+ "@dxos/react-ui": "0.8.4-main.1068cf700f",
53
+ "@dxos/ui-theme": "0.8.4-main.1068cf700f"
50
54
  },
51
55
  "publishConfig": {
52
56
  "access": "public"
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React from 'react';
7
+
8
+ import { faker } from '@dxos/random';
9
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
10
+
11
+ import { translations } from '../../translations';
12
+ import { useSearchListResults } from '../SearchList/hooks';
13
+
14
+ import { Combobox } from './Combobox';
15
+
16
+ faker.seed(1234);
17
+
18
+ const items = faker.helpers.uniqueArray(faker.commerce.productName, 16).sort();
19
+
20
+ const DefaultStory = () => {
21
+ const { results, handleSearch } = useSearchListResults({
22
+ items,
23
+ });
24
+
25
+ return (
26
+ <Combobox.Root
27
+ placeholder='Nothing selected'
28
+ onValueChange={(value) => {
29
+ console.log('[Combobox.Root.onValueChange]', value);
30
+ }}
31
+ >
32
+ <Combobox.Trigger />
33
+ <Combobox.Content onSearch={handleSearch}>
34
+ <Combobox.Input placeholder='Search...' />
35
+ <Combobox.List>
36
+ {results.map((value) => (
37
+ <Combobox.Item key={value} value={value} label={value} />
38
+ ))}
39
+ </Combobox.List>
40
+ <Combobox.Arrow />
41
+ </Combobox.Content>
42
+ </Combobox.Root>
43
+ );
44
+ };
45
+
46
+ const meta = {
47
+ title: 'ui/react-ui-searchlist/Combobox',
48
+ component: Combobox.Root as any,
49
+ render: DefaultStory,
50
+ decorators: [withTheme(), withLayout({ layout: 'column', classNames: 'p-2' })],
51
+ parameters: {
52
+ translations,
53
+ },
54
+ } satisfies Meta<typeof DefaultStory>;
55
+
56
+ export default meta;
57
+
58
+ type Story = StoryObj<typeof meta>;
59
+
60
+ export const Default: Story = {
61
+ args: {},
62
+ };
@@ -0,0 +1,348 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { createContext } from '@radix-ui/react-context';
6
+ import { useControllableState } from '@radix-ui/react-use-controllable-state';
7
+ import React, { type PropsWithChildren, forwardRef, useCallback } from 'react';
8
+
9
+ import {
10
+ Button,
11
+ type ButtonProps,
12
+ Icon,
13
+ Popover,
14
+ type PopoverArrowProps,
15
+ type PopoverContentProps,
16
+ type PopoverVirtualTriggerProps,
17
+ } from '@dxos/react-ui';
18
+ import { useId } from '@dxos/react-ui';
19
+ import { mx, staticPlaceholderText } from '@dxos/ui-theme';
20
+
21
+ import {
22
+ SearchList,
23
+ type SearchListEmptyProps,
24
+ type SearchListInputProps,
25
+ type SearchListItemProps,
26
+ type SearchListRootProps,
27
+ type SearchListViewportProps,
28
+ } from '../SearchList';
29
+
30
+ const COMBOBOX_NAME = 'Combobox';
31
+ const COMBOBOX_CONTENT_NAME = 'ComboboxContent';
32
+ const COMBOBOX_ITEM_NAME = 'ComboboxItem';
33
+ const COMBOBOX_TRIGGER_NAME = 'ComboboxTrigger';
34
+
35
+ //
36
+ // Context
37
+ //
38
+
39
+ type ComboboxContextValue = {
40
+ modalId: string;
41
+ isCombobox: true;
42
+ placeholder?: string;
43
+ open: boolean;
44
+ onOpenChange: (nextOpen: boolean) => void;
45
+ value: string;
46
+ onValueChange: (nextValue: string) => void;
47
+ };
48
+
49
+ const [ComboboxProvider, useComboboxContext] = createContext<Partial<ComboboxContextValue>>(COMBOBOX_NAME, {});
50
+
51
+ //
52
+ // Root
53
+ //
54
+
55
+ type ComboboxRootProps = PropsWithChildren<
56
+ Partial<ComboboxContextValue & { modal: boolean; defaultOpen: boolean; defaultValue: string; placeholder: string }>
57
+ >;
58
+
59
+ const ComboboxRoot = ({
60
+ modal,
61
+ modalId: propsModalId,
62
+ open: propsOpen,
63
+ defaultOpen,
64
+ onOpenChange: propsOnOpenChange,
65
+ value: propsValue,
66
+ defaultValue,
67
+ onValueChange: propsOnValueChange,
68
+ placeholder,
69
+ children,
70
+ }: ComboboxRootProps) => {
71
+ const modalId = useId(COMBOBOX_NAME, propsModalId);
72
+ const [open = false, onOpenChange] = useControllableState({
73
+ prop: propsOpen,
74
+ onChange: propsOnOpenChange,
75
+ defaultProp: defaultOpen,
76
+ });
77
+ const [value = '', onValueChange] = useControllableState({
78
+ prop: propsValue,
79
+ onChange: propsOnValueChange,
80
+ defaultProp: defaultValue,
81
+ });
82
+
83
+ return (
84
+ <Popover.Root open={open} onOpenChange={onOpenChange} modal={modal}>
85
+ <ComboboxProvider
86
+ isCombobox
87
+ modalId={modalId}
88
+ placeholder={placeholder}
89
+ open={open}
90
+ onOpenChange={onOpenChange}
91
+ value={value}
92
+ onValueChange={onValueChange}
93
+ >
94
+ {children}
95
+ </ComboboxProvider>
96
+ </Popover.Root>
97
+ );
98
+ };
99
+
100
+ //
101
+ // ContentProps
102
+ //
103
+
104
+ type ComboboxContentProps = SearchListRootProps & PopoverContentProps & { label?: string };
105
+
106
+ const ComboboxContent = forwardRef<HTMLDivElement, ComboboxContentProps>(
107
+ (
108
+ {
109
+ side = 'bottom',
110
+ collisionPadding = 48,
111
+ sideOffset,
112
+ align,
113
+ alignOffset,
114
+ avoidCollisions,
115
+ collisionBoundary,
116
+ arrowPadding,
117
+ sticky,
118
+ hideWhenDetached,
119
+ onOpenAutoFocus,
120
+ onCloseAutoFocus,
121
+ onEscapeKeyDown,
122
+ onPointerDownOutside,
123
+ onFocusOutside,
124
+ onInteractOutside,
125
+ forceMount,
126
+ children,
127
+ classNames,
128
+ onSearch,
129
+ value,
130
+ defaultValue,
131
+ debounceMs,
132
+ label,
133
+ },
134
+ forwardedRef,
135
+ ) => {
136
+ const { modalId } = useComboboxContext(COMBOBOX_CONTENT_NAME);
137
+
138
+ return (
139
+ <Popover.Content
140
+ {...{
141
+ side,
142
+ sideOffset,
143
+ align,
144
+ alignOffset,
145
+ avoidCollisions,
146
+ collisionBoundary,
147
+ collisionPadding,
148
+ arrowPadding,
149
+ sticky,
150
+ hideWhenDetached,
151
+ onOpenAutoFocus,
152
+ onCloseAutoFocus,
153
+ onEscapeKeyDown,
154
+ onPointerDownOutside,
155
+ onFocusOutside,
156
+ onInteractOutside,
157
+ forceMount,
158
+ }}
159
+ classNames={[
160
+ 'is-[--radix-popover-trigger-width] max-bs-[--radix-popover-content-available-height] grid grid-rows-[min-content_1fr]',
161
+ classNames,
162
+ ]}
163
+ id={modalId}
164
+ ref={forwardedRef}
165
+ >
166
+ <SearchList.Root onSearch={onSearch} value={value} defaultValue={defaultValue} debounceMs={debounceMs}>
167
+ <SearchList.Content>{children}</SearchList.Content>
168
+ </SearchList.Root>
169
+ </Popover.Content>
170
+ );
171
+ },
172
+ );
173
+
174
+ ComboboxContent.displayName = COMBOBOX_CONTENT_NAME;
175
+
176
+ //
177
+ // Trigger
178
+ //
179
+
180
+ type ComboboxTriggerProps = ButtonProps;
181
+
182
+ const ComboboxTrigger = forwardRef<HTMLButtonElement, ComboboxTriggerProps>(
183
+ ({ children, onClick, ...props }, forwardedRef) => {
184
+ const { modalId, open, onOpenChange, placeholder, value } = useComboboxContext(COMBOBOX_TRIGGER_NAME);
185
+ const handleClick = useCallback(
186
+ (event: Parameters<Exclude<ButtonProps['onClick'], undefined>>[0]) => {
187
+ onClick?.(event);
188
+ onOpenChange?.(true);
189
+ },
190
+ [onClick, onOpenChange],
191
+ );
192
+
193
+ return (
194
+ <Popover.Trigger asChild>
195
+ <Button
196
+ {...props}
197
+ role='combobox'
198
+ aria-expanded={open}
199
+ aria-controls={modalId}
200
+ aria-haspopup='dialog'
201
+ onClick={handleClick}
202
+ ref={forwardedRef}
203
+ >
204
+ {children ?? (
205
+ <>
206
+ <span
207
+ className={mx('font-normal text-start flex-1 min-is-0 truncate mie-2', !value && staticPlaceholderText)}
208
+ >
209
+ {value || placeholder}
210
+ </span>
211
+ <Icon icon='ph--caret-down--bold' size={3} />
212
+ </>
213
+ )}
214
+ </Button>
215
+ </Popover.Trigger>
216
+ );
217
+ },
218
+ );
219
+
220
+ ComboboxTrigger.displayName = COMBOBOX_TRIGGER_NAME;
221
+
222
+ //
223
+ // VirtualTrigger
224
+ //
225
+
226
+ type ComboboxVirtualTriggerProps = PopoverVirtualTriggerProps;
227
+
228
+ const ComboboxVirtualTrigger = Popover.VirtualTrigger;
229
+
230
+ //
231
+ // Input
232
+ //
233
+
234
+ type ComboboxInputProps = SearchListInputProps;
235
+
236
+ const ComboboxInput = forwardRef<HTMLInputElement, ComboboxInputProps>(({ classNames, ...props }, forwardedRef) => {
237
+ return (
238
+ <SearchList.Input
239
+ {...props}
240
+ classNames={[
241
+ 'mli-cardSpacingChrome mbs-cardSpacingChrome mbe-0 is-[calc(100%-2*var(--dx-cardSpacingChrome))]',
242
+ classNames,
243
+ ]}
244
+ ref={forwardedRef}
245
+ />
246
+ );
247
+ });
248
+
249
+ //
250
+ // List
251
+ //
252
+
253
+ type ComboboxListProps = SearchListViewportProps;
254
+
255
+ const ComboboxList = forwardRef<HTMLDivElement, ComboboxListProps>(({ classNames, ...props }, forwardedRef) => {
256
+ return <SearchList.Viewport {...props} classNames={['plb-cardSpacingChrome', classNames]} ref={forwardedRef} />;
257
+ });
258
+
259
+ //
260
+ // Item
261
+ //
262
+
263
+ type ComboboxItemProps = SearchListItemProps & {
264
+ /** Whether to close the popover when this item is selected. Defaults to true. */
265
+ closeOnSelect?: boolean;
266
+ };
267
+
268
+ const ComboboxItem = forwardRef<HTMLDivElement, ComboboxItemProps>(
269
+ ({ classNames, onSelect, value, closeOnSelect = true, ...props }, forwardedRef) => {
270
+ const { onValueChange, onOpenChange } = useComboboxContext(COMBOBOX_ITEM_NAME);
271
+ const handleSelect = useCallback<NonNullable<SearchListItemProps['onSelect']>>(() => {
272
+ onSelect?.();
273
+ if (value !== undefined) {
274
+ onValueChange?.(value);
275
+ }
276
+ if (closeOnSelect) {
277
+ onOpenChange?.(false);
278
+ }
279
+ }, [onSelect, onValueChange, onOpenChange, value, closeOnSelect]);
280
+
281
+ return (
282
+ <SearchList.Item
283
+ {...props}
284
+ value={value}
285
+ classNames={['mli-cardSpacingChrome pli-cardSpacingChrome', classNames]}
286
+ onSelect={handleSelect}
287
+ ref={forwardedRef}
288
+ />
289
+ );
290
+ },
291
+ );
292
+
293
+ ComboboxItem.displayName = COMBOBOX_ITEM_NAME;
294
+
295
+ //
296
+ // Arrow
297
+ //
298
+
299
+ type ComboboxArrowProps = PopoverArrowProps;
300
+
301
+ const ComboboxArrow = Popover.Arrow;
302
+
303
+ //
304
+ // Empty
305
+ //
306
+
307
+ type ComboboxEmptyProps = SearchListEmptyProps;
308
+
309
+ const ComboboxEmpty = SearchList.Empty;
310
+
311
+ //
312
+ // Combobox
313
+ // https://www.w3.org/WAI/ARIA/apg/patterns/combobox
314
+ //
315
+
316
+ //
317
+ // Portal
318
+ //
319
+
320
+ type ComboboxPortalProps = React.ComponentPropsWithoutRef<typeof Popover.Portal>;
321
+
322
+ const ComboboxPortal = Popover.Portal;
323
+
324
+ export const Combobox = {
325
+ Root: ComboboxRoot,
326
+ Portal: ComboboxPortal,
327
+ Content: ComboboxContent,
328
+ Trigger: ComboboxTrigger,
329
+ VirtualTrigger: ComboboxVirtualTrigger,
330
+ Input: ComboboxInput,
331
+ List: ComboboxList,
332
+ Item: ComboboxItem,
333
+ Arrow: ComboboxArrow,
334
+ Empty: ComboboxEmpty,
335
+ };
336
+
337
+ export type {
338
+ ComboboxRootProps,
339
+ ComboboxPortalProps,
340
+ ComboboxContentProps,
341
+ ComboboxTriggerProps,
342
+ ComboboxVirtualTriggerProps,
343
+ ComboboxInputProps,
344
+ ComboboxListProps,
345
+ ComboboxItemProps,
346
+ ComboboxArrowProps,
347
+ ComboboxEmptyProps,
348
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export * from './Combobox';
@@ -0,0 +1,53 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useState } from 'react';
7
+
8
+ import { faker } from '@dxos/random';
9
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
10
+
11
+ import { translations } from '../../translations';
12
+
13
+ import { Listbox } from './Listbox';
14
+
15
+ faker.seed(1234);
16
+
17
+ type StoryItem = { value: string; label: string };
18
+
19
+ const options: StoryItem[] = faker.helpers.multiple(
20
+ () => ({ value: faker.string.uuid(), label: faker.commerce.productName() }) satisfies StoryItem,
21
+ { count: 16 },
22
+ );
23
+
24
+ const DefaultStory = () => {
25
+ const [selectedValue, setSelectedValue] = useState<string>();
26
+
27
+ return (
28
+ <Listbox.Root value={selectedValue} onValueChange={setSelectedValue}>
29
+ {options.map((option) => (
30
+ <Listbox.Option key={option.value} value={option.value}>
31
+ <Listbox.OptionLabel>{option.label}</Listbox.OptionLabel>
32
+ <Listbox.OptionIndicator />
33
+ </Listbox.Option>
34
+ ))}
35
+ </Listbox.Root>
36
+ );
37
+ };
38
+
39
+ const meta = {
40
+ title: 'ui/react-ui-searchlist/Listbox',
41
+ component: Listbox.Root,
42
+ render: DefaultStory,
43
+ decorators: [withTheme(), withLayout({ layout: 'column', classNames: 'p-2' })],
44
+ parameters: {
45
+ translations,
46
+ },
47
+ } satisfies Meta<typeof Listbox.Root>;
48
+
49
+ export default meta;
50
+
51
+ type Story = StoryObj<typeof meta>;
52
+
53
+ export const Default: Story = {};