@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
@@ -0,0 +1,214 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { useArrowNavigationGroup } from '@fluentui/react-tabster';
6
+ import { useComposedRefs } from '@radix-ui/react-compose-refs';
7
+ import { type Scope, createContextScope } from '@radix-ui/react-context';
8
+ import { useControllableState } from '@radix-ui/react-use-controllable-state';
9
+ import React, { type ComponentPropsWithRef, forwardRef, useCallback, useEffect, useRef } from 'react';
10
+
11
+ import { Icon, type IconProps, type ThemedClassName } from '@dxos/react-ui';
12
+ import { mx } from '@dxos/ui-theme';
13
+
14
+ const commandItem = 'flex items-center overflow-hidden';
15
+
16
+ const LISTBOX_NAME = 'Listbox';
17
+ const LISTBOX_OPTION_NAME = 'ListboxOption';
18
+ const LISTBOX_OPTION_LABEL_NAME = 'ListboxOptionLabel';
19
+ const LISTBOX_OPTION_INDICATOR_NAME = 'ListboxOptionIndicator';
20
+
21
+ //
22
+ // Context
23
+ //
24
+
25
+ type ListboxScopedProps<P> = P & { __listboxScope?: Scope };
26
+ type ListboxOptionScopedProps<P> = P & { __listboxOptionScope?: Scope };
27
+
28
+ type ListboxOptionProps = ThemedClassName<ComponentPropsWithRef<'li'>> & {
29
+ value: string;
30
+ };
31
+
32
+ const [createListboxContext, createListboxScope] = createContextScope(LISTBOX_NAME, []);
33
+ const [createListboxOptionContext, createListboxOptionScope] = createContextScope(LISTBOX_OPTION_NAME, [
34
+ createListboxScope,
35
+ ]);
36
+
37
+ type ListboxContextValue = {
38
+ selectedValue: string | undefined;
39
+ onValueChange: (value: string) => void;
40
+ };
41
+
42
+ type ListboxOptionContextValue = {
43
+ value: string;
44
+ isSelected: boolean;
45
+ };
46
+
47
+ const [ListboxProvider, useListboxContext] = createListboxContext<ListboxContextValue>(LISTBOX_NAME);
48
+ const [ListboxOptionProvider, useListboxOptionContext] =
49
+ createListboxOptionContext<ListboxOptionContextValue>(LISTBOX_OPTION_NAME);
50
+
51
+ //
52
+ // Root
53
+ //
54
+
55
+ type ListboxRootProps = ThemedClassName<ComponentPropsWithRef<'ul'>> & {
56
+ value?: string;
57
+ defaultValue?: string;
58
+ onValueChange?: (value: string) => void;
59
+ autoFocus?: boolean;
60
+ };
61
+
62
+ // TODO(thure): Note that this overlaps significantly with the the `SelectableListbox` story of `List.tsx` in `react-ui`,
63
+ // making this an exemplar of `List` specifying standard `role="listbox"` interactivity, though it is here because it
64
+ // coheres with SearchList’s styles and norms. This can be promoted to `react-ui`, but doing so should involve clearing
65
+ // the technical- and design-debt in its `List` component.
66
+ const ListboxRoot = forwardRef<HTMLUListElement, ListboxRootProps>(
67
+ (props: ListboxScopedProps<ListboxRootProps>, forwardedRef) => {
68
+ const {
69
+ __listboxScope,
70
+ children,
71
+ classNames,
72
+ value: propsValue,
73
+ defaultValue,
74
+ onValueChange,
75
+ autoFocus,
76
+ ...rootProps
77
+ } = props;
78
+
79
+ const arrowGroup = useArrowNavigationGroup({ axis: 'vertical' });
80
+ const ref = useRef<HTMLUListElement | null>(null);
81
+ const rootRef = useComposedRefs<HTMLUListElement>(ref, forwardedRef);
82
+
83
+ const [selectedValue, setSelectedValue] = useControllableState({
84
+ prop: propsValue,
85
+ defaultProp: defaultValue,
86
+ onChange: onValueChange,
87
+ });
88
+
89
+ const handleValueChange = (value: string) => {
90
+ setSelectedValue(value);
91
+ };
92
+
93
+ useEffect(() => {
94
+ // Autofocus the selected option on mount using querySelector
95
+ (ref.current?.querySelector('[aria-selected="true"]') as HTMLLIElement)?.focus();
96
+ }, [autoFocus]);
97
+
98
+ return (
99
+ <ListboxProvider scope={__listboxScope} selectedValue={selectedValue} onValueChange={handleValueChange}>
100
+ <ul
101
+ role='listbox'
102
+ {...rootProps}
103
+ className={mx('is-full p-cardSpacingChrome', classNames)}
104
+ ref={rootRef}
105
+ {...arrowGroup}
106
+ >
107
+ {children}
108
+ </ul>
109
+ </ListboxProvider>
110
+ );
111
+ },
112
+ );
113
+
114
+ ListboxRoot.displayName = LISTBOX_NAME;
115
+
116
+ //
117
+ // Option
118
+ //
119
+
120
+ const ListboxOption = forwardRef<HTMLLIElement, ListboxOptionProps>(
121
+ (props: ListboxScopedProps<ListboxOptionProps>, forwardedRef) => {
122
+ const { __listboxScope, children, classNames, value, ...rootProps } = props;
123
+ const { selectedValue, onValueChange } = useListboxContext(LISTBOX_OPTION_NAME, __listboxScope);
124
+
125
+ const isSelected = selectedValue === value;
126
+
127
+ const handleSelect = useCallback(() => {
128
+ onValueChange(value);
129
+ }, [value, onValueChange]);
130
+
131
+ return (
132
+ <ListboxOptionProvider scope={__listboxScope} value={value} isSelected={isSelected}>
133
+ <li
134
+ role='option'
135
+ {...rootProps}
136
+ aria-selected={isSelected}
137
+ tabIndex={0}
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
+ )}
144
+ onClick={handleSelect}
145
+ onKeyDown={({ key }) => {
146
+ if (['Enter', ' '].includes(key)) {
147
+ handleSelect();
148
+ }
149
+ }}
150
+ ref={forwardedRef}
151
+ >
152
+ {children}
153
+ </li>
154
+ </ListboxOptionProvider>
155
+ );
156
+ },
157
+ );
158
+
159
+ ListboxOption.displayName = LISTBOX_OPTION_NAME;
160
+
161
+ //
162
+ // OptionLabel
163
+ //
164
+
165
+ const ListboxOptionLabel = forwardRef<HTMLDivElement, ThemedClassName<ComponentPropsWithRef<'div'>>>(
166
+ ({ children, classNames, ...rootProps }, forwardedRef) => {
167
+ return (
168
+ <span {...rootProps} className={mx('grow truncate', classNames)} ref={forwardedRef}>
169
+ {children}
170
+ </span>
171
+ );
172
+ },
173
+ );
174
+
175
+ ListboxOptionLabel.displayName = LISTBOX_OPTION_LABEL_NAME;
176
+
177
+ type ListboxOptionIndicatorProps = Omit<IconProps, 'icon'> & Partial<Pick<IconProps, 'icon'>>;
178
+
179
+ //
180
+ // OptionIndicator
181
+ //
182
+
183
+ const ListboxOptionIndicator = forwardRef<SVGSVGElement, ListboxOptionIndicatorProps>(
184
+ (props: ListboxOptionScopedProps<ListboxOptionIndicatorProps>, forwardedRef) => {
185
+ const { __listboxOptionScope, classNames, ...rootProps } = props;
186
+ const { isSelected } = useListboxOptionContext(LISTBOX_OPTION_INDICATOR_NAME, __listboxOptionScope);
187
+
188
+ return (
189
+ <Icon
190
+ icon='ph--check--regular'
191
+ {...rootProps}
192
+ classNames={mx(!isSelected && 'invisible', classNames)}
193
+ ref={forwardedRef}
194
+ />
195
+ );
196
+ },
197
+ );
198
+
199
+ ListboxOptionIndicator.displayName = LISTBOX_OPTION_INDICATOR_NAME;
200
+
201
+ //
202
+ // Listbox
203
+ //
204
+
205
+ export const Listbox = {
206
+ Root: ListboxRoot,
207
+ Option: ListboxOption,
208
+ OptionLabel: ListboxOptionLabel,
209
+ OptionIndicator: ListboxOptionIndicator,
210
+ };
211
+
212
+ export { createListboxScope, useListboxContext };
213
+
214
+ export type { ListboxRootProps, ListboxOptionProps, ListboxScopedProps };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ export * from './Listbox';