@sproutsocial/seeds-react-menu 1.11.2 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/seeds-react-menu",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "description": "Seeds React Menu",
5
5
  "author": "Sprout Social, Inc.",
6
6
  "license": "MIT",
@@ -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,7 @@ function ComboboxItemInner<T>(
38
40
  data-index={dataIndex}
39
41
  style={style}
40
42
  ref={ref}
43
+ disabled={disabled}
41
44
  data-qa-menu-item={label}
42
45
  >
43
46
  {inputType === "radio" ? (
@@ -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,6 +66,7 @@ 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,
@@ -72,6 +74,7 @@ export default function SelectItem({
72
74
  return (
73
75
  <StyledItem
74
76
  value={value}
77
+ disabled={disabled}
75
78
  style={hidden ? { display: "none" } : undefined}
76
79
  data-qa-menu-item={label}
77
80
  >
@@ -1,3 +1,4 @@
1
1
  export interface DataWithId {
2
2
  id: string | number;
3
+ disabled?: boolean;
3
4
  }
@@ -2,7 +2,13 @@ import React from "react";
2
2
  import type { Meta, StoryObj } from "@storybook/react";
3
3
  import { FormField } from "@sproutsocial/seeds-react-form-field";
4
4
  import { MultiCombobox } from "./MultiCombobox";
5
- import { books, largeBookSet, itemToString, renderItem } from "./storyData";
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: () => (
@@ -343,6 +343,7 @@ export function MultiCombobox<T extends DataWithId>(
343
343
  value={item}
344
344
  itemId={String(item.id)}
345
345
  label={itemToString(item)}
346
+ disabled={item.disabled}
346
347
  inputType={inputType}
347
348
  renderItem={
348
349
  renderItem ? () => renderItem(item) : () => itemToString(item)
@@ -525,6 +526,7 @@ export function MultiCombobox<T extends DataWithId>(
525
526
  value={item}
526
527
  itemId={String(item.id)}
527
528
  label={itemToString(item)}
529
+ disabled={item.disabled}
528
530
  inputType={inputType}
529
531
  renderItem={
530
532
  renderItem
@@ -545,6 +547,7 @@ export function MultiCombobox<T extends DataWithId>(
545
547
  value={item}
546
548
  itemId={String(item.id)}
547
549
  label={itemToString(item)}
550
+ disabled={item.disabled}
548
551
  inputType={inputType}
549
552
  renderItem={
550
553
  renderItem
@@ -2,7 +2,13 @@ import React from "react";
2
2
  import type { Meta, StoryObj } from "@storybook/react";
3
3
  import { FormField } from "@sproutsocial/seeds-react-form-field";
4
4
  import { MultiSearchableSelect } from "./MultiSearchableSelect";
5
- import { books, largeBookSet, itemToString, renderItem } from "./storyData";
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: () => (
@@ -342,6 +342,7 @@ export function MultiSearchableSelect<T extends DataWithId>(
342
342
  value={item}
343
343
  itemId={String(item.id)}
344
344
  label={itemToString(item)}
345
+ disabled={item.disabled}
345
346
  inputType={inputType}
346
347
  renderItem={
347
348
  renderItem ? () => renderItem(item) : () => itemToString(item)
@@ -508,6 +509,7 @@ export function MultiSearchableSelect<T extends DataWithId>(
508
509
  value={item}
509
510
  itemId={String(item.id)}
510
511
  label={itemToString(item)}
512
+ disabled={item.disabled}
511
513
  inputType={inputType}
512
514
  renderItem={
513
515
  renderItem
@@ -528,6 +530,7 @@ export function MultiSearchableSelect<T extends DataWithId>(
528
530
  value={item}
529
531
  itemId={String(item.id)}
530
532
  label={itemToString(item)}
533
+ disabled={item.disabled}
531
534
  inputType={inputType}
532
535
  renderItem={
533
536
  renderItem
@@ -4,7 +4,12 @@ import { FormField } from "@sproutsocial/seeds-react-form-field";
4
4
  import { MultiSelect } from "./MultiSelect";
5
5
  import SelectItem from "./Common/SelectItem";
6
6
  import SelectGroup from "./Common/SelectGroup";
7
- import { books, itemToString, renderItem } from "./storyData";
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",
@@ -223,6 +228,24 @@ export const CustomSelection: Story = {
223
228
  // ),
224
229
  // };
225
230
 
231
+ export const DisabledItems: Story = {
232
+ name: "Disabled items",
233
+ render: () => (
234
+ <div style={{ width: "300px" }}>
235
+ <FormField label="Pick books">
236
+ {({ id }) => (
237
+ <MultiSelect
238
+ id={id}
239
+ data={booksWithDisabled}
240
+ itemToString={itemToString}
241
+ placeholder="Select books..."
242
+ />
243
+ )}
244
+ </FormField>
245
+ </div>
246
+ ),
247
+ };
248
+
226
249
  export const RemoveSelectedItems: Story = {
227
250
  name: "Remove selected items",
228
251
  render: () => (
@@ -238,6 +238,7 @@ export function MultiSelect<T extends DataWithId>(props: MultiSelectProps<T>) {
238
238
  key={item.id}
239
239
  value={String(item.id)}
240
240
  label={itemToString(item)}
241
+ disabled={item.disabled}
241
242
  inputType={inputType}
242
243
  hidden={
243
244
  removeSelectedItems &&
@@ -257,6 +258,7 @@ export function MultiSelect<T extends DataWithId>(props: MultiSelectProps<T>) {
257
258
  key={item.id}
258
259
  value={String(item.id)}
259
260
  label={itemToString(item)}
261
+ disabled={item.disabled}
260
262
  inputType={inputType}
261
263
  hidden={
262
264
  removeSelectedItems && value.includes(String(item.id))
@@ -2,7 +2,13 @@ import React from "react";
2
2
  import type { Meta, StoryObj } from "@storybook/react";
3
3
  import { FormField } from "@sproutsocial/seeds-react-form-field";
4
4
  import { SingleCombobox } from "./SingleCombobox";
5
- import { books, largeBookSet, itemToString, renderItem } from "./storyData";
5
+ import {
6
+ books,
7
+ booksWithDisabled,
8
+ largeBookSet,
9
+ itemToString,
10
+ renderItem,
11
+ } from "./storyData";
6
12
 
7
13
  const meta: Meta<typeof SingleCombobox> = {
8
14
  title: "Really Under Development/V3/Single Combobox",
@@ -148,6 +154,24 @@ export const Controlled: Story = {
148
154
  },
149
155
  };
150
156
 
157
+ export const DisabledItems: Story = {
158
+ name: "Disabled items",
159
+ render: () => (
160
+ <div style={{ width: "300px" }}>
161
+ <FormField label="Pick a book">
162
+ {({ id }) => (
163
+ <SingleCombobox
164
+ id={id}
165
+ data={booksWithDisabled}
166
+ itemToString={itemToString}
167
+ placeholder="Search books..."
168
+ />
169
+ )}
170
+ </FormField>
171
+ </div>
172
+ ),
173
+ };
174
+
151
175
  export const Virtualized: Story = {
152
176
  name: "Virtualized",
153
177
  render: () => (
@@ -267,6 +267,7 @@ export function SingleCombobox<T extends DataWithId>(
267
267
  value={item}
268
268
  itemId={String(item.id)}
269
269
  label={itemToString(item)}
270
+ disabled={item.disabled}
270
271
  inputType={inputType}
271
272
  renderItem={
272
273
  renderItem
@@ -287,6 +288,7 @@ export function SingleCombobox<T extends DataWithId>(
287
288
  value={item}
288
289
  itemId={String(item.id)}
289
290
  label={itemToString(item)}
291
+ disabled={item.disabled}
290
292
  inputType={inputType}
291
293
  renderItem={
292
294
  renderItem
@@ -2,7 +2,13 @@ import React from "react";
2
2
  import type { Meta, StoryObj } from "@storybook/react";
3
3
  import { FormField } from "@sproutsocial/seeds-react-form-field";
4
4
  import { SingleSearchableSelect } from "./SingleSearchableSelect";
5
- import { books, largeBookSet, itemToString, renderItem } from "./storyData";
5
+ import {
6
+ books,
7
+ booksWithDisabled,
8
+ largeBookSet,
9
+ itemToString,
10
+ renderItem,
11
+ } from "./storyData";
6
12
 
7
13
  const meta: Meta<typeof SingleSearchableSelect> = {
8
14
  title: "Really Under Development/V3/Single Searchable Select",
@@ -163,6 +169,45 @@ export const CustomSelection: Story = {
163
169
  ),
164
170
  };
165
171
 
172
+ export const DisabledItems: Story = {
173
+ name: "Disabled items",
174
+ render: () => (
175
+ <div style={{ width: "300px" }}>
176
+ <FormField label="Pick a book">
177
+ {({ id }) => (
178
+ <SingleSearchableSelect
179
+ id={id}
180
+ data={booksWithDisabled}
181
+ itemToString={itemToString}
182
+ placeholder="Select a book"
183
+ searchPlaceholder="Search books..."
184
+ />
185
+ )}
186
+ </FormField>
187
+ </div>
188
+ ),
189
+ };
190
+
191
+ export const IncludePlaceholderItem: Story = {
192
+ name: "Include placeholder item",
193
+ render: () => (
194
+ <div style={{ width: "300px" }}>
195
+ <FormField label="Pick a book">
196
+ {({ id }) => (
197
+ <SingleSearchableSelect
198
+ id={id}
199
+ data={books}
200
+ itemToString={itemToString}
201
+ placeholder="Select a book"
202
+ searchPlaceholder="Search books..."
203
+ includePlaceholderItem
204
+ />
205
+ )}
206
+ </FormField>
207
+ </div>
208
+ ),
209
+ };
210
+
166
211
  export const Virtualized: Story = {
167
212
  name: "Virtualized",
168
213
  render: () => (
@@ -29,6 +29,7 @@ import { StyledChevron, ChevronIcon } from "./Common/SelectIcons";
29
29
  interface SingleSearchableSelectBaseProps {
30
30
  id?: string;
31
31
  placeholder?: string;
32
+ includePlaceholderItem?: boolean;
32
33
  searchPlaceholder?: string;
33
34
  emptyText?: string;
34
35
  isLoading?: boolean;
@@ -92,6 +93,7 @@ export function SingleSearchableSelect<T extends DataWithId>(
92
93
  const {
93
94
  id,
94
95
  placeholder = "Select...",
96
+ includePlaceholderItem,
95
97
  searchPlaceholder = "Search...",
96
98
  emptyText = "No results found.",
97
99
  isLoading = false,
@@ -284,6 +286,7 @@ export function SingleSearchableSelect<T extends DataWithId>(
284
286
  value={item}
285
287
  itemId={String(item.id)}
286
288
  label={itemToString(item)}
289
+ disabled={item.disabled}
287
290
  inputType={inputType}
288
291
  renderItem={
289
292
  renderItem
@@ -298,18 +301,31 @@ export function SingleSearchableSelect<T extends DataWithId>(
298
301
  </React.Fragment>
299
302
  )
300
303
  ) : (
301
- (item: T) => (
302
- <ComboboxItem
303
- key={item.id}
304
- value={item}
305
- itemId={String(item.id)}
306
- label={itemToString(item)}
307
- inputType={inputType}
308
- renderItem={
309
- renderItem ? () => renderItem(item) : undefined
310
- }
311
- />
312
- )
304
+ <>
305
+ {includePlaceholderItem && (
306
+ <ComboboxItem
307
+ key="placeholder"
308
+ value={null as unknown as T}
309
+ itemId="placeholder"
310
+ label={placeholder}
311
+ />
312
+ )}
313
+ <Combobox.Collection>
314
+ {(item: T) => (
315
+ <ComboboxItem
316
+ key={item.id}
317
+ value={item}
318
+ itemId={String(item.id)}
319
+ label={itemToString(item)}
320
+ disabled={item.disabled}
321
+ inputType={inputType}
322
+ renderItem={
323
+ renderItem ? () => renderItem(item) : undefined
324
+ }
325
+ />
326
+ )}
327
+ </Combobox.Collection>
328
+ </>
313
329
  )}
314
330
  </SearchableSelectList>
315
331
  </SearchableSelectPopup>
@@ -4,7 +4,12 @@ import { FormField } from "@sproutsocial/seeds-react-form-field";
4
4
  import { SingleSelect } from "./SingleSelect";
5
5
  import SelectItem from "./Common/SelectItem";
6
6
  import SelectGroup from "./Common/SelectGroup";
7
- import { books, itemToString, renderItem } from "./storyData";
7
+ import {
8
+ books,
9
+ booksWithDisabled,
10
+ itemToString,
11
+ renderItem,
12
+ } from "./storyData";
8
13
 
9
14
  const meta: Meta<typeof SingleSelect> = {
10
15
  title: "Really Under Development/V3/Single Select",
@@ -217,6 +222,24 @@ export const CustomSelection: Story = {
217
222
  ),
218
223
  };
219
224
 
225
+ export const DisabledItems: Story = {
226
+ name: "Disabled items",
227
+ render: () => (
228
+ <div style={{ width: "300px" }}>
229
+ <FormField label="Pick a book">
230
+ {({ id }) => (
231
+ <SingleSelect
232
+ id={id}
233
+ data={booksWithDisabled}
234
+ itemToString={itemToString}
235
+ placeholder="Select a book"
236
+ />
237
+ )}
238
+ </FormField>
239
+ </div>
240
+ ),
241
+ };
242
+
220
243
  export const Children: Story = {
221
244
  name: "Children API",
222
245
  render: () => (
@@ -199,6 +199,7 @@ export function SingleSelect<T extends DataWithId>(
199
199
  key={item.id}
200
200
  value={String(item.id)}
201
201
  label={itemToString(item)}
202
+ disabled={item.disabled}
202
203
  inputType={inputType}
203
204
  renderItem={
204
205
  renderItem
@@ -212,7 +213,6 @@ export function SingleSelect<T extends DataWithId>(
212
213
  </React.Fragment>
213
214
  ))
214
215
  ) : (
215
- // TODO: need to add a placeholder item when includePlaceholderItem is true
216
216
  <>
217
217
  {includePlaceholderItem && (
218
218
  <SelectItem
@@ -226,6 +226,7 @@ export function SingleSelect<T extends DataWithId>(
226
226
  key={item.id}
227
227
  value={String(item.id)}
228
228
  label={itemToString(item)}
229
+ disabled={item.disabled}
229
230
  inputType={inputType}
230
231
  renderItem={
231
232
  renderItem
@@ -105,6 +105,11 @@ const generateBooks = (count: number): Book[] => {
105
105
 
106
106
  export const largeBookSet = generateBooks(1000);
107
107
 
108
+ export const booksWithDisabled: Book[] = books.map((book) => ({
109
+ ...book,
110
+ disabled: book.id === "book-3" || book.id === "book-7",
111
+ }));
112
+
108
113
  export const itemToString = (item: Book | null) => item?.title ?? "";
109
114
 
110
115
  export const renderItem = (item: Book) => (