@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/seeds-react-menu",
3
- "version": "1.11.1",
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,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 value={value} style={hidden ? { display: "none" } : undefined}>
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)`
@@ -1,3 +1,4 @@
1
1
  export interface DataWithId {
2
2
  id: string | number;
3
+ disabled?: boolean;
3
4
  }
@@ -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 { books, largeBookSet, itemToString, renderItem } from "./storyData";
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: () => (
@@ -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 default function MultiCombobox<T extends DataWithId>(
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 { books, largeBookSet, itemToString, renderItem } from "./storyData";
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 default function MultiSearchableSelect<T extends DataWithId>(
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 { 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",
@@ -169,53 +174,71 @@ export const CustomSelection: Story = {
169
174
  ),
170
175
  };
171
176
 
172
- export const CustomToken: Story = {
173
- name: "Custom renderToken",
174
- render: () => (
175
- <div style={{ width: "300px" }}>
176
- <FormField label="Pick books">
177
- {({ id }) => (
178
- <MultiSelect
179
- id={id}
180
- data={books}
181
- itemToString={itemToString}
182
- renderItem={renderItem}
183
- placeholder="Select books..."
184
- renderToken={(item) => (
185
- <span>
186
- {item.title}{" "}
187
- <span style={{ fontSize: "11px", opacity: 0.7 }}>
188
- ({item.author})
189
- </span>
190
- </span>
191
- )}
192
- />
193
- )}
194
- </FormField>
195
- </div>
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 MaxTokens: Story = {
200
- name: "Max tokens",
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={books}
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>