@dxos/react-ui-searchlist 0.8.4-main.ae835ea → 0.8.4-main.bc674ce

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 (49) hide show
  1. package/dist/lib/browser/index.mjs +669 -337
  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 +669 -337
  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 +48 -8
  8. package/dist/types/src/components/Combobox/Combobox.d.ts.map +1 -1
  9. package/dist/types/src/components/Combobox/Combobox.stories.d.ts +1 -1
  10. package/dist/types/src/components/Combobox/Combobox.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/Listbox/Listbox.d.ts.map +1 -1
  12. package/dist/types/src/components/Listbox/Listbox.stories.d.ts +1 -1
  13. package/dist/types/src/components/SearchList/SearchList.d.ts +83 -20
  14. package/dist/types/src/components/SearchList/SearchList.d.ts.map +1 -1
  15. package/dist/types/src/components/SearchList/SearchList.stories.d.ts +10 -7
  16. package/dist/types/src/components/SearchList/SearchList.stories.d.ts.map +1 -1
  17. package/dist/types/src/components/SearchList/context.d.ts +33 -0
  18. package/dist/types/src/components/SearchList/context.d.ts.map +1 -0
  19. package/dist/types/src/components/SearchList/hooks/index.d.ts +5 -0
  20. package/dist/types/src/components/SearchList/hooks/index.d.ts.map +1 -0
  21. package/dist/types/src/components/SearchList/hooks/useGlobalFilter.d.ts +34 -0
  22. package/dist/types/src/components/SearchList/hooks/useGlobalFilter.d.ts.map +1 -0
  23. package/dist/types/src/components/SearchList/hooks/useSearchListInput.d.ts +12 -0
  24. package/dist/types/src/components/SearchList/hooks/useSearchListInput.d.ts.map +1 -0
  25. package/dist/types/src/components/SearchList/hooks/useSearchListItem.d.ts +10 -0
  26. package/dist/types/src/components/SearchList/hooks/useSearchListItem.d.ts.map +1 -0
  27. package/dist/types/src/components/SearchList/hooks/useSearchListResults.d.ts +36 -0
  28. package/dist/types/src/components/SearchList/hooks/useSearchListResults.d.ts.map +1 -0
  29. package/dist/types/src/components/SearchList/index.d.ts +1 -0
  30. package/dist/types/src/components/SearchList/index.d.ts.map +1 -1
  31. package/dist/types/src/translations.d.ts +2 -2
  32. package/dist/types/src/translations.d.ts.map +1 -1
  33. package/dist/types/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +20 -17
  35. package/src/components/Combobox/Combobox.stories.tsx +9 -4
  36. package/src/components/Combobox/Combobox.tsx +35 -14
  37. package/src/components/Listbox/Listbox.stories.tsx +1 -1
  38. package/src/components/Listbox/Listbox.tsx +8 -3
  39. package/src/components/SearchList/SearchList.stories.tsx +500 -30
  40. package/src/components/SearchList/SearchList.tsx +458 -62
  41. package/src/components/SearchList/context.ts +43 -0
  42. package/src/components/SearchList/hooks/index.ts +8 -0
  43. package/src/components/SearchList/hooks/useGlobalFilter.tsx +61 -0
  44. package/src/components/SearchList/hooks/useSearchListInput.ts +14 -0
  45. package/src/components/SearchList/hooks/useSearchListItem.ts +14 -0
  46. package/src/components/SearchList/hooks/useSearchListResults.ts +104 -0
  47. package/src/components/SearchList/index.ts +1 -0
  48. package/src/translations.ts +1 -1
  49. package/src/types/command-score.d.ts +16 -0
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-searchlist",
3
- "version": "0.8.4-main.ae835ea",
3
+ "version": "0.8.4-main.bc674ce",
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
  ".": {
@@ -25,29 +29,28 @@
25
29
  "src"
26
30
  ],
27
31
  "dependencies": {
28
- "@fluentui/react-tabster": "^9.24.2",
29
- "@preact-signals/safe-react": "^0.9.0",
32
+ "@fluentui/react-tabster": "9.26.11",
30
33
  "@radix-ui/react-compose-refs": "1.1.1",
31
34
  "@radix-ui/react-context": "1.1.1",
32
35
  "@radix-ui/react-use-controllable-state": "1.1.0",
33
- "cmdk": "^0.2.0"
36
+ "command-score": "0.1.2"
34
37
  },
35
38
  "devDependencies": {
36
- "@types/react": "~19.2.2",
37
- "@types/react-dom": "~19.2.2",
38
- "react": "~19.2.0",
39
- "react-dom": "~19.2.0",
39
+ "@types/react": "~19.2.7",
40
+ "@types/react-dom": "~19.2.3",
41
+ "react": "~19.2.3",
42
+ "react-dom": "~19.2.3",
40
43
  "vite": "7.1.9",
41
- "@dxos/random": "0.8.4-main.ae835ea",
42
- "@dxos/react-ui": "0.8.4-main.ae835ea",
43
- "@dxos/react-ui-theme": "0.8.4-main.ae835ea",
44
- "@dxos/storybook-utils": "0.8.4-main.ae835ea"
44
+ "@dxos/random": "0.8.4-main.bc674ce",
45
+ "@dxos/react-ui": "0.8.4-main.bc674ce",
46
+ "@dxos/storybook-utils": "0.8.4-main.bc674ce",
47
+ "@dxos/ui-theme": "0.8.4-main.bc674ce"
45
48
  },
