@dxos/react-ui-searchlist 0.8.4-main.406dc2a → 0.8.4-main.40e3dcdf1b
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.
- package/README.md +1 -1
- package/dist/lib/browser/index.mjs +667 -336
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +667 -336
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Combobox/Combobox.d.ts +51 -10
- package/dist/types/src/components/Combobox/Combobox.d.ts.map +1 -1
- package/dist/types/src/components/Combobox/Combobox.stories.d.ts +1 -1
- package/dist/types/src/components/Combobox/Combobox.stories.d.ts.map +1 -1
- package/dist/types/src/components/Listbox/Listbox.d.ts.map +1 -1
- package/dist/types/src/components/Listbox/Listbox.stories.d.ts +1 -1
- package/dist/types/src/components/SearchList/SearchList.d.ts +86 -20
- package/dist/types/src/components/SearchList/SearchList.d.ts.map +1 -1
- package/dist/types/src/components/SearchList/SearchList.stories.d.ts +10 -7
- package/dist/types/src/components/SearchList/SearchList.stories.d.ts.map +1 -1
- package/dist/types/src/components/SearchList/context.d.ts +33 -0
- package/dist/types/src/components/SearchList/context.d.ts.map +1 -0
- package/dist/types/src/components/SearchList/hooks/index.d.ts +5 -0
- package/dist/types/src/components/SearchList/hooks/index.d.ts.map +1 -0
- package/dist/types/src/components/SearchList/hooks/useGlobalFilter.d.ts +34 -0
- package/dist/types/src/components/SearchList/hooks/useGlobalFilter.d.ts.map +1 -0
- package/dist/types/src/components/SearchList/hooks/useSearchListInput.d.ts +12 -0
- package/dist/types/src/components/SearchList/hooks/useSearchListInput.d.ts.map +1 -0
- package/dist/types/src/components/SearchList/hooks/useSearchListItem.d.ts +10 -0
- package/dist/types/src/components/SearchList/hooks/useSearchListItem.d.ts.map +1 -0
- package/dist/types/src/components/SearchList/hooks/useSearchListResults.d.ts +36 -0
- package/dist/types/src/components/SearchList/hooks/useSearchListResults.d.ts.map +1 -0
- package/dist/types/src/components/SearchList/index.d.ts +1 -0
- package/dist/types/src/components/SearchList/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -2
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -18
- package/src/components/Combobox/Combobox.stories.tsx +9 -4
- package/src/components/Combobox/Combobox.tsx +40 -32
- package/src/components/Listbox/Listbox.stories.tsx +1 -1
- package/src/components/Listbox/Listbox.tsx +9 -4
- package/src/components/SearchList/SearchList.stories.tsx +496 -28
- package/src/components/SearchList/SearchList.tsx +451 -60
- package/src/components/SearchList/context.ts +43 -0
- package/src/components/SearchList/hooks/index.ts +8 -0
- package/src/components/SearchList/hooks/useGlobalFilter.tsx +61 -0
- package/src/components/SearchList/hooks/useSearchListInput.ts +14 -0
- package/src/components/SearchList/hooks/useSearchListItem.ts +14 -0
- package/src/components/SearchList/hooks/useSearchListResults.ts +104 -0
- package/src/components/SearchList/index.ts +1 -0
- package/src/translations.ts +1 -1
- 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.
|
|
3
|
+
"version": "0.8.4-main.40e3dcdf1b",
|
|
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":
|
|
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": "
|
|
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
|
-
"
|
|
36
|
+
"command-score": "0.1.2"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
36
|
-
"@types/react": "~19.2.
|
|
37
|
-
"@types/react-dom": "~19.2.
|
|
38
|
-
"react": "~19.2.
|
|
39
|
-
"react-dom": "~19.2.
|
|
40
|
-
"vite": "7.1.
|
|
41
|
-
"@dxos/random": "0.8.4-main.
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/react-ui
|
|
44
|
-
"@dxos/
|
|
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.11",
|
|
44
|
+
"@dxos/random": "0.8.4-main.40e3dcdf1b",
|
|
45
|
+
"@dxos/storybook-utils": "0.8.4-main.40e3dcdf1b",
|
|
46
|
+
"@dxos/react-ui": "0.8.4-main.40e3dcdf1b",
|
|
47
|
+
"@dxos/ui-theme": "0.8.4-main.40e3dcdf1b"
|
|
45
48
|
},
|
|
46
49
|
"peerDependencies": {
|
|
47
|
-
"react": "
|
|
48
|
-
"react-dom": "
|
|
49
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
50
|
-
"@dxos/
|
|
50
|
+
"react": "~19.2.3",
|
|
51
|
+
"react-dom": "~19.2.3",
|
|
52
|
+
"@dxos/react-ui": "0.8.4-main.40e3dcdf1b",
|
|
53
|
+
"@dxos/ui-theme": "0.8.4-main.40e3dcdf1b"
|
|
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
|
|
33
|
+
<Combobox.Content onSearch={handleSearch}>
|
|
29
34
|
<Combobox.Input placeholder='Search...' />
|
|
30
35
|
<Combobox.List>
|
|
31
|
-
{
|
|
32
|
-
<Combobox.Item key={value}
|
|
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({
|
|
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
|
|
19
|
+
import { mx } 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
|
-
|
|
128
|
+
onSearch,
|
|
129
|
+
value,
|
|
130
|
+
defaultValue,
|
|
131
|
+
debounceMs,
|
|
132
|
+
label,
|
|
129
133
|
},
|
|
130
134
|
forwardedRef,
|
|
131
135
|
) => {
|
|
@@ -153,14 +157,14 @@ const ComboboxContent = forwardRef<HTMLDivElement, ComboboxContentProps>(
|
|
|
153
157
|
forceMount,
|
|
154
158
|
}}
|
|
155
159
|
classNames={[
|
|
156
|
-
'
|
|
160
|
+
'w-(--radix-popover-trigger-width) max-h-(--radix-popover-content-available-height) grid grid-rows-[min-content_1fr]',
|
|
157
161
|
classNames,
|
|
158
162
|
]}
|
|
159
163
|
id={modalId}
|
|
160
164
|
ref={forwardedRef}
|
|
161
165
|
>
|
|
162
|
-
<SearchList.Root {
|
|
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
|
);
|
|
@@ -199,9 +203,7 @@ const ComboboxTrigger = forwardRef<HTMLButtonElement, ComboboxTriggerProps>(
|
|
|
199
203
|
>
|
|
200
204
|
{children ?? (
|
|
201
205
|
<>
|
|
202
|
-
<span
|
|
203
|
-
className={mx('font-normal text-start flex-1 min-is-0 truncate mie-2', !value && staticPlaceholderText)}
|
|
204
|
-
>
|
|
206
|
+
<span className={mx('font-normal text-start flex-1 min-w-0 truncate me-2', !value && 'text-subdued')}>
|
|
205
207
|
{value || placeholder}
|
|
206
208
|
</span>
|
|
207
209
|
<Icon icon='ph--caret-down--bold' size={3} />
|
|
@@ -233,10 +235,7 @@ const ComboboxInput = forwardRef<HTMLInputElement, ComboboxInputProps>(({ classN
|
|
|
233
235
|
return (
|
|
234
236
|
<SearchList.Input
|
|
235
237
|
{...props}
|
|
236
|
-
classNames={[
|
|
237
|
-
'mli-cardSpacingChrome mbs-cardSpacingChrome mbe-0 is-[calc(100%-2*var(--dx-cardSpacingChrome))]',
|
|
238
|
-
classNames,
|
|
239
|
-
]}
|
|
238
|
+
classNames={['m-form-chrome mb-0 w-[calc(100%-2*var(--spacing-form-chrome))]', classNames]}
|
|
240
239
|
ref={forwardedRef}
|
|
241
240
|
/>
|
|
242
241
|
);
|
|
@@ -246,40 +245,39 @@ const ComboboxInput = forwardRef<HTMLInputElement, ComboboxInputProps>(({ classN
|
|
|
246
245
|
// List
|
|
247
246
|
//
|
|
248
247
|
|
|
249
|
-
type ComboboxListProps =
|
|
248
|
+
type ComboboxListProps = SearchListViewportProps;
|
|
250
249
|
|
|
251
250
|
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
|
-
);
|
|
251
|
+
return <SearchList.Viewport {...props} classNames={['py-form-chrome', classNames]} ref={forwardedRef} />;
|
|
259
252
|
});
|
|
260
253
|
|
|
261
254
|
//
|
|
262
255
|
// Item
|
|
263
256
|
//
|
|
264
257
|
|
|
265
|
-
type ComboboxItemProps = SearchListItemProps
|
|
258
|
+
type ComboboxItemProps = SearchListItemProps & {
|
|
259
|
+
/** Whether to close the popover when this item is selected. Defaults to true. */
|
|
260
|
+
closeOnSelect?: boolean;
|
|
261
|
+
};
|
|
266
262
|
|
|
267
263
|
const ComboboxItem = forwardRef<HTMLDivElement, ComboboxItemProps>(
|
|
268
|
-
({ classNames, onSelect, ...props }, forwardedRef) => {
|
|
264
|
+
({ classNames, onSelect, value, closeOnSelect = true, ...props }, forwardedRef) => {
|
|
269
265
|
const { onValueChange, onOpenChange } = useComboboxContext(COMBOBOX_ITEM_NAME);
|
|
270
|
-
const handleSelect = useCallback<NonNullable<SearchListItemProps['onSelect']>>(
|
|
271
|
-
(
|
|
272
|
-
|
|
273
|
-
onValueChange?.(
|
|
266
|
+
const handleSelect = useCallback<NonNullable<SearchListItemProps['onSelect']>>(() => {
|
|
267
|
+
onSelect?.();
|
|
268
|
+
if (value !== undefined) {
|
|
269
|
+
onValueChange?.(value);
|
|
270
|
+
}
|
|
271
|
+
if (closeOnSelect) {
|
|
274
272
|
onOpenChange?.(false);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
);
|
|
273
|
+
}
|
|
274
|
+
}, [onSelect, onValueChange, onOpenChange, value, closeOnSelect]);
|
|
278
275
|
|
|
279
276
|
return (
|
|
280
277
|
<SearchList.Item
|
|
281
278
|
{...props}
|
|
282
|
-
|
|
279
|
+
value={value}
|
|
280
|
+
classNames={['mx-form-chrome px-form-chrome', classNames]}
|
|
283
281
|
onSelect={handleSelect}
|
|
284
282
|
ref={forwardedRef}
|
|
285
283
|
/>
|
|
@@ -310,8 +308,17 @@ const ComboboxEmpty = SearchList.Empty;
|
|
|
310
308
|
// https://www.w3.org/WAI/ARIA/apg/patterns/combobox
|
|
311
309
|
//
|
|
312
310
|
|
|
311
|
+
//
|
|
312
|
+
// Portal
|
|
313
|
+
//
|
|
314
|
+
|
|
315
|
+
type ComboboxPortalProps = React.ComponentPropsWithoutRef<typeof Popover.Portal>;
|
|
316
|
+
|
|
317
|
+
const ComboboxPortal = Popover.Portal;
|
|
318
|
+
|
|
313
319
|
export const Combobox = {
|
|
314
320
|
Root: ComboboxRoot,
|
|
321
|
+
Portal: ComboboxPortal,
|
|
315
322
|
Content: ComboboxContent,
|
|
316
323
|
Trigger: ComboboxTrigger,
|
|
317
324
|
VirtualTrigger: ComboboxVirtualTrigger,
|
|
@@ -324,6 +331,7 @@ export const Combobox = {
|
|
|
324
331
|
|
|
325
332
|
export type {
|
|
326
333
|
ComboboxRootProps,
|
|
334
|
+
ComboboxPortalProps,
|
|
327
335
|
ComboboxContentProps,
|
|
328
336
|
ComboboxTriggerProps,
|
|
329
337
|
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({
|
|
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/
|
|
12
|
+
import { mx } from '@dxos/ui-theme';
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const commandItem = 'flex items-center overflow-hidden';
|
|
15
15
|
|
|
16
16
|
const LISTBOX_NAME = 'Listbox';
|
|
17
17
|
const LISTBOX_OPTION_NAME = 'ListboxOption';
|
|
@@ -100,7 +100,7 @@ const ListboxRoot = forwardRef<HTMLUListElement, ListboxRootProps>(
|
|
|
100
100
|
<ul
|
|
101
101
|
role='listbox'
|
|
102
102
|
{...rootProps}
|
|
103
|
-
className={mx('
|
|
103
|
+
className={mx('w-full p-form-chrome', classNames)}
|
|
104
104
|
ref={rootRef}
|
|
105
105
|
{...arrowGroup}
|
|
106
106
|
>
|
|
@@ -135,7 +135,12 @@ const ListboxOption = forwardRef<HTMLLIElement, ListboxOptionProps>(
|
|
|
135
135
|
{...rootProps}
|
|
136
136
|
aria-selected={isSelected}
|
|
137
137
|
tabIndex={0}
|
|
138
|
-
className={mx(
|
|
138
|
+
className={mx(
|
|
139
|
+
'dx-focus-ring',
|
|
140
|
+
'py-1 px-2 rounded-xs select-none cursor-pointer data-[selected=true]:bg-hover-overlay hover:bg-hover-overlay',
|
|
141
|
+
commandItem,
|
|
142
|
+
classNames,
|
|
143
|
+
)}
|
|
139
144
|
onClick={handleSelect}
|
|
140
145
|
onKeyDown={({ key }) => {
|
|
141
146
|
if (['Enter', ' '].includes(key)) {
|