@dxos/react-ui-searchlist 0.8.4-main.e8ec1fe → 0.8.4-main.ef1bc66f44

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 +665 -336
  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 +665 -336
  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 +50 -10
  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 +84 -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 +36 -23
  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 +496 -28
  40. package/src/components/SearchList/SearchList.tsx +460 -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.e8ec1fe",
3
+ "version": "0.8.4-main.ef1bc66f44",
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.e8ec1fe",
42
- "@dxos/react-ui": "0.8.4-main.e8ec1fe",
43
- "@dxos/react-ui-theme": "0.8.4-main.e8ec1fe",
44
- "@dxos/storybook-utils": "0.8.4-main.e8ec1fe"
44
+ "@dxos/random": "0.8.4-main.ef1bc66f44",
45
+ "@dxos/react-ui": "0.8.4-main.ef1bc66f44",
46
+ "@dxos/storybook-utils": "0.8.4-main.ef1bc66f44",
47
+ "@dxos/ui-theme": "0.8.4-main.ef1bc66f44"
45
48
  },
46
49
  "peerDependencies": {
47
- "react": "^19.0.0",
48
- "react-dom": "^19.0.0",
49
- "@dxos/react-ui": "0.8.4-main.e8ec1fe",
50
- "@dxos/react-ui-theme": "0.8.4-main.e8ec1fe"
50
+ "react": "~19.2.3",
51
+ "react-dom": "~19.2.3",
52
+ "@dxos/react-ui": "0.8.4-main.ef1bc66f44",
53
+ "@dxos/ui-theme": "0.8.4-main.ef1bc66f44"
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,15 +16,15 @@ 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,
23
- type SearchListContentProps,
24
23
  type SearchListEmptyProps,
25
24
  type SearchListInputProps,
26
25
  type SearchListItemProps,
27
26
  type SearchListRootProps,
27
+ type SearchListViewportProps,
28
28
  } from '../SearchList';
29
29
 
30
30
  const COMBOBOX_NAME = 'Combobox';
@@ -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,8 @@ 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
+ <SearchList.Content>{children}</SearchList.Content>
164
168
  </SearchList.Root>
165
169
  </Popover.Content>
166
170
  );
@@ -246,39 +250,38 @@ const ComboboxInput = forwardRef<HTMLInputElement, ComboboxInputProps>(({ classN
246
250
  // List
247
251
  //
248
252
 
249
- type ComboboxListProps = SearchListContentProps;
253
+ type ComboboxListProps = SearchListViewportProps;
250
254
 
251
255
  const ComboboxList = forwardRef<HTMLDivElement, ComboboxListProps>(({ classNames, ...props }, forwardedRef) => {
252
- return (
253
- <SearchList.Content
254
- {...props}
255
- classNames={['min-bs-0 overflow-y-auto plb-cardSpacingChrome', classNames]}
256
- ref={forwardedRef}
257
- />
258
- );
256
+ return <SearchList.Viewport {...props} classNames={['plb-cardSpacingChrome', classNames]} ref={forwardedRef} />;
259
257
  });
260
258
 
261
259
  //
262
260
  // Item
263
261
  //
264
262
 
265
- type ComboboxItemProps = SearchListItemProps;
263
+ type ComboboxItemProps = SearchListItemProps & {
264
+ /** Whether to close the popover when this item is selected. Defaults to true. */
265
+ closeOnSelect?: boolean;
266
+ };
266
267
 
267
268
  const ComboboxItem = forwardRef<HTMLDivElement, ComboboxItemProps>(
268
- ({ classNames, onSelect, ...props }, forwardedRef) => {
269
+ ({ classNames, onSelect, value, closeOnSelect = true, ...props }, forwardedRef) => {
269
270
  const { onValueChange, onOpenChange } = useComboboxContext(COMBOBOX_ITEM_NAME);
270
- const handleSelect = useCallback<NonNullable<SearchListItemProps['onSelect']>>(
271
- (nextValue) => {
272
- onSelect?.(nextValue);
273
- onValueChange?.(nextValue);
271
+ const handleSelect = useCallback<NonNullable<SearchListItemProps['onSelect']>>(() => {
272
+ onSelect?.();
273
+ if (value !== undefined) {
274
+ onValueChange?.(value);
275
+ }
276
+ if (closeOnSelect) {
274
277
  onOpenChange?.(false);
275
- },
276
- [onSelect, onValueChange, onOpenChange],
277
- );
278
+ }
279
+ }, [onSelect, onValueChange, onOpenChange, value, closeOnSelect]);
278
280
 
279
281
  return (
280
282
  <SearchList.Item
281
283
  {...props}
284
+ value={value}
282
285
  classNames={['mli-cardSpacingChrome pli-cardSpacingChrome', classNames]}
283
286
  onSelect={handleSelect}
284
287
  ref={forwardedRef}
@@ -310,8 +313,17 @@ const ComboboxEmpty = SearchList.Empty;
310
313
  // https://www.w3.org/WAI/ARIA/apg/patterns/combobox
311
314
  //
312
315
 
316
+ //
317
+ // Portal
318
+ //
319
+
320
+ type ComboboxPortalProps = React.ComponentPropsWithoutRef<typeof Popover.Portal>;
321
+
322
+ const ComboboxPortal = Popover.Portal;
323
+
313
324
  export const Combobox = {
314
325
  Root: ComboboxRoot,
326
+ Portal: ComboboxPortal,
315
327
  Content: ComboboxContent,
316
328
  Trigger: ComboboxTrigger,
317
329
  VirtualTrigger: ComboboxVirtualTrigger,
@@ -324,6 +336,7 @@ export const Combobox = {
324
336
 
325
337
  export type {
326
338
  ComboboxRootProps,
339
+ ComboboxPortalProps,
327
340
  ComboboxContentProps,
328
341
  ComboboxTriggerProps,
329
342
  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)) {