@sproutsocial/seeds-react-menu 1.11.1 → 1.11.3
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 +10 -10
- package/CHANGELOG.md +12 -0
- package/dist/esm/v3/index.js +1413 -3
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/v3/index.d.mts +16 -2
- package/dist/v3/index.d.ts +16 -2
- package/dist/v3/index.js +1418 -2
- package/dist/v3/index.js.map +1 -1
- package/package.json +1 -1
- package/src/v3/Common/ComboboxItem.tsx +4 -0
- package/src/v3/Common/ComboboxStyles.tsx +28 -0
- package/src/v3/Common/SelectItem.tsx +8 -1
- package/src/v3/Common/SelectStyles.tsx +5 -0
- package/src/v3/Common/types.ts +1 -0
- package/src/v3/ModalStories.stories.tsx +6 -6
- package/src/v3/MultiCombobox.stories.tsx +26 -2
- package/src/v3/MultiCombobox.tsx +6 -1
- package/src/v3/MultiSearchableSelect.stories.tsx +27 -2
- package/src/v3/MultiSearchableSelect.tsx +6 -1
- package/src/v3/MultiSelect.stories.tsx +63 -40
- package/src/v3/MultiSelect.tsx +5 -222
- package/src/v3/SingleCombobox.stories.tsx +26 -2
- package/src/v3/SingleCombobox.tsx +5 -1
- package/src/v3/SingleSearchableSelect.stories.tsx +47 -2
- package/src/v3/SingleSearchableSelect.tsx +31 -13
- package/src/v3/SingleSelect.stories.tsx +44 -2
- package/src/v3/SingleSelect.tsx +5 -2
- package/src/v3/storyData.tsx +5 -0
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ interface ComboboxItemProps<T> {
|
|
|
11
11
|
value: T;
|
|
12
12
|
itemId: string;
|
|
13
13
|
label: string;
|
|
14
|
+
disabled?: boolean;
|
|
14
15
|
inputType?: "icon" | "radio" | "checkbox" | "none";
|
|
15
16
|
renderItem?: () => React.ReactNode;
|
|
16
17
|
index?: number;
|
|
@@ -23,6 +24,7 @@ function ComboboxItemInner<T>(
|
|
|
23
24
|
value,
|
|
24
25
|
itemId,
|
|
25
26
|
label,
|
|
27
|
+
disabled,
|
|
26
28
|
inputType = "icon",
|
|
27
29
|
renderItem,
|
|
28
30
|
index,
|
|
@@ -38,6 +40,8 @@ function ComboboxItemInner<T>(
|
|
|
38
40
|
data-index={dataIndex}
|
|
39
41
|
style={style}
|
|
40
42
|
ref={ref}
|
|
43
|
+
disabled={disabled}
|
|
44
|
+
data-qa-menu-item={label}
|
|
41
45
|
>
|
|
42
46
|
{inputType === "radio" ? (
|
|
43
47
|
<ComboboxItemIndicator
|
|
@@ -25,6 +25,11 @@ export const ComboboxInputGroup = styled(Combobox.InputGroup)`
|
|
|
25
25
|
&:focus-within {
|
|
26
26
|
${focusRing}
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
&[data-disabled] {
|
|
30
|
+
opacity: 0.4;
|
|
31
|
+
cursor: not-allowed;
|
|
32
|
+
}
|
|
28
33
|
`;
|
|
29
34
|
|
|
30
35
|
export const ComboboxInput = styled(Combobox.Input)`
|
|
@@ -41,6 +46,10 @@ export const ComboboxInput = styled(Combobox.Input)`
|
|
|
41
46
|
&::placeholder {
|
|
42
47
|
color: ${({ theme }) => theme.colors.text.subtext};
|
|
43
48
|
}
|
|
49
|
+
|
|
50
|
+
&:disabled {
|
|
51
|
+
cursor: not-allowed;
|
|
52
|
+
}
|
|
44
53
|
`;
|
|
45
54
|
|
|
46
55
|
export const ComboboxTokenInput = styled(Combobox.Input)`
|
|
@@ -58,6 +67,10 @@ export const ComboboxTokenInput = styled(Combobox.Input)`
|
|
|
58
67
|
&::placeholder {
|
|
59
68
|
color: ${({ theme }) => theme.colors.text.subtext};
|
|
60
69
|
}
|
|
70
|
+
|
|
71
|
+
&:disabled {
|
|
72
|
+
cursor: not-allowed;
|
|
73
|
+
}
|
|
61
74
|
`;
|
|
62
75
|
|
|
63
76
|
export const ComboboxActionButtons = styled.div`
|
|
@@ -323,6 +336,11 @@ export const ComboboxTokenInputGroup = styled(Combobox.InputGroup)`
|
|
|
323
336
|
&:focus-within {
|
|
324
337
|
${focusRing}
|
|
325
338
|
}
|
|
339
|
+
|
|
340
|
+
&[data-disabled] {
|
|
341
|
+
opacity: 0.4;
|
|
342
|
+
cursor: not-allowed;
|
|
343
|
+
}
|
|
326
344
|
`;
|
|
327
345
|
|
|
328
346
|
export const Token = styled.span`
|
|
@@ -388,6 +406,11 @@ export const SearchableSelectTrigger = styled(Combobox.Trigger)`
|
|
|
388
406
|
&[data-popup-open] [data-chevron] {
|
|
389
407
|
transform: rotate(-180deg);
|
|
390
408
|
}
|
|
409
|
+
|
|
410
|
+
&[data-disabled] {
|
|
411
|
+
opacity: 0.4;
|
|
412
|
+
cursor: not-allowed;
|
|
413
|
+
}
|
|
391
414
|
`;
|
|
392
415
|
|
|
393
416
|
export const SearchableSelectTriggerIcon = styled(Combobox.Icon)`
|
|
@@ -472,4 +495,9 @@ export const SearchableSelectTokenTrigger = styled(Combobox.Trigger)`
|
|
|
472
495
|
&[data-popup-open] [data-chevron] {
|
|
473
496
|
transform: rotate(-180deg);
|
|
474
497
|
}
|
|
498
|
+
|
|
499
|
+
&[data-disabled] {
|
|
500
|
+
opacity: 0.4;
|
|
501
|
+
cursor: not-allowed;
|
|
502
|
+
}
|
|
475
503
|
`;
|
|
@@ -57,6 +57,7 @@ function CheckIcon() {
|
|
|
57
57
|
interface SelectItemProps {
|
|
58
58
|
value: string | null;
|
|
59
59
|
label: string;
|
|
60
|
+
disabled?: boolean;
|
|
60
61
|
inputType?: "icon" | "radio" | "checkbox" | "none";
|
|
61
62
|
renderItem?: () => React.ReactNode;
|
|
62
63
|
hidden?: boolean;
|
|
@@ -65,12 +66,18 @@ interface SelectItemProps {
|
|
|
65
66
|
export default function SelectItem({
|
|
66
67
|
value,
|
|
67
68
|
label,
|
|
69
|
+
disabled,
|
|
68
70
|
inputType = "icon",
|
|
69
71
|
renderItem,
|
|
70
72
|
hidden,
|
|
71
73
|
}: SelectItemProps) {
|
|
72
74
|
return (
|
|
73
|
-
<StyledItem
|
|
75
|
+
<StyledItem
|
|
76
|
+
value={value}
|
|
77
|
+
disabled={disabled}
|
|
78
|
+
style={hidden ? { display: "none" } : undefined}
|
|
79
|
+
data-qa-menu-item={label}
|
|
80
|
+
>
|
|
74
81
|
{inputType === "radio" ? (
|
|
75
82
|
<StyledItemIndicator
|
|
76
83
|
keepMounted
|
|
@@ -44,6 +44,11 @@ export const SelectTrigger = styled(Select.Trigger)`
|
|
|
44
44
|
&[data-popup-open] [data-chevron] {
|
|
45
45
|
transform: rotate(-180deg);
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
&[data-disabled] {
|
|
49
|
+
opacity: 0.4;
|
|
50
|
+
cursor: not-allowed;
|
|
51
|
+
}
|
|
47
52
|
`;
|
|
48
53
|
|
|
49
54
|
export const SelectValue = styled(Select.Value)`
|
package/src/v3/Common/types.ts
CHANGED
|
@@ -10,12 +10,12 @@ import {
|
|
|
10
10
|
ModalBody,
|
|
11
11
|
ModalFooter,
|
|
12
12
|
} from "@sproutsocial/seeds-react-modal";
|
|
13
|
-
import SingleSelect from "./SingleSelect";
|
|
14
|
-
import MultiSelect from "./MultiSelect";
|
|
15
|
-
import SingleCombobox from "./SingleCombobox";
|
|
16
|
-
import MultiCombobox from "./MultiCombobox";
|
|
17
|
-
import SingleSearchableSelect from "./SingleSearchableSelect";
|
|
18
|
-
import MultiSearchableSelect from "./MultiSearchableSelect";
|
|
13
|
+
import { SingleSelect } from "./SingleSelect";
|
|
14
|
+
import { MultiSelect } from "./MultiSelect";
|
|
15
|
+
import { SingleCombobox } from "./SingleCombobox";
|
|
16
|
+
import { MultiCombobox } from "./MultiCombobox";
|
|
17
|
+
import { SingleSearchableSelect } from "./SingleSearchableSelect";
|
|
18
|
+
import { MultiSearchableSelect } from "./MultiSearchableSelect";
|
|
19
19
|
import { books, itemToString } from "./storyData";
|
|
20
20
|
|
|
21
21
|
// ─── Shared content ───────────────────────────────────────────────────────────
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
3
|
import { FormField } from "@sproutsocial/seeds-react-form-field";
|
|
4
|
-
import MultiCombobox from "./MultiCombobox";
|
|
5
|
-
import {
|
|
4
|
+
import { MultiCombobox } from "./MultiCombobox";
|
|
5
|
+
import {
|
|
6
|
+
books,
|
|
7
|
+
booksWithDisabled,
|
|
8
|
+
largeBookSet,
|
|
9
|
+
itemToString,
|
|
10
|
+
renderItem,
|
|
11
|
+
} from "./storyData";
|
|
6
12
|
|
|
7
13
|
const meta: Meta<typeof MultiCombobox> = {
|
|
8
14
|
title: "Really Under Development/V3/Multi Combobox",
|
|
@@ -135,6 +141,24 @@ export const Controlled: Story = {
|
|
|
135
141
|
},
|
|
136
142
|
};
|
|
137
143
|
|
|
144
|
+
export const DisabledItems: Story = {
|
|
145
|
+
name: "Disabled items",
|
|
146
|
+
render: () => (
|
|
147
|
+
<div style={{ width: "300px" }}>
|
|
148
|
+
<FormField label="Pick books">
|
|
149
|
+
{({ id }) => (
|
|
150
|
+
<MultiCombobox
|
|
151
|
+
id={id}
|
|
152
|
+
data={booksWithDisabled}
|
|
153
|
+
itemToString={itemToString}
|
|
154
|
+
placeholder="Search books..."
|
|
155
|
+
/>
|
|
156
|
+
)}
|
|
157
|
+
</FormField>
|
|
158
|
+
</div>
|
|
159
|
+
),
|
|
160
|
+
};
|
|
161
|
+
|
|
138
162
|
export const SelectableHeadings: Story = {
|
|
139
163
|
name: "Selectable headings",
|
|
140
164
|
render: () => (
|
package/src/v3/MultiCombobox.tsx
CHANGED
|
@@ -64,6 +64,7 @@ interface MultiComboboxBaseProps {
|
|
|
64
64
|
emptyText?: string;
|
|
65
65
|
isLoading?: boolean;
|
|
66
66
|
loadingText?: string;
|
|
67
|
+
disabled?: boolean;
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
interface MultiComboboxDataProps<T extends DataWithId>
|
|
@@ -115,7 +116,7 @@ export type MultiComboboxProps<T extends DataWithId> =
|
|
|
115
116
|
|
|
116
117
|
// ─── Component ────────────────────────────────────────────────────────────────
|
|
117
118
|
|
|
118
|
-
export
|
|
119
|
+
export function MultiCombobox<T extends DataWithId>(
|
|
119
120
|
props: MultiComboboxProps<T>
|
|
120
121
|
) {
|
|
121
122
|
const {
|
|
@@ -342,6 +343,7 @@ export default function MultiCombobox<T extends DataWithId>(
|
|
|
342
343
|
value={item}
|
|
343
344
|
itemId={String(item.id)}
|
|
344
345
|
label={itemToString(item)}
|
|
346
|
+
disabled={item.disabled}
|
|
345
347
|
inputType={inputType}
|
|
346
348
|
renderItem={
|
|
347
349
|
renderItem ? () => renderItem(item) : () => itemToString(item)
|
|
@@ -374,6 +376,7 @@ export default function MultiCombobox<T extends DataWithId>(
|
|
|
374
376
|
id={id}
|
|
375
377
|
virtualized={isVirtualized}
|
|
376
378
|
open={open}
|
|
379
|
+
disabled={props.disabled}
|
|
377
380
|
onOpenChange={setOpen}
|
|
378
381
|
onItemHighlighted={
|
|
379
382
|
isVirtualized
|
|
@@ -523,6 +526,7 @@ export default function MultiCombobox<T extends DataWithId>(
|
|
|
523
526
|
value={item}
|
|
524
527
|
itemId={String(item.id)}
|
|
525
528
|
label={itemToString(item)}
|
|
529
|
+
disabled={item.disabled}
|
|
526
530
|
inputType={inputType}
|
|
527
531
|
renderItem={
|
|
528
532
|
renderItem
|
|
@@ -543,6 +547,7 @@ export default function MultiCombobox<T extends DataWithId>(
|
|
|
543
547
|
value={item}
|
|
544
548
|
itemId={String(item.id)}
|
|
545
549
|
label={itemToString(item)}
|
|
550
|
+
disabled={item.disabled}
|
|
546
551
|
inputType={inputType}
|
|
547
552
|
renderItem={
|
|
548
553
|
renderItem
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
3
|
import { FormField } from "@sproutsocial/seeds-react-form-field";
|
|
4
|
-
import MultiSearchableSelect from "./MultiSearchableSelect";
|
|
5
|
-
import {
|
|
4
|
+
import { MultiSearchableSelect } from "./MultiSearchableSelect";
|
|
5
|
+
import {
|
|
6
|
+
books,
|
|
7
|
+
booksWithDisabled,
|
|
8
|
+
largeBookSet,
|
|
9
|
+
itemToString,
|
|
10
|
+
renderItem,
|
|
11
|
+
} from "./storyData";
|
|
6
12
|
|
|
7
13
|
const meta: Meta<typeof MultiSearchableSelect> = {
|
|
8
14
|
title: "Really Under Development/V3/Multi Searchable Select",
|
|
@@ -193,6 +199,25 @@ export const CustomRenderSelections: Story = {
|
|
|
193
199
|
),
|
|
194
200
|
};
|
|
195
201
|
|
|
202
|
+
export const DisabledItems: Story = {
|
|
203
|
+
name: "Disabled items",
|
|
204
|
+
render: () => (
|
|
205
|
+
<div style={{ width: "300px" }}>
|
|
206
|
+
<FormField label="Pick books">
|
|
207
|
+
{({ id }) => (
|
|
208
|
+
<MultiSearchableSelect
|
|
209
|
+
id={id}
|
|
210
|
+
data={booksWithDisabled}
|
|
211
|
+
itemToString={itemToString}
|
|
212
|
+
placeholder="Select books"
|
|
213
|
+
searchPlaceholder="Search books..."
|
|
214
|
+
/>
|
|
215
|
+
)}
|
|
216
|
+
</FormField>
|
|
217
|
+
</div>
|
|
218
|
+
),
|
|
219
|
+
};
|
|
220
|
+
|
|
196
221
|
export const SelectableHeadings: Story = {
|
|
197
222
|
name: "Selectable headings",
|
|
198
223
|
render: () => (
|
|
@@ -71,6 +71,7 @@ interface MultiSearchableSelectBaseProps {
|
|
|
71
71
|
emptyText?: string;
|
|
72
72
|
isLoading?: boolean;
|
|
73
73
|
loadingText?: string;
|
|
74
|
+
disabled?: boolean;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
interface MultiSearchableSelectDataProps<T extends DataWithId>
|
|
@@ -121,7 +122,7 @@ export type MultiSearchableSelectProps<T extends DataWithId> =
|
|
|
121
122
|
|
|
122
123
|
// ─── Component ────────────────────────────────────────────────────────────────
|
|
123
124
|
|
|
124
|
-
export
|
|
125
|
+
export function MultiSearchableSelect<T extends DataWithId>(
|
|
125
126
|
props: MultiSearchableSelectProps<T>
|
|
126
127
|
) {
|
|
127
128
|
const {
|
|
@@ -341,6 +342,7 @@ export default function MultiSearchableSelect<T extends DataWithId>(
|
|
|
341
342
|
value={item}
|
|
342
343
|
itemId={String(item.id)}
|
|
343
344
|
label={itemToString(item)}
|
|
345
|
+
disabled={item.disabled}
|
|
344
346
|
inputType={inputType}
|
|
345
347
|
renderItem={
|
|
346
348
|
renderItem ? () => renderItem(item) : () => itemToString(item)
|
|
@@ -364,6 +366,7 @@ export default function MultiSearchableSelect<T extends DataWithId>(
|
|
|
364
366
|
id={id}
|
|
365
367
|
virtualized={isVirtualized}
|
|
366
368
|
open={open}
|
|
369
|
+
disabled={props.disabled}
|
|
367
370
|
onOpenChange={setOpen}
|
|
368
371
|
onItemHighlighted={
|
|
369
372
|
isVirtualized
|
|
@@ -506,6 +509,7 @@ export default function MultiSearchableSelect<T extends DataWithId>(
|
|
|
506
509
|
value={item}
|
|
507
510
|
itemId={String(item.id)}
|
|
508
511
|
label={itemToString(item)}
|
|
512
|
+
disabled={item.disabled}
|
|
509
513
|
inputType={inputType}
|
|
510
514
|
renderItem={
|
|
511
515
|
renderItem
|
|
@@ -526,6 +530,7 @@ export default function MultiSearchableSelect<T extends DataWithId>(
|
|
|
526
530
|
value={item}
|
|
527
531
|
itemId={String(item.id)}
|
|
528
532
|
label={itemToString(item)}
|
|
533
|
+
disabled={item.disabled}
|
|
529
534
|
inputType={inputType}
|
|
530
535
|
renderItem={
|
|
531
536
|
renderItem
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
3
|
import { FormField } from "@sproutsocial/seeds-react-form-field";
|
|
4
|
-
import MultiSelect from "./MultiSelect";
|
|
4
|
+
import { MultiSelect } from "./MultiSelect";
|
|
5
5
|
import SelectItem from "./Common/SelectItem";
|
|
6
6
|
import SelectGroup from "./Common/SelectGroup";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
books,
|
|
9
|
+
booksWithDisabled,
|
|
10
|
+
itemToString,
|
|
11
|
+
renderItem,
|
|
12
|
+
} from "./storyData";
|
|
8
13
|
|
|
9
14
|
const meta: Meta<typeof MultiSelect> = {
|
|
10
15
|
title: "Really Under Development/V3/Multi Select",
|
|
@@ -169,53 +174,71 @@ export const CustomSelection: Story = {
|
|
|
169
174
|
),
|
|
170
175
|
};
|
|
171
176
|
|
|
172
|
-
export const CustomToken: Story = {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
};
|
|
177
|
+
// export const CustomToken: Story = {
|
|
178
|
+
// name: "Custom renderToken",
|
|
179
|
+
// render: () => (
|
|
180
|
+
// <div style={{ width: "300px" }}>
|
|
181
|
+
// <FormField label="Pick books">
|
|
182
|
+
// {({ id }) => (
|
|
183
|
+
// <MultiSelect
|
|
184
|
+
// id={id}
|
|
185
|
+
// data={books}
|
|
186
|
+
// itemToString={itemToString}
|
|
187
|
+
// renderItem={renderItem}
|
|
188
|
+
// placeholder="Select books..."
|
|
189
|
+
// renderToken={(item) => (
|
|
190
|
+
// <span>
|
|
191
|
+
// {item.title}{" "}
|
|
192
|
+
// <span style={{ fontSize: "11px", opacity: 0.7 }}>
|
|
193
|
+
// ({item.author})
|
|
194
|
+
// </span>
|
|
195
|
+
// </span>
|
|
196
|
+
// )}
|
|
197
|
+
// />
|
|
198
|
+
// )}
|
|
199
|
+
// </FormField>
|
|
200
|
+
// </div>
|
|
201
|
+
// ),
|
|
202
|
+
// };
|
|
203
|
+
|
|
204
|
+
// export const MaxTokens: Story = {
|
|
205
|
+
// name: "Max tokens",
|
|
206
|
+
// render: () => (
|
|
207
|
+
// <div style={{ width: "300px" }}>
|
|
208
|
+
// <FormField label="Pick books">
|
|
209
|
+
// {({ id }) => (
|
|
210
|
+
// <MultiSelect
|
|
211
|
+
// id={id}
|
|
212
|
+
// data={books}
|
|
213
|
+
// itemToString={itemToString}
|
|
214
|
+
// renderItem={renderItem}
|
|
215
|
+
// placeholder="Select books..."
|
|
216
|
+
// defaultSelectedItemIds={[
|
|
217
|
+
// "book-1",
|
|
218
|
+
// "book-2",
|
|
219
|
+
// "book-3",
|
|
220
|
+
// "book-4",
|
|
221
|
+
// "book-5",
|
|
222
|
+
// ]}
|
|
223
|
+
// maxTokens={2}
|
|
224
|
+
// />
|
|
225
|
+
// )}
|
|
226
|
+
// </FormField>
|
|
227
|
+
// </div>
|
|
228
|
+
// ),
|
|
229
|
+
// };
|
|
198
230
|
|
|
199
|
-
export const
|
|
200
|
-
name: "
|
|
231
|
+
export const DisabledItems: Story = {
|
|
232
|
+
name: "Disabled items",
|
|
201
233
|
render: () => (
|
|
202
234
|
<div style={{ width: "300px" }}>
|
|
203
235
|
<FormField label="Pick books">
|
|
204
236
|
{({ id }) => (
|
|
205
237
|
<MultiSelect
|
|
206
238
|
id={id}
|
|
207
|
-
data={
|
|
239
|
+
data={booksWithDisabled}
|
|
208
240
|
itemToString={itemToString}
|
|
209
|
-
renderItem={renderItem}
|
|
210
241
|
placeholder="Select books..."
|
|
211
|
-
defaultSelectedItemIds={[
|
|
212
|
-
"book-1",
|
|
213
|
-
"book-2",
|
|
214
|
-
"book-3",
|
|
215
|
-
"book-4",
|
|
216
|
-
"book-5",
|
|
217
|
-
]}
|
|
218
|
-
maxTokens={2}
|
|
219
242
|
/>
|
|
220
243
|
)}
|
|
221
244
|
</FormField>
|