46
49
  "peerDependencies": {
47
- "react": "^19.0.0",
48
- "react-dom": "^19.0.0",
49
- "@dxos/react-ui": "0.8.4-main.ae835ea",
50
- "@dxos/react-ui-theme": "0.8.4-main.ae835ea"
50
+ "react": "~19.2.3",
51
+ "react-dom": "~19.2.3",
52
+ "@dxos/react-ui": "0.8.4-main.bc674ce",
53
+ "@dxos/ui-theme": "0.8.4-main.bc674ce"
51
54
  },
52
55
  "publishConfig": {
53
56
  "access": "public"
@@ -9,6 +9,7 @@ import { faker } from '@dxos/random';
9
9
  import { withLayout, withTheme } from '@dxos/react-ui/testing';
10
10
 
11
11
  import { translations } from '../../translations';
12
+ import { useSearchListResults } from '../SearchList/hooks';
12
13
 
13
14
  import { Combobox } from './Combobox';
14
15
 
@@ -17,6 +18,10 @@ faker.seed(1234);
17
18
  const items = faker.helpers.uniqueArray(faker.commerce.productName, 16).sort();
18
19
 
19
20
  const DefaultStory = () => {
21
+ const { results, handleSearch } = useSearchListResults({
22
+ items,
23
+ });
24
+
20
25
  return (
21
26
  <Combobox.Root
22
27
  placeholder='Nothing selected'
@@ -25,11 +30,11 @@ const DefaultStory = () => {
25
30
  }}
26
31
  >
27
32
  <Combobox.Trigger />
28
- <Combobox.Content filter={(value, search) => (value.includes(search) ? 1 : 0)}>
33
+ <Combobox.Content onSearch={handleSearch}>
29
34
  <Combobox.Input placeholder='Search...' />
30
35
  <Combobox.List>
31
- {items.map((value) => (
32
- <Combobox.Item key={value}>{value}</Combobox.Item>
36
+ {results.map((value) => (
37
+ <Combobox.Item key={value} value={value} label={value} />
33
38
  ))}
34
39
  </Combobox.List>
35
40
  <Combobox.Arrow />
@@ -42,7 +47,7 @@ const meta = {
42
47
  title: 'ui/react-ui-searchlist/Combobox',
43
48
  component: Combobox.Root as any,
44
49
  render: DefaultStory,
45
- decorators: [withTheme, withLayout({ container: 'column', classNames: 'p-2' })],
50
+ decorators: [withTheme, withLayout({ layout: 'column', classNames: 'p-2' })],
46
51
  parameters: {
47
52
  translations,
48
53
  },
@@ -16,7 +16,7 @@ import {
16
16
  type PopoverVirtualTriggerProps,
17
17
  } from '@dxos/react-ui';
18
18
  import { useId } from '@dxos/react-ui';
19
- import { mx, staticPlaceholderText } from '@dxos/react-ui-theme';
19
+ import { mx, staticPlaceholderText } from '@dxos/ui-theme';
20
20
 
21
21
  import {
22
22
  SearchList,
@@ -101,7 +101,7 @@ const ComboboxRoot = ({
101
101
  // ContentProps
102
102
  //
103
103
 
104
- type ComboboxContentProps = SearchListRootProps & PopoverContentProps;
104
+ type ComboboxContentProps = SearchListRootProps & PopoverContentProps & { label?: string };
105
105
 
106
106
  const ComboboxContent = forwardRef<HTMLDivElement, ComboboxContentProps>(
107
107
  (
@@ -125,7 +125,11 @@ const ComboboxContent = forwardRef<HTMLDivElement, ComboboxContentProps>(
125
125
  forceMount,
126
126
  children,
127
127
  classNames,
128
- ...props
128
+ onSearch,
129
+ value,
130
+ defaultValue,
131
+ debounceMs,
132
+ label,
129
133
  },
130
134
  forwardedRef,
131
135
  ) => {
@@ -159,8 +163,10 @@ const ComboboxContent = forwardRef<HTMLDivElement, ComboboxContentProps>(
159
163
  id={modalId}
160
164
  ref={forwardedRef}
161
165
  >
162
- <SearchList.Root {...props} classNames='contents density-fine' role='none'>
163
- {children}
166
+ <SearchList.Root onSearch={onSearch} value={value} defaultValue={defaultValue} debounceMs={debounceMs}>
167
+ <div className='contents density-fine' aria-label={label} role='combobox' aria-expanded='true'>
168
+ {children}
169
+ </div>
164
170
  </SearchList.Root>
165
171
  </Popover.Content>
166
172
  );
@@ -262,23 +268,28 @@ const ComboboxList = forwardRef<HTMLDivElement, ComboboxListProps>(({ classNames
262
268
  // Item
263
269
  //
264
270
 
265
- type ComboboxItemProps = SearchListItemProps;
271
+ type ComboboxItemProps = SearchListItemProps & {
272
+ /** Whether to close the popover when this item is selected. Defaults to true. */
273
+ closeOnSelect?: boolean;
274
+ };
266
275
 
267
276
  const ComboboxItem = forwardRef<HTMLDivElement, ComboboxItemProps>(
268
- ({ classNames, onSelect, ...props }, forwardedRef) => {
277
+ ({ classNames, onSelect, value, closeOnSelect = true, ...props }, forwardedRef) => {
269
278
  const { onValueChange, onOpenChange } = useComboboxContext(COMBOBOX_ITEM_NAME);
270
- const handleSelect = useCallback<NonNullable<SearchListItemProps['onSelect']>>(
271
- (nextValue) => {
272
- onSelect?.(nextValue);
273
- onValueChange?.(nextValue);
279
+ const handleSelect = useCallback<NonNullable<SearchListItemProps['onSelect']>>(() => {
280
+ onSelect?.();
281
+ if (value !== undefined) {
282
+ onValueChange?.(value);
283
+ }
284
+ if (closeOnSelect) {
274
285
  onOpenChange?.(false);
275
- },
276
- [onSelect, onValueChange, onOpenChange],
277
- );
286
+ }
287
+ }, [onSelect, onValueChange, onOpenChange, value, closeOnSelect]);
278
288
 
279
289
  return (
280
290
  <SearchList.Item
281
291
  {...props}
292
+ value={value}
282
293
  classNames={['mli-cardSpacingChrome pli-cardSpacingChrome', classNames]}
283
294
  onSelect={handleSelect}
284
295
  ref={forwardedRef}
@@ -310,8 +321,17 @@ const ComboboxEmpty = SearchList.Empty;
310
321
  // https://www.w3.org/WAI/ARIA/apg/patterns/combobox
311
322
  //
312
323
 
324
+ //
325
+ // Portal
326
+ //
327
+
328
+ type ComboboxPortalProps = React.ComponentPropsWithoutRef<typeof Popover.Portal>;
329
+
330
+ const ComboboxPortal = Popover.Portal;
331
+
313
332
  export const Combobox = {
314
333
  Root: ComboboxRoot,
334
+ Portal: ComboboxPortal,
315
335
  Content: ComboboxContent,
316
336
  Trigger: ComboboxTrigger,
317
337
  VirtualTrigger: ComboboxVirtualTrigger,
@@ -324,6 +344,7 @@ export const Combobox = {
324
344
 
325
345
  export type {
326
346
  ComboboxRootProps,
347
+ ComboboxPortalProps,
327
348
  ComboboxContentProps,
328
349
  ComboboxTriggerProps,
329
350
  ComboboxVirtualTriggerProps,
@@ -40,7 +40,7 @@ const meta = {
40
40
  title: 'ui/react-ui-searchlist/Listbox',
41
41
  component: Listbox.Root,
42
42
  render: DefaultStory,
43
- decorators: [withTheme, withLayout({ container: 'column', classNames: 'p-2' })],
43
+ decorators: [withTheme, withLayout({ layout: 'column', classNames: 'p-2' })],
44
44
  parameters: {
45
45
  translations,
46
46
  },
@@ -9,9 +9,9 @@ import { useControllableState } from '@radix-ui/react-use-controllable-state';
9
9
  import React, { type ComponentPropsWithRef, forwardRef, useCallback, useEffect, useRef } from 'react';
10
10
 
11
11
  import { Icon, type IconProps, type ThemedClassName } from '@dxos/react-ui';
12
- import { mx } from '@dxos/react-ui-theme';
12
+ import { mx } from '@dxos/ui-theme';
13
13
 
14
- import { commandItem, searchListItem } from '../SearchList';
14
+ const commandItem = 'flex items-center overflow-hidden';
15
15
 
16
16
  const LISTBOX_NAME = 'Listbox';
17
17
  const LISTBOX_OPTION_NAME = 'ListboxOption';
@@ -135,7 +135,12 @@ const ListboxOption = forwardRef<HTMLLIElement, ListboxOptionProps>(
135
135
  {...rootProps}
136
136
  aria-selected={isSelected}
137
137
  tabIndex={0}
138
- className={mx('dx-focus-ring', commandItem, searchListItem, classNames)}
138
+ className={mx(
139
+ 'dx-focus-ring',
140
+ 'plb-1 pli-2 rounded-sm select-none cursor-pointer data-[selected=true]:bg-hoverOverlay hover:bg-hoverOverlay',
141
+ commandItem,
142
+ classNames,
143
+ )}
139
144
  onClick={handleSelect}
140
145
  onKeyDown={({ key }) => {
141
146
  if (['Enter', ' '].includes(key)) {