@a-type/ui 4.1.0-beta.7 → 4.1.0
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/dist/cjs/components/autocomplete/Autocomplete.d.ts +12 -9
- package/dist/cjs/components/autocomplete/Autocomplete.js +19 -24
- package/dist/cjs/components/autocomplete/Autocomplete.js.map +1 -1
- package/dist/cjs/components/combobox/Combobox.d.ts +202 -0
- package/dist/cjs/components/combobox/Combobox.js +311 -0
- package/dist/cjs/components/combobox/Combobox.js.map +1 -0
- package/dist/cjs/components/combobox/Combobox.stories.d.ts +53 -0
- package/dist/cjs/components/combobox/Combobox.stories.js +115 -0
- package/dist/cjs/components/combobox/Combobox.stories.js.map +1 -0
- package/dist/cjs/components/input/Input.js +1 -1
- package/dist/cjs/components/input/Input.js.map +1 -1
- package/dist/css/main.css +4 -4
- package/dist/esm/components/autocomplete/Autocomplete.d.ts +12 -9
- package/dist/esm/components/autocomplete/Autocomplete.js +18 -24
- package/dist/esm/components/autocomplete/Autocomplete.js.map +1 -1
- package/dist/esm/components/combobox/Combobox.d.ts +202 -0
- package/dist/esm/components/combobox/Combobox.js +271 -0
- package/dist/esm/components/combobox/Combobox.js.map +1 -0
- package/dist/esm/components/combobox/Combobox.stories.d.ts +53 -0
- package/dist/esm/components/combobox/Combobox.stories.js +112 -0
- package/dist/esm/components/combobox/Combobox.stories.js.map +1 -0
- package/dist/esm/components/input/Input.js +1 -1
- package/dist/esm/components/input/Input.js.map +1 -1
- package/package.json +3 -2
- package/src/components/autocomplete/Autocomplete.tsx +46 -66
- package/src/components/combobox/Combobox.stories.tsx +289 -0
- package/src/components/combobox/Combobox.tsx +757 -0
- package/src/components/input/Input.tsx +1 -1
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
AutocompleteArrowProps,
|
|
3
3
|
Autocomplete as BaseAutocomplete,
|
|
4
4
|
AutocompleteGroupProps as BaseAutocompleteGroupProps,
|
|
5
|
-
AutocompleteInputProps as BaseAutocompleteInputProps,
|
|
6
5
|
AutocompleteItemProps as BaseAutocompleteItemProps,
|
|
7
6
|
AutocompleteListProps as BaseAutocompleteListProps,
|
|
8
7
|
AutocompletePopupProps as BaseAutocompletePopupProps,
|
|
@@ -15,36 +14,44 @@ import {
|
|
|
15
14
|
ComboboxRowProps as BaseAutocompleteRowProps,
|
|
16
15
|
} from '@base-ui/react/combobox';
|
|
17
16
|
import clsx from 'clsx';
|
|
18
|
-
import {
|
|
17
|
+
import { ReactNode } from 'react';
|
|
19
18
|
import { withClassName } from '../../hooks.js';
|
|
20
19
|
import { PaletteName } from '../../uno/index.js';
|
|
21
20
|
import { Button } from '../button/Button.js';
|
|
22
21
|
import { Chip, ChipProps } from '../chip/Chip.js';
|
|
22
|
+
import {
|
|
23
|
+
comboboxBackdropClassName,
|
|
24
|
+
ComboboxComposedInput,
|
|
25
|
+
comboboxEmptyClassName,
|
|
26
|
+
comboboxGroupClassName,
|
|
27
|
+
comboboxGroupItemClassName,
|
|
28
|
+
comboboxGroupItemListClassName,
|
|
29
|
+
comboboxGroupLabelClassName,
|
|
30
|
+
comboboxIconClassName,
|
|
31
|
+
ComboboxInputProps,
|
|
32
|
+
comboboxListClassName,
|
|
33
|
+
comboboxPopupClassName,
|
|
34
|
+
comboboxRowClassName,
|
|
35
|
+
ComboboxValueContext,
|
|
36
|
+
} from '../combobox/Combobox.js';
|
|
23
37
|
import { Icon } from '../icon/Icon.js';
|
|
24
|
-
import { Input } from '../input/Input.js';
|
|
25
38
|
import {
|
|
26
39
|
arrowClassName,
|
|
27
40
|
itemClassName,
|
|
28
|
-
itemListClassName,
|
|
29
|
-
popupClassName,
|
|
30
41
|
separatorClassName,
|
|
31
42
|
} from '../primitives/menus.js';
|
|
32
43
|
import { ArrowSvg } from '../utility/ArrowSvg.js';
|
|
33
44
|
import { SlotDiv } from '../utility/SlotDiv.js';
|
|
34
45
|
|
|
35
|
-
const ValueContext = createContext<string | number | readonly string[] | null>(
|
|
36
|
-
null,
|
|
37
|
-
);
|
|
38
|
-
|
|
39
46
|
const AutocompleteRoot = (props: BaseAutocompleteRootProps<any>) => {
|
|
40
47
|
return (
|
|
41
|
-
<
|
|
48
|
+
<ComboboxValueContext.Provider value={props.value || null}>
|
|
42
49
|
<BaseAutocomplete.Root {...props} />
|
|
43
|
-
</
|
|
50
|
+
</ComboboxValueContext.Provider>
|
|
44
51
|
);
|
|
45
52
|
};
|
|
46
53
|
|
|
47
|
-
export interface AutocompleteInputProps extends
|
|
54
|
+
export interface AutocompleteInputProps extends ComboboxInputProps {
|
|
48
55
|
ref?: React.Ref<HTMLInputElement>;
|
|
49
56
|
icon?: ReactNode;
|
|
50
57
|
disableCaret?: boolean;
|
|
@@ -56,47 +63,31 @@ const AutocompleteInput = ({
|
|
|
56
63
|
icon,
|
|
57
64
|
children,
|
|
58
65
|
disableClear,
|
|
59
|
-
...
|
|
66
|
+
...outerProps
|
|
60
67
|
}: AutocompleteInputProps) => {
|
|
61
|
-
const valueFromContext = useContext(ValueContext);
|
|
62
68
|
return (
|
|
63
69
|
<BaseAutocomplete.Input
|
|
64
|
-
render={(
|
|
65
|
-
<
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
)}
|
|
73
|
-
{!disableCaret && (
|
|
74
|
-
<BaseAutocomplete.Trigger
|
|
75
|
-
render={<Button emphasis="ghost" size="small" />}
|
|
76
|
-
>
|
|
77
|
-
<AutocompleteIcon data-open={state.open ? true : undefined} />
|
|
78
|
-
</BaseAutocomplete.Trigger>
|
|
79
|
-
)}
|
|
80
|
-
</div>
|
|
81
|
-
)}
|
|
70
|
+
render={(props, state) => (
|
|
71
|
+
<ComboboxComposedInput
|
|
72
|
+
{...props}
|
|
73
|
+
open={state.open}
|
|
74
|
+
disableCaret={disableCaret}
|
|
75
|
+
disableClear={disableClear}
|
|
76
|
+
icon={icon}
|
|
77
|
+
>
|
|
82
78
|
{children}
|
|
83
|
-
</
|
|
79
|
+
</ComboboxComposedInput>
|
|
84
80
|
)}
|
|
85
|
-
{...
|
|
81
|
+
{...outerProps}
|
|
86
82
|
/>
|
|
87
83
|
);
|
|
88
84
|
};
|
|
89
85
|
|
|
90
|
-
const AutocompleteIcon = withClassName(
|
|
86
|
+
export const AutocompleteIcon = withClassName(
|
|
91
87
|
({ className, ...props }: BaseAutocompleteIconProps) => (
|
|
92
88
|
<BaseAutocomplete.Icon
|
|
93
89
|
{...props}
|
|
94
|
-
className={clsx(
|
|
95
|
-
'icon',
|
|
96
|
-
'layer-components:(flex shrink-0 items-center justify-center transition-transform)',
|
|
97
|
-
'layer-components:data-[open]:(rotate-180)',
|
|
98
|
-
className,
|
|
99
|
-
)}
|
|
90
|
+
className={clsx(comboboxIconClassName, className)}
|
|
100
91
|
>
|
|
101
92
|
<Icon name="chevron" />
|
|
102
93
|
</BaseAutocomplete.Icon>
|
|
@@ -105,13 +96,12 @@ const AutocompleteIcon = withClassName(
|
|
|
105
96
|
|
|
106
97
|
const AutocompletePopup = withClassName(
|
|
107
98
|
BaseAutocomplete.Popup,
|
|
108
|
-
|
|
109
|
-
'layer-components:(w-[--anchor-width])',
|
|
99
|
+
comboboxPopupClassName,
|
|
110
100
|
);
|
|
111
101
|
|
|
112
102
|
const AutocompleteBackdrop = withClassName(
|
|
113
103
|
BaseAutocomplete.Backdrop,
|
|
114
|
-
|
|
104
|
+
comboboxBackdropClassName,
|
|
115
105
|
);
|
|
116
106
|
|
|
117
107
|
const AutocompleteArrow = ({ className, ...props }: AutocompleteArrowProps) => (
|
|
@@ -149,14 +139,12 @@ const AutocompleteContent = ({
|
|
|
149
139
|
|
|
150
140
|
const AutocompleteList = withClassName(
|
|
151
141
|
BaseAutocomplete.List,
|
|
152
|
-
|
|
153
|
-
'layer-components:(flex flex-col overscroll-contain outline-none overflow-y-auto overflow-unstable)',
|
|
154
|
-
'layer-components:empty:(p-0)',
|
|
142
|
+
comboboxListClassName,
|
|
155
143
|
);
|
|
156
144
|
|
|
157
145
|
const AutocompleteEmpty = withClassName(
|
|
158
146
|
BaseAutocomplete.Empty,
|
|
159
|
-
|
|
147
|
+
comboboxEmptyClassName,
|
|
160
148
|
);
|
|
161
149
|
|
|
162
150
|
export interface AutocompleteItemProps extends BaseAutocompleteItemProps {
|
|
@@ -180,27 +168,24 @@ const AutocompleteGroup = ({
|
|
|
180
168
|
return (
|
|
181
169
|
<BaseAutocomplete.Group
|
|
182
170
|
{...props}
|
|
183
|
-
className={clsx(
|
|
184
|
-
'layer-components:(flex flex-col gap-xs overflow-hidden p-sm)',
|
|
185
|
-
className,
|
|
186
|
-
)}
|
|
171
|
+
className={clsx(comboboxGroupClassName, className)}
|
|
187
172
|
/>
|
|
188
173
|
);
|
|
189
174
|
};
|
|
190
175
|
|
|
191
176
|
const AutocompleteGroupItemList = withClassName(
|
|
192
177
|
SlotDiv,
|
|
193
|
-
|
|
178
|
+
comboboxGroupItemListClassName,
|
|
194
179
|
);
|
|
195
180
|
|
|
196
181
|
const AutocompleteGroupLabel = withClassName(
|
|
197
182
|
BaseAutocomplete.GroupLabel,
|
|
198
|
-
|
|
183
|
+
comboboxGroupLabelClassName,
|
|
199
184
|
);
|
|
200
185
|
|
|
201
186
|
const AutocompleteRow: React.FC<BaseAutocompleteRowProps> = withClassName(
|
|
202
187
|
BaseAutocomplete.Row,
|
|
203
|
-
|
|
188
|
+
comboboxRowClassName,
|
|
204
189
|
);
|
|
205
190
|
|
|
206
191
|
const AutocompleteSeparator = withClassName(
|
|
@@ -224,12 +209,7 @@ function AutocompleteGroupItem({
|
|
|
224
209
|
<BaseAutocomplete.Item
|
|
225
210
|
render={replace ?? <Button render={<Chip render={render} />} />}
|
|
226
211
|
{...props}
|
|
227
|
-
className={clsx(
|
|
228
|
-
'palette-primary',
|
|
229
|
-
'layer-composed-2:(bg-white)',
|
|
230
|
-
'layer-composed-2:data-[highlighted]:(ring-2 bg-main-wash ring-primary)',
|
|
231
|
-
className,
|
|
232
|
-
)}
|
|
212
|
+
className={clsx(comboboxGroupItemClassName, className)}
|
|
233
213
|
/>
|
|
234
214
|
);
|
|
235
215
|
}
|
|
@@ -238,7 +218,10 @@ export type AutocompleteClearProps = ButtonProps & {
|
|
|
238
218
|
ref?: React.Ref<HTMLButtonElement>;
|
|
239
219
|
children?: ReactNode;
|
|
240
220
|
};
|
|
241
|
-
const AutocompleteClear = ({
|
|
221
|
+
export const AutocompleteClear = ({
|
|
222
|
+
children,
|
|
223
|
+
...props
|
|
224
|
+
}: AutocompleteClearProps) => (
|
|
242
225
|
<BaseAutocomplete.Clear
|
|
243
226
|
render={<Button emphasis="ghost" size="small" />}
|
|
244
227
|
{...props}
|
|
@@ -276,7 +259,7 @@ const baseSubComponents = {
|
|
|
276
259
|
function createAutocomplete<TItem>() {
|
|
277
260
|
function TypedRoot(
|
|
278
261
|
props: Omit<BaseAutocompleteRootProps<TItem>, 'items'> & {
|
|
279
|
-
items
|
|
262
|
+
items?: readonly TItem[];
|
|
280
263
|
},
|
|
281
264
|
) {
|
|
282
265
|
return <AutocompleteRoot {...(props as any)} />;
|
|
@@ -290,10 +273,7 @@ function createAutocomplete<TItem>() {
|
|
|
290
273
|
}
|
|
291
274
|
return Object.assign(TypedRoot, {
|
|
292
275
|
...baseSubComponents,
|
|
293
|
-
Input: AutocompleteInput,
|
|
294
|
-
Content: AutocompleteContent,
|
|
295
276
|
List: TypedList,
|
|
296
|
-
Empty: AutocompleteEmpty,
|
|
297
277
|
Item: AutocompleteItem,
|
|
298
278
|
});
|
|
299
279
|
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Box } from '../box/Box.js';
|
|
4
|
+
import { Button } from '../button/Button.js';
|
|
5
|
+
import { Icon } from '../icon/Icon.js';
|
|
6
|
+
import { Combobox } from './Combobox.js';
|
|
7
|
+
|
|
8
|
+
interface Args {
|
|
9
|
+
arrow?: boolean;
|
|
10
|
+
autoHighlight?: boolean;
|
|
11
|
+
creatable?: boolean;
|
|
12
|
+
highlightItemOnHover?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: 'Components/Combobox',
|
|
17
|
+
argTypes: {
|
|
18
|
+
arrow: {
|
|
19
|
+
control: 'boolean',
|
|
20
|
+
description: 'Whether to show the arrow on the Combobox popup.',
|
|
21
|
+
defaultValue: false,
|
|
22
|
+
},
|
|
23
|
+
autoHighlight: {
|
|
24
|
+
control: 'boolean',
|
|
25
|
+
description:
|
|
26
|
+
'If true, the first item will be automatically highlighted when the list opens.',
|
|
27
|
+
defaultValue: false,
|
|
28
|
+
},
|
|
29
|
+
highlightItemOnHover: {
|
|
30
|
+
control: 'boolean',
|
|
31
|
+
description:
|
|
32
|
+
'If true, items will be highlighted when hovered with the mouse.',
|
|
33
|
+
defaultValue: false,
|
|
34
|
+
},
|
|
35
|
+
creatable: {
|
|
36
|
+
control: 'boolean',
|
|
37
|
+
description:
|
|
38
|
+
'If true, the Combobox will allow creating new items based on user input.',
|
|
39
|
+
defaultValue: false,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
args: {
|
|
43
|
+
arrow: false,
|
|
44
|
+
autoHighlight: false,
|
|
45
|
+
highlightItemOnHover: true,
|
|
46
|
+
creatable: false,
|
|
47
|
+
},
|
|
48
|
+
parameters: {
|
|
49
|
+
controls: { expanded: true },
|
|
50
|
+
},
|
|
51
|
+
} satisfies Meta<Args>;
|
|
52
|
+
|
|
53
|
+
export default meta;
|
|
54
|
+
|
|
55
|
+
type Story = StoryObj<Args>;
|
|
56
|
+
|
|
57
|
+
export interface Item {
|
|
58
|
+
id: string;
|
|
59
|
+
label: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const items: Item[] = [
|
|
63
|
+
{ id: 'apple', label: 'Apple' },
|
|
64
|
+
{ id: 'banana', label: 'Banana' },
|
|
65
|
+
{ id: 'cherry', label: 'Cherry' },
|
|
66
|
+
{ id: 'date', label: 'Date' },
|
|
67
|
+
{ id: 'elderberry', label: 'Elderberry' },
|
|
68
|
+
{ id: 'fig', label: 'Fig' },
|
|
69
|
+
{ id: 'grape', label: 'Grape' },
|
|
70
|
+
{ id: 'honeydew', label: 'Honeydew' },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const ExampleCombobox = Combobox.create<Item>();
|
|
74
|
+
|
|
75
|
+
export const Default: Story = {
|
|
76
|
+
render({ arrow, autoHighlight, highlightItemOnHover, creatable }) {
|
|
77
|
+
const [value, setValue] = useState<Item | null>(null);
|
|
78
|
+
const allItems =
|
|
79
|
+
value && items.includes(value)
|
|
80
|
+
? items
|
|
81
|
+
: value
|
|
82
|
+
? [value, ...items]
|
|
83
|
+
: items;
|
|
84
|
+
return (
|
|
85
|
+
<ExampleCombobox
|
|
86
|
+
value={value}
|
|
87
|
+
onValueChange={setValue}
|
|
88
|
+
items={allItems}
|
|
89
|
+
autoHighlight={autoHighlight}
|
|
90
|
+
highlightItemOnHover={highlightItemOnHover}
|
|
91
|
+
showCreatableItem={creatable}
|
|
92
|
+
onCreate={
|
|
93
|
+
creatable
|
|
94
|
+
? (value: string) => {
|
|
95
|
+
console.log('Creating item:', value);
|
|
96
|
+
setValue({ id: value, label: value });
|
|
97
|
+
}
|
|
98
|
+
: undefined
|
|
99
|
+
}
|
|
100
|
+
>
|
|
101
|
+
<ExampleCombobox.Input
|
|
102
|
+
icon={<Icon name="food" />}
|
|
103
|
+
className="w-[200px]"
|
|
104
|
+
/>
|
|
105
|
+
<ExampleCombobox.Content arrow={arrow}>
|
|
106
|
+
<ExampleCombobox.List>
|
|
107
|
+
{(item) => (
|
|
108
|
+
<ExampleCombobox.Item key={item.id} value={item}>
|
|
109
|
+
{item.label}
|
|
110
|
+
</ExampleCombobox.Item>
|
|
111
|
+
)}
|
|
112
|
+
</ExampleCombobox.List>
|
|
113
|
+
<ExampleCombobox.Empty>No results found.</ExampleCombobox.Empty>
|
|
114
|
+
</ExampleCombobox.Content>
|
|
115
|
+
</ExampleCombobox>
|
|
116
|
+
);
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
interface ItemGroup {
|
|
121
|
+
category: string;
|
|
122
|
+
items: Item[];
|
|
123
|
+
}
|
|
124
|
+
const groupedItems: ItemGroup[] = [
|
|
125
|
+
{
|
|
126
|
+
category: 'Fruits',
|
|
127
|
+
items: [
|
|
128
|
+
{ id: 'apple', label: 'Apple' },
|
|
129
|
+
{ id: 'banana', label: 'Banana' },
|
|
130
|
+
{ id: 'cherry', label: 'Cherry' },
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
category: 'Berries',
|
|
135
|
+
items: [
|
|
136
|
+
{ id: 'strawberry', label: 'Strawberry' },
|
|
137
|
+
{ id: 'blueberry', label: 'Blueberry' },
|
|
138
|
+
{ id: 'raspberry', label: 'Raspberry' },
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
const GroupedCombobox = Combobox.createGrouped<ItemGroup>();
|
|
144
|
+
|
|
145
|
+
export const Grouped: Story = {
|
|
146
|
+
render({ arrow, autoHighlight, highlightItemOnHover, creatable }) {
|
|
147
|
+
const [value, setValue] = useState<Item | null>(null);
|
|
148
|
+
const [input, setInput] = useState<string>('');
|
|
149
|
+
return (
|
|
150
|
+
<GroupedCombobox
|
|
151
|
+
value={value}
|
|
152
|
+
onValueChange={setValue}
|
|
153
|
+
inputValue={input}
|
|
154
|
+
onInputValueChange={setInput}
|
|
155
|
+
items={groupedItems}
|
|
156
|
+
autoHighlight={autoHighlight}
|
|
157
|
+
highlightItemOnHover={highlightItemOnHover}
|
|
158
|
+
onCreate={
|
|
159
|
+
creatable
|
|
160
|
+
? (value: string) => alert(`Create item: ${value}`)
|
|
161
|
+
: undefined
|
|
162
|
+
}
|
|
163
|
+
>
|
|
164
|
+
<GroupedCombobox.Input />
|
|
165
|
+
<GroupedCombobox.Content arrow={arrow}>
|
|
166
|
+
<GroupedCombobox.List>
|
|
167
|
+
{(group) => (
|
|
168
|
+
<GroupedCombobox.Group key={group.category}>
|
|
169
|
+
<GroupedCombobox.GroupLabel>
|
|
170
|
+
{group.category}
|
|
171
|
+
</GroupedCombobox.GroupLabel>
|
|
172
|
+
<GroupedCombobox.GroupList>
|
|
173
|
+
{group.items.map((item) => (
|
|
174
|
+
<GroupedCombobox.Item key={item.id} value={item}>
|
|
175
|
+
{item.label}
|
|
176
|
+
</GroupedCombobox.Item>
|
|
177
|
+
))}
|
|
178
|
+
</GroupedCombobox.GroupList>
|
|
179
|
+
</GroupedCombobox.Group>
|
|
180
|
+
)}
|
|
181
|
+
</GroupedCombobox.List>
|
|
182
|
+
<GroupedCombobox.Empty>
|
|
183
|
+
{creatable ? (
|
|
184
|
+
<div>
|
|
185
|
+
<Icon name="enterKey" /> Create "{input}"
|
|
186
|
+
</div>
|
|
187
|
+
) : (
|
|
188
|
+
`No results found.`
|
|
189
|
+
)}
|
|
190
|
+
</GroupedCombobox.Empty>
|
|
191
|
+
<GroupedCombobox.Separator />
|
|
192
|
+
<div className="p-sm text-xs color-gray-dark">
|
|
193
|
+
Select your favorite fruit or berry.
|
|
194
|
+
{creatable ? ' Enter creates a new item.' : ''}
|
|
195
|
+
</div>
|
|
196
|
+
</GroupedCombobox.Content>
|
|
197
|
+
</GroupedCombobox>
|
|
198
|
+
);
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export const NotPopover: Story = {
|
|
203
|
+
render({ autoHighlight, highlightItemOnHover, creatable }) {
|
|
204
|
+
const [value, setValue] = useState<Item | null>(null);
|
|
205
|
+
return (
|
|
206
|
+
<GroupedCombobox
|
|
207
|
+
value={value}
|
|
208
|
+
onValueChange={setValue}
|
|
209
|
+
items={groupedItems}
|
|
210
|
+
autoHighlight={autoHighlight}
|
|
211
|
+
highlightItemOnHover={highlightItemOnHover}
|
|
212
|
+
onCreate={
|
|
213
|
+
creatable
|
|
214
|
+
? (value: string) => alert(`Create item: ${value}`)
|
|
215
|
+
: undefined
|
|
216
|
+
}
|
|
217
|
+
>
|
|
218
|
+
<Box border p surface="white" col>
|
|
219
|
+
<GroupedCombobox.Input disableCaret className="w-full" disableClear>
|
|
220
|
+
<Button size="small" emphasis="primary" className="aspect-1 h-full">
|
|
221
|
+
<Icon name="plus" />
|
|
222
|
+
</Button>
|
|
223
|
+
</GroupedCombobox.Input>
|
|
224
|
+
<GroupedCombobox.List>
|
|
225
|
+
{(group) => (
|
|
226
|
+
<GroupedCombobox.Group key={group.category}>
|
|
227
|
+
<GroupedCombobox.GroupLabel>
|
|
228
|
+
{group.category}
|
|
229
|
+
</GroupedCombobox.GroupLabel>
|
|
230
|
+
<GroupedCombobox.GroupList>
|
|
231
|
+
{group.items.map((item) => (
|
|
232
|
+
<GroupedCombobox.Item key={item.id} value={item}>
|
|
233
|
+
{item.label}
|
|
234
|
+
</GroupedCombobox.Item>
|
|
235
|
+
))}
|
|
236
|
+
</GroupedCombobox.GroupList>
|
|
237
|
+
</GroupedCombobox.Group>
|
|
238
|
+
)}
|
|
239
|
+
</GroupedCombobox.List>
|
|
240
|
+
<GroupedCombobox.Empty>No results found.</GroupedCombobox.Empty>
|
|
241
|
+
</Box>
|
|
242
|
+
</GroupedCombobox>
|
|
243
|
+
);
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
export const MultiSelect: Story = {
|
|
248
|
+
render({ arrow, autoHighlight, highlightItemOnHover, creatable }) {
|
|
249
|
+
const [value, setValue] = useState<Item[]>([]);
|
|
250
|
+
return (
|
|
251
|
+
<ExampleCombobox.Multi
|
|
252
|
+
multiple
|
|
253
|
+
value={value}
|
|
254
|
+
onValueChange={setValue}
|
|
255
|
+
items={items}
|
|
256
|
+
autoHighlight={autoHighlight}
|
|
257
|
+
highlightItemOnHover={highlightItemOnHover}
|
|
258
|
+
showCreatableItem={creatable}
|
|
259
|
+
>
|
|
260
|
+
<ExampleCombobox.Chips className="w-300px">
|
|
261
|
+
<ExampleCombobox.MultiValue>
|
|
262
|
+
{(items) => (
|
|
263
|
+
<>
|
|
264
|
+
<ExampleCombobox.ChipsList>
|
|
265
|
+
{items.map((item) => (
|
|
266
|
+
<ExampleCombobox.Chip key={item.id}>
|
|
267
|
+
{item.label}
|
|
268
|
+
</ExampleCombobox.Chip>
|
|
269
|
+
))}
|
|
270
|
+
</ExampleCombobox.ChipsList>
|
|
271
|
+
<ExampleCombobox.Input />
|
|
272
|
+
</>
|
|
273
|
+
)}
|
|
274
|
+
</ExampleCombobox.MultiValue>
|
|
275
|
+
</ExampleCombobox.Chips>
|
|
276
|
+
<ExampleCombobox.Content arrow={arrow}>
|
|
277
|
+
<ExampleCombobox.List>
|
|
278
|
+
{(item) => (
|
|
279
|
+
<ExampleCombobox.Item key={item.id} value={item}>
|
|
280
|
+
{item.label}
|
|
281
|
+
</ExampleCombobox.Item>
|
|
282
|
+
)}
|
|
283
|
+
</ExampleCombobox.List>
|
|
284
|
+
<ExampleCombobox.Empty>No results found.</ExampleCombobox.Empty>
|
|
285
|
+
</ExampleCombobox.Content>
|
|
286
|
+
</ExampleCombobox.Multi>
|
|
287
|
+
);
|
|
288
|
+
},
|
|
289
|
+
};
|