@sproutsocial/seeds-react-menu 1.17.0 → 1.18.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/.turbo/turbo-build.log +14 -22
- package/CHANGELOG.md +30 -0
- package/dist/esm/index.js +542 -229
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/v3/index.js +793 -1038
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/v3/index.d.mts +64 -38
- package/dist/v3/index.d.ts +64 -38
- package/dist/v3/index.js +813 -1058
- package/dist/v3/index.js.map +1 -1
- package/dist/v3/menu.css +947 -0
- package/package.json +20 -21
- package/src/v3/ActionMenuStyles.tsx +169 -149
- package/src/v3/Common/ComboboxStyles.tsx +396 -511
- package/src/v3/Common/SelectIcons.tsx +17 -8
- package/src/v3/Common/SelectItem.tsx +25 -38
- package/src/v3/Common/SelectStyles.tsx +146 -144
- package/src/v3/Common/cn.ts +38 -0
- package/src/v3/MenuButtonStyles.tsx +55 -34
- package/src/v3/MultiSearchableSelect.tsx +8 -8
- package/src/v3/MultiSelect.tsx +11 -16
- package/src/v3/SingleSelect.tsx +13 -13
- package/src/v3/menu.css +947 -0
- package/tsup.config.ts +0 -1
- package/dist/esm/chunk-ROQATIB7.js +0 -357
- package/dist/esm/chunk-ROQATIB7.js.map +0 -1
- package/dist/esm/v2/index.js +0 -2089
- package/dist/esm/v2/index.js.map +0 -1
- package/dist/v2/index.d.mts +0 -108
- package/dist/v2/index.d.ts +0 -108
- package/dist/v2/index.js +0 -2280
- package/dist/v2/index.js.map +0 -1
- package/src/v2/Autocomplete/Autocomplete.stories.tsx +0 -645
- package/src/v2/Autocomplete/MultiAutocomplete.tsx +0 -487
- package/src/v2/Autocomplete/SingleAutocomplete.tsx +0 -366
- package/src/v2/Autocomplete/index.ts +0 -2
- package/src/v2/Common-V2/ComboboxContent.tsx +0 -457
- package/src/v2/Common-V2/MenuGroup.tsx +0 -60
- package/src/v2/Common-V2/MenuGroupTypes.ts +0 -30
- package/src/v2/Common-V2/MenuHeading.tsx +0 -83
- package/src/v2/Common-V2/MenuItem.tsx +0 -138
- package/src/v2/Common-V2/Popout.tsx +0 -124
- package/src/v2/Common-V2/PopoutTypes.tsx +0 -109
- package/src/v2/Common-V2/SelectToggleButton.tsx +0 -99
- package/src/v2/Common-V2/index.ts +0 -11
- package/src/v2/Common-V2/props.ts +0 -84
- package/src/v2/Common-V2/styles.tsx +0 -41
- package/src/v2/Common-V2/types.ts +0 -16
- package/src/v2/Common-V2/useHighlightedIndex.ts +0 -62
- package/src/v2/Common-V2/utils.ts +0 -238
- package/src/v2/SearchableSelect/AutocompleteContent.tsx +0 -325
- package/src/v2/SearchableSelect/SearchableMultiSelect.tsx +0 -527
- package/src/v2/SearchableSelect/SearchableSelect.tsx +0 -395
- package/src/v2/SearchableSelect/index.ts +0 -12
- package/src/v2/Select/MultiSelect.tsx +0 -417
- package/src/v2/Select/Select.stories.tsx +0 -593
- package/src/v2/Select/SingleSelect.tsx +0 -285
- package/src/v2/Select/index.ts +0 -2
- package/src/v2/index.ts +0 -2
|
@@ -1,593 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
-
import React from "react";
|
|
3
|
-
import type { ReactNode } from "react";
|
|
4
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
5
|
-
import { action } from "@storybook/addon-actions";
|
|
6
|
-
|
|
7
|
-
import { Box } from "@sproutsocial/seeds-react-box";
|
|
8
|
-
import { FormField } from "@sproutsocial/seeds-react-form-field";
|
|
9
|
-
import { Icon } from "@sproutsocial/seeds-react-icon";
|
|
10
|
-
import { Badge } from "@sproutsocial/seeds-react-badge";
|
|
11
|
-
|
|
12
|
-
import { MultiSelect } from "./MultiSelect";
|
|
13
|
-
import { SingleSelect } from "./SingleSelect";
|
|
14
|
-
import Button from "@sproutsocial/seeds-react-button";
|
|
15
|
-
import type { ToggleItem } from "../Common-V2";
|
|
16
|
-
|
|
17
|
-
type CustomSelectArgs = React.ComponentProps<typeof MultiSelect>;
|
|
18
|
-
|
|
19
|
-
const meta: Meta<CustomSelectArgs> = {
|
|
20
|
-
title: "Components/Menus/v2/Select",
|
|
21
|
-
component: MultiSelect,
|
|
22
|
-
parameters: {
|
|
23
|
-
controls: {
|
|
24
|
-
expanded: true,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
decorators: [
|
|
28
|
-
(Story) => (
|
|
29
|
-
<Box display="flex" flexDirection="column" gap="16px" maxWidth={320}>
|
|
30
|
-
<Story />
|
|
31
|
-
</Box>
|
|
32
|
-
),
|
|
33
|
-
],
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export default meta;
|
|
37
|
-
|
|
38
|
-
type Story = StoryObj<CustomSelectArgs>;
|
|
39
|
-
|
|
40
|
-
interface Book {
|
|
41
|
-
id: string;
|
|
42
|
-
author: string;
|
|
43
|
-
title: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const books: Book[] = [
|
|
47
|
-
{ id: "book-1", author: "Harper Lee", title: "To Kill a Mockingbird" },
|
|
48
|
-
{ id: "book-2", author: "Lev Tolstoy", title: "War and Peace" },
|
|
49
|
-
{ id: "book-3", author: "Fyodor Dostoyevsy", title: "The Idiot" },
|
|
50
|
-
{ id: "book-4", author: "Oscar Wilde", title: "A Picture of Dorian Gray" },
|
|
51
|
-
{ id: "book-5", author: "George Orwell", title: "1984" },
|
|
52
|
-
{ id: "book-6", author: "Jane Austen", title: "Pride and Prejudice" },
|
|
53
|
-
{ id: "book-7", author: "Marcus Aurelius", title: "Meditations" },
|
|
54
|
-
{
|
|
55
|
-
id: "book-8",
|
|
56
|
-
author: "Fyodor Dostoevsky",
|
|
57
|
-
title: "The Brothers Karamazov",
|
|
58
|
-
},
|
|
59
|
-
{ id: "book-9", author: "Lev Tolstoy", title: "Anna Karenina" },
|
|
60
|
-
{ id: "book-10", author: "Fyodor Dostoevsky", title: "Crime and Punishment" },
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
// Generate 1000 books for virtualization testing
|
|
64
|
-
const generateBooks = (count: number): Book[] => {
|
|
65
|
-
const authors = [
|
|
66
|
-
"Harper Lee",
|
|
67
|
-
"Lev Tolstoy",
|
|
68
|
-
"Fyodor Dostoevsky",
|
|
69
|
-
"Oscar Wilde",
|
|
70
|
-
"George Orwell",
|
|
71
|
-
"Jane Austen",
|
|
72
|
-
"Marcus Aurelius",
|
|
73
|
-
"Ernest Hemingway",
|
|
74
|
-
"Virginia Woolf",
|
|
75
|
-
"James Joyce",
|
|
76
|
-
"Charles Dickens",
|
|
77
|
-
"Mark Twain",
|
|
78
|
-
"J.R.R. Tolkien",
|
|
79
|
-
"C.S. Lewis",
|
|
80
|
-
"Agatha Christie",
|
|
81
|
-
"Arthur Conan Doyle",
|
|
82
|
-
"J.K. Rowling",
|
|
83
|
-
"Stephen King",
|
|
84
|
-
"Isaac Asimov",
|
|
85
|
-
"Ray Bradbury",
|
|
86
|
-
"Aldous Huxley",
|
|
87
|
-
"Kurt Vonnegut",
|
|
88
|
-
"J.D. Salinger",
|
|
89
|
-
"Maya Angelou",
|
|
90
|
-
"Toni Morrison",
|
|
91
|
-
"Gabriel García Márquez",
|
|
92
|
-
"Milan Kundera",
|
|
93
|
-
"Umberto Eco",
|
|
94
|
-
"Haruki Murakami",
|
|
95
|
-
"Chimamanda Ngozi Adichie",
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
const titleWords = [
|
|
99
|
-
"Adventures",
|
|
100
|
-
"Chronicles",
|
|
101
|
-
"Memories",
|
|
102
|
-
"Journey",
|
|
103
|
-
"Quest",
|
|
104
|
-
"Tales",
|
|
105
|
-
"Stories",
|
|
106
|
-
"Legends",
|
|
107
|
-
"Myths",
|
|
108
|
-
"Dreams",
|
|
109
|
-
"Visions",
|
|
110
|
-
"Revelations",
|
|
111
|
-
"Secrets",
|
|
112
|
-
"Mysteries",
|
|
113
|
-
"Shadows",
|
|
114
|
-
"Light",
|
|
115
|
-
"Darkness",
|
|
116
|
-
"Echoes",
|
|
117
|
-
"Whispers",
|
|
118
|
-
"Voices",
|
|
119
|
-
"Songs",
|
|
120
|
-
"Poems",
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
const books: Book[] = [];
|
|
124
|
-
for (let i = 0; i < count; i++) {
|
|
125
|
-
const author = authors[i % authors.length];
|
|
126
|
-
const titleWord1 =
|
|
127
|
-
titleWords[Math.floor(Math.random() * titleWords.length)];
|
|
128
|
-
const titleWord2 =
|
|
129
|
-
titleWords[Math.floor(Math.random() * titleWords.length)];
|
|
130
|
-
const number = Math.floor(i / authors.length) + 1;
|
|
131
|
-
const title = `${titleWord1} of ${titleWord2} ${number}`;
|
|
132
|
-
|
|
133
|
-
books.push({
|
|
134
|
-
id: `book-${i + 1}`,
|
|
135
|
-
author,
|
|
136
|
-
title,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return books;
|
|
141
|
-
};
|
|
142
|
-
const largeBookSet = generateBooks(1000);
|
|
143
|
-
|
|
144
|
-
const renderItem = (item: Book) => (
|
|
145
|
-
<>
|
|
146
|
-
<span style={{ fontWeight: "bold" }}>{item.title}</span>
|
|
147
|
-
{item.author && (
|
|
148
|
-
<span style={{ fontSize: "12px", color: "#666", marginLeft: "8px" }}>
|
|
149
|
-
by {item.author}
|
|
150
|
-
</span>
|
|
151
|
-
)}
|
|
152
|
-
</>
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
const itemToString = (item: Book | null): string => {
|
|
156
|
-
if (!item) return "";
|
|
157
|
-
return item.title;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
// 1. Single
|
|
161
|
-
export const Single: Story = {
|
|
162
|
-
name: "Single",
|
|
163
|
-
render: () => {
|
|
164
|
-
return (
|
|
165
|
-
<FormField label="Pick a book">
|
|
166
|
-
{({ id }) => (
|
|
167
|
-
<SingleSelect
|
|
168
|
-
id={id}
|
|
169
|
-
data={books}
|
|
170
|
-
itemToString={itemToString}
|
|
171
|
-
renderItem={renderItem}
|
|
172
|
-
onSelectedItemIdChange={(itemId) => console.log(itemId)}
|
|
173
|
-
placeholder="Select a book"
|
|
174
|
-
/>
|
|
175
|
-
)}
|
|
176
|
-
</FormField>
|
|
177
|
-
);
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
// 3. Multi
|
|
182
|
-
export const Multi: Story = {
|
|
183
|
-
name: "Multi",
|
|
184
|
-
render: () => {
|
|
185
|
-
return (
|
|
186
|
-
<div>
|
|
187
|
-
<FormField label="Pick some books">
|
|
188
|
-
{({ id }) => (
|
|
189
|
-
<MultiSelect
|
|
190
|
-
id={id}
|
|
191
|
-
data={books}
|
|
192
|
-
itemToString={itemToString}
|
|
193
|
-
renderItem={renderItem}
|
|
194
|
-
onSelectedItemIdsChange={(newitems) => console.log(newitems)}
|
|
195
|
-
showSelectedItems={true}
|
|
196
|
-
placeholder="Select books"
|
|
197
|
-
/>
|
|
198
|
-
)}
|
|
199
|
-
</FormField>
|
|
200
|
-
<Button onClick={() => console.log("Button clicked")}>Submit</Button>
|
|
201
|
-
</div>
|
|
202
|
-
);
|
|
203
|
-
},
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
// 4. Multi Grouped by Author
|
|
207
|
-
const TestMultiGroupedByAuthor = () => {
|
|
208
|
-
return (
|
|
209
|
-
<FormField label="Pick some books">
|
|
210
|
-
{({ id }) => (
|
|
211
|
-
<SingleSelect
|
|
212
|
-
id={id}
|
|
213
|
-
data={books}
|
|
214
|
-
itemToString={itemToString}
|
|
215
|
-
renderItem={renderItem}
|
|
216
|
-
groupBy={(book) => book.author}
|
|
217
|
-
placeholder="Select books"
|
|
218
|
-
isVirtualized={true}
|
|
219
|
-
menuProps={{
|
|
220
|
-
style: {
|
|
221
|
-
maxHeight: "400px",
|
|
222
|
-
overflow: "auto",
|
|
223
|
-
},
|
|
224
|
-
}}
|
|
225
|
-
/>
|
|
226
|
-
)}
|
|
227
|
-
</FormField>
|
|
228
|
-
);
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
export const MultiGroupedByAuthor: Story = {
|
|
232
|
-
name: "Multi Grouped by Author",
|
|
233
|
-
render: () => {
|
|
234
|
-
return <TestMultiGroupedByAuthor />;
|
|
235
|
-
},
|
|
236
|
-
};
|
|
237
|
-
|
|
238
|
-
// 5. Multi Grouped by First Letter
|
|
239
|
-
const TestMultiGroupedByFirstLetter = () => {
|
|
240
|
-
return (
|
|
241
|
-
<FormField label="Pick some books">
|
|
242
|
-
{({ id }) => (
|
|
243
|
-
<MultiSelect
|
|
244
|
-
id={id}
|
|
245
|
-
data={books}
|
|
246
|
-
itemToString={itemToString}
|
|
247
|
-
renderItem={renderItem}
|
|
248
|
-
showSelectedItems={true}
|
|
249
|
-
groupBy={(book) => {
|
|
250
|
-
return book.title.charAt(0).toUpperCase();
|
|
251
|
-
}}
|
|
252
|
-
placeholder="Select books"
|
|
253
|
-
/>
|
|
254
|
-
)}
|
|
255
|
-
</FormField>
|
|
256
|
-
);
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
export const MultiGroupedByFirstLetter: Story = {
|
|
260
|
-
name: "Multi Grouped by First Letter",
|
|
261
|
-
render: () => {
|
|
262
|
-
return <TestMultiGroupedByFirstLetter />;
|
|
263
|
-
},
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
// 6. Multi Grouped by Author with Custom Heading
|
|
267
|
-
const TestMultiGroupedByAuthorWithCustomHeading = () => {
|
|
268
|
-
return (
|
|
269
|
-
<FormField label="Pick some books">
|
|
270
|
-
{({ id }) => (
|
|
271
|
-
<MultiSelect
|
|
272
|
-
id={id}
|
|
273
|
-
data={books}
|
|
274
|
-
itemToString={itemToString}
|
|
275
|
-
renderItem={renderItem}
|
|
276
|
-
groupBy={(book) => book.author}
|
|
277
|
-
renderGroupHeading={(label) => `📚 ${label.toUpperCase()}`}
|
|
278
|
-
showSelectedItems={true}
|
|
279
|
-
placeholder="Select books"
|
|
280
|
-
/>
|
|
281
|
-
)}
|
|
282
|
-
</FormField>
|
|
283
|
-
);
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
export const MultiGroupedByAuthorWithCustomHeading: Story = {
|
|
287
|
-
name: "Multi Grouped by Author with Custom Heading",
|
|
288
|
-
render: () => {
|
|
289
|
-
return <TestMultiGroupedByAuthorWithCustomHeading />;
|
|
290
|
-
},
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
// 7. Multi with Select All
|
|
294
|
-
const TestMultiWithSelectAll = () => {
|
|
295
|
-
const selectAllItem: ToggleItem = {
|
|
296
|
-
id: "select-all",
|
|
297
|
-
label: "Select All",
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
return (
|
|
301
|
-
<FormField label="Pick some books">
|
|
302
|
-
{({ id }) => (
|
|
303
|
-
<MultiSelect
|
|
304
|
-
id={id}
|
|
305
|
-
data={books}
|
|
306
|
-
itemToString={itemToString}
|
|
307
|
-
renderItem={renderItem}
|
|
308
|
-
selectAllItem={selectAllItem}
|
|
309
|
-
onSelectedItemIdsChange={(items) => console.log(items)}
|
|
310
|
-
showSelectedItems={true}
|
|
311
|
-
placeholder="Select books"
|
|
312
|
-
/>
|
|
313
|
-
)}
|
|
314
|
-
</FormField>
|
|
315
|
-
);
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
export const MultiWithSelectAll: Story = {
|
|
319
|
-
name: "Multi with Select All",
|
|
320
|
-
render: () => {
|
|
321
|
-
return <TestMultiWithSelectAll />;
|
|
322
|
-
},
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
// 8. Virtualized Multi (with 1000 items)
|
|
326
|
-
const TestVirtualizedMulti = () => {
|
|
327
|
-
return (
|
|
328
|
-
<FormField label="Pick some books">
|
|
329
|
-
{({ id }) => (
|
|
330
|
-
<MultiSelect
|
|
331
|
-
id={id}
|
|
332
|
-
data={largeBookSet}
|
|
333
|
-
itemToString={itemToString}
|
|
334
|
-
renderItem={renderItem}
|
|
335
|
-
isVirtualized={true}
|
|
336
|
-
placeholder="Select books"
|
|
337
|
-
menuProps={{
|
|
338
|
-
style: {
|
|
339
|
-
maxHeight: "400px",
|
|
340
|
-
overflow: "auto",
|
|
341
|
-
},
|
|
342
|
-
}}
|
|
343
|
-
/>
|
|
344
|
-
)}
|
|
345
|
-
</FormField>
|
|
346
|
-
);
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
export const VirtualizedMulti: Story = {
|
|
350
|
-
name: "Virtualized Multi (with 1000 items)",
|
|
351
|
-
render: () => {
|
|
352
|
-
return <TestVirtualizedMulti />;
|
|
353
|
-
},
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
// 9. Virtualized Multi (with 1000 items), With Select All, Grouped by Author, with Selectable Headings
|
|
357
|
-
const TestVirtualizedMultiWithSelectAllGrouped = () => {
|
|
358
|
-
const selectAllItem: ToggleItem = {
|
|
359
|
-
id: "select-all",
|
|
360
|
-
label: "Select All",
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
return (
|
|
364
|
-
<FormField label="Pick some books">
|
|
365
|
-
{({ id }) => (
|
|
366
|
-
<MultiSelect
|
|
367
|
-
id={id}
|
|
368
|
-
data={largeBookSet}
|
|
369
|
-
itemToString={itemToString}
|
|
370
|
-
renderItem={renderItem}
|
|
371
|
-
groupBy={(book) => book.author}
|
|
372
|
-
selectAllItem={selectAllItem}
|
|
373
|
-
selectHeadings={true}
|
|
374
|
-
isVirtualized={true}
|
|
375
|
-
renderGroupHeading={(label) => `📚 ${label.toUpperCase()}`}
|
|
376
|
-
onSelectedItemIdsChange={(items) => console.log(items)}
|
|
377
|
-
showSelectedItems={true}
|
|
378
|
-
placeholder="Select books"
|
|
379
|
-
menuProps={{
|
|
380
|
-
style: {
|
|
381
|
-
maxHeight: "400px",
|
|
382
|
-
overflow: "auto",
|
|
383
|
-
},
|
|
384
|
-
}}
|
|
385
|
-
/>
|
|
386
|
-
)}
|
|
387
|
-
</FormField>
|
|
388
|
-
);
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
export const VirtualizedMultiWithSelectAllGrouped: Story = {
|
|
392
|
-
name: "Virtualized Multi (with 1000 items), With Select All, Grouped by Author, with Selectable Headings",
|
|
393
|
-
render: () => {
|
|
394
|
-
return <TestVirtualizedMultiWithSelectAllGrouped />;
|
|
395
|
-
},
|
|
396
|
-
};
|
|
397
|
-
|
|
398
|
-
// 10. Single with Selection rendering
|
|
399
|
-
export const SingleWithSelectionRendering: Story = {
|
|
400
|
-
name: "Single with Selection rendering",
|
|
401
|
-
render: () => {
|
|
402
|
-
return (
|
|
403
|
-
<FormField label="Pick a book">
|
|
404
|
-
{({ id }) => (
|
|
405
|
-
<SingleSelect
|
|
406
|
-
id={id}
|
|
407
|
-
data={books}
|
|
408
|
-
itemToString={itemToString}
|
|
409
|
-
itemToSelection={renderItem}
|
|
410
|
-
renderItem={renderItem}
|
|
411
|
-
onSelectedItemIdChange={(itemId) => console.log(itemId)}
|
|
412
|
-
placeholder="Select a book"
|
|
413
|
-
/>
|
|
414
|
-
)}
|
|
415
|
-
</FormField>
|
|
416
|
-
);
|
|
417
|
-
},
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
const customSelectionRenderer = (selectedItems: Book[]): ReactNode => {
|
|
421
|
-
if (selectedItems.length === 0) {
|
|
422
|
-
return "No books selected";
|
|
423
|
-
}
|
|
424
|
-
return selectedItems.map((item) => <Badge key={item.id}>{item.title}</Badge>);
|
|
425
|
-
};
|
|
426
|
-
// 11. Multi with Selection rendering
|
|
427
|
-
export const MultiWithSelectionRendering: Story = {
|
|
428
|
-
name: "Multi with Selection rendering",
|
|
429
|
-
render: () => {
|
|
430
|
-
return (
|
|
431
|
-
<FormField label="Pick some books">
|
|
432
|
-
{({ id }) => (
|
|
433
|
-
<MultiSelect
|
|
434
|
-
id={id}
|
|
435
|
-
data={books}
|
|
436
|
-
itemToString={itemToString}
|
|
437
|
-
renderSelections={customSelectionRenderer}
|
|
438
|
-
renderItem={renderItem}
|
|
439
|
-
onSelectedItemIdsChange={(newitems) => console.log(newitems)}
|
|
440
|
-
showSelectedItems={true}
|
|
441
|
-
shouldOverflow
|
|
442
|
-
placeholder="Select books"
|
|
443
|
-
/>
|
|
444
|
-
)}
|
|
445
|
-
</FormField>
|
|
446
|
-
);
|
|
447
|
-
},
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
// 12. FullyControlled Single
|
|
451
|
-
const TestFullyControlledSingle = () => {
|
|
452
|
-
const [selectedItemId, setSelectedItemId] = React.useState<string | null>(
|
|
453
|
-
books[0].id
|
|
454
|
-
);
|
|
455
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
456
|
-
|
|
457
|
-
const selectedItem = books.find((book) => book.id === selectedItemId) ?? null;
|
|
458
|
-
|
|
459
|
-
return (
|
|
460
|
-
<>
|
|
461
|
-
<FormField label="Pick a book">
|
|
462
|
-
{({ id }) => (
|
|
463
|
-
<SingleSelect
|
|
464
|
-
id={id}
|
|
465
|
-
data={books}
|
|
466
|
-
itemToString={itemToString}
|
|
467
|
-
selectedItemId={selectedItemId}
|
|
468
|
-
onSelectedItemIdChange={(newItemId) => {
|
|
469
|
-
console.log("Selected item changed:", newItemId);
|
|
470
|
-
setSelectedItemId(newItemId);
|
|
471
|
-
}}
|
|
472
|
-
isOpen={isOpen}
|
|
473
|
-
onIsOpenChange={(newIsOpen) => {
|
|
474
|
-
console.log("isOpen changed:", newIsOpen);
|
|
475
|
-
setIsOpen(newIsOpen);
|
|
476
|
-
}}
|
|
477
|
-
renderItem={renderItem}
|
|
478
|
-
placeholder="Select a book"
|
|
479
|
-
/>
|
|
480
|
-
)}
|
|
481
|
-
</FormField>
|
|
482
|
-
<div
|
|
483
|
-
style={{
|
|
484
|
-
marginTop: "16px",
|
|
485
|
-
display: "flex",
|
|
486
|
-
flexDirection: "column",
|
|
487
|
-
gap: "8px",
|
|
488
|
-
}}
|
|
489
|
-
>
|
|
490
|
-
<div>
|
|
491
|
-
<Button onClick={() => setIsOpen(!isOpen)}>Toggle Menu</Button>
|
|
492
|
-
<Button
|
|
493
|
-
onClick={() => {
|
|
494
|
-
const randomBook =
|
|
495
|
-
books[Math.floor(Math.random() * books.length)];
|
|
496
|
-
setSelectedItemId(randomBook.id);
|
|
497
|
-
}}
|
|
498
|
-
style={{ marginLeft: "8px" }}
|
|
499
|
-
>
|
|
500
|
-
Select Random Book
|
|
501
|
-
</Button>
|
|
502
|
-
</div>
|
|
503
|
-
<div style={{ fontSize: "12px", color: "#666" }}>
|
|
504
|
-
Menu: {isOpen ? "OPEN" : "CLOSED"} | Selected:{" "}
|
|
505
|
-
{selectedItem ? selectedItem.title : "None"}
|
|
506
|
-
</div>
|
|
507
|
-
</div>
|
|
508
|
-
</>
|
|
509
|
-
);
|
|
510
|
-
};
|
|
511
|
-
|
|
512
|
-
export const FullyControlledSingle: Story = {
|
|
513
|
-
name: "FullyControlled Single",
|
|
514
|
-
render: () => {
|
|
515
|
-
return <TestFullyControlledSingle />;
|
|
516
|
-
},
|
|
517
|
-
};
|
|
518
|
-
|
|
519
|
-
// 13. FullyControlled Multi
|
|
520
|
-
const TestFullyControlledMulti = () => {
|
|
521
|
-
const [selectedItemIds, setSelectedItemIds] = React.useState<string[]>([
|
|
522
|
-
books[0].id,
|
|
523
|
-
]);
|
|
524
|
-
const [isOpen, setIsOpen] = React.useState(false);
|
|
525
|
-
|
|
526
|
-
const selectedItems = books.filter((book) =>
|
|
527
|
-
selectedItemIds.includes(book.id)
|
|
528
|
-
);
|
|
529
|
-
|
|
530
|
-
return (
|
|
531
|
-
<>
|
|
532
|
-
<FormField label="Pick some books">
|
|
533
|
-
{({ id }) => (
|
|
534
|
-
<MultiSelect
|
|
535
|
-
id={id}
|
|
536
|
-
data={books}
|
|
537
|
-
itemToString={itemToString}
|
|
538
|
-
selectedItemIds={selectedItemIds}
|
|
539
|
-
onSelectedItemIdsChange={(newItemIds) => {
|
|
540
|
-
console.log("Selected items changed:", newItemIds);
|
|
541
|
-
setSelectedItemIds(newItemIds);
|
|
542
|
-
}}
|
|
543
|
-
isOpen={isOpen}
|
|
544
|
-
onIsOpenChange={(newIsOpen) => {
|
|
545
|
-
console.log("isOpen changed:", newIsOpen);
|
|
546
|
-
setIsOpen(newIsOpen);
|
|
547
|
-
}}
|
|
548
|
-
renderItem={renderItem}
|
|
549
|
-
placeholder="Select books"
|
|
550
|
-
/>
|
|
551
|
-
)}
|
|
552
|
-
</FormField>
|
|
553
|
-
<div
|
|
554
|
-
style={{
|
|
555
|
-
marginTop: "16px",
|
|
556
|
-
display: "flex",
|
|
557
|
-
flexDirection: "column",
|
|
558
|
-
gap: "8px",
|
|
559
|
-
}}
|
|
560
|
-
>
|
|
561
|
-
<div>
|
|
562
|
-
<Button onClick={() => setIsOpen(!isOpen)}>Toggle Menu</Button>
|
|
563
|
-
<Button
|
|
564
|
-
onClick={() => {
|
|
565
|
-
const randomBook =
|
|
566
|
-
books[Math.floor(Math.random() * books.length)];
|
|
567
|
-
setSelectedItemIds((prev) => {
|
|
568
|
-
if (!prev.includes(randomBook.id)) {
|
|
569
|
-
return [...prev, randomBook.id];
|
|
570
|
-
}
|
|
571
|
-
return prev;
|
|
572
|
-
});
|
|
573
|
-
}}
|
|
574
|
-
style={{ marginLeft: "8px" }}
|
|
575
|
-
>
|
|
576
|
-
Add Random Book
|
|
577
|
-
</Button>
|
|
578
|
-
</div>
|
|
579
|
-
<div style={{ fontSize: "12px", color: "#666" }}>
|
|
580
|
-
Menu: {isOpen ? "OPEN" : "CLOSED"} | Selected:{" "}
|
|
581
|
-
{selectedItems.map((item) => item.title).join(", ") || "None"}
|
|
582
|
-
</div>
|
|
583
|
-
</div>
|
|
584
|
-
</>
|
|
585
|
-
);
|
|
586
|
-
};
|
|
587
|
-
|
|
588
|
-
export const FullyControlledMulti: Story = {
|
|
589
|
-
name: "FullyControlled Multi",
|
|
590
|
-
render: () => {
|
|
591
|
-
return <TestFullyControlledMulti />;
|
|
592
|
-
},
|
|
593
|
-
};
|