@sproutsocial/seeds-react-menu 1.11.2 → 1.11.4

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.4",
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
  >
@@ -6,6 +6,7 @@ export const Field = styled.div`
6
6
  display: flex;
7
7
  flex-direction: column;
8
8
  gap: ${({ theme }) => theme.space[200]};
9
+ width: 100%;
9
10
  `;
10
11
 
11
12
  export const SelectLabel = styled(Select.Label)`
@@ -8,6 +8,7 @@ import {
8
8
  ComboboxSelectAllItem,
9
9
  } from "./ComboboxStyles";
10
10
  import type { DataWithId } from "./types";
11
+ import { isPlaceholderSentinel } from "./sentinels";
11
12
 
12
13
  export const ITEM_HEIGHT = 32;
13
14
 
@@ -37,6 +38,10 @@ interface VirtualizedComboboxListProps<T extends DataWithId> {
37
38
  > | null>;
38
39
  value: T | T[] | null;
39
40
  groups: Array<{ value: string; items: T[] }> | null;
41
+ // `data` contains only real items (no sentinels). Sentinel rows (placeholder,
42
+ // group headers, select-all) come exclusively from `filteredItems` via
43
+ // Combobox.useFilteredItems. This means `data.length` is the correct count
44
+ // of selectable items for select-all logic.
40
45
  data: T[];
41
46
  itemToString: (item: T) => string;
42
47
  inputType: "icon" | "radio" | "checkbox" | "none";
@@ -109,7 +114,7 @@ export default function VirtualizedComboboxList<T extends DataWithId>({
109
114
  >
110
115
  {virtualizer.getVirtualItems().map((virtualItem) => {
111
116
  const row = filteredItems[virtualItem.index];
112
- if (!row) return null;
117
+ if (row == null) return null;
113
118
 
114
119
  const baseStyle: React.CSSProperties = {
115
120
  position: "absolute",
@@ -120,6 +125,22 @@ export default function VirtualizedComboboxList<T extends DataWithId>({
120
125
  boxSizing: "border-box",
121
126
  };
122
127
 
128
+ if (isPlaceholderSentinel(row)) {
129
+ return (
130
+ <ComboboxItem
131
+ key="placeholder"
132
+ index={virtualItem.index}
133
+ data-index={virtualItem.index}
134
+ value={row as unknown as T}
135
+ itemId="placeholder"
136
+ label={row.label}
137
+ inputType={inputType}
138
+ style={baseStyle}
139
+ ref={virtualizer.measureElement}
140
+ />
141
+ );
142
+ }
143
+
123
144
  if (isSelectAllSentinel(row)) {
124
145
  const selectedCount = selectedArray.length;
125
146
  const totalCount = data.length;
@@ -185,6 +206,7 @@ export default function VirtualizedComboboxList<T extends DataWithId>({
185
206
  value={item}
186
207
  itemId={String(item.id)}
187
208
  label={itemToString(item)}
209
+ disabled={item.disabled}
188
210
  inputType={inputType}
189
211
  renderItem={
190
212
  renderItem ? () => renderItem(item) : () => itemToString(item)
@@ -0,0 +1,17 @@
1
+ // ─── Shared sentinel types & predicates ────────────────────────────────────
2
+ // Sentinels are non-data rows injected into virtualized lists for special UI
3
+ // items (placeholder, group headers, select-all). They carry no `.id` field
4
+ // and must never be counted toward real data totals.
5
+
6
+ export interface PlaceholderSentinel {
7
+ __placeholder: true;
8
+ label: string;
9
+ }
10
+
11
+ export function makePlaceholderSentinel(label: string): PlaceholderSentinel {
12
+ return { __placeholder: true, label };
13
+ }
14
+
15
+ export function isPlaceholderSentinel(v: unknown): v is PlaceholderSentinel {
16
+ return typeof v === "object" && v !== null && "__placeholder" in v;
17
+ }
@@ -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,66 @@ 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
+
211
+ export const IncludePlaceholderItemVirtualized: Story = {
212
+ name: "Include placeholder item (virtualized)",
213
+ render: () => (
214
+ <div style={{ width: "300px" }}>
215
+ <FormField label="Pick a book">
216
+ {({ id }) => (
217
+ <SingleSearchableSelect
218
+ id={id}
219
+ data={largeBookSet}
220
+ itemToString={itemToString}
221
+ placeholder="Select a book"
222
+ searchPlaceholder="Search books..."
223
+ includePlaceholderItem
224
+ isVirtualized
225
+ />
226
+ )}
227
+ </FormField>
228
+ </div>
229
+ ),
230
+ };
231
+
166
232
  export const Virtualized: Story = {
167
233
  name: "Virtualized",
168
234
  render: () => (
@@ -6,6 +6,11 @@ import ComboboxItem from "./Common/ComboboxItem";
6
6
  import VirtualizedComboboxList from "./Common/VirtualizedComboboxList";
7
7
  import type { DataWithId } from "./Common/types";
8
8
  import { groupItems } from "./Common/groupItems";
9
+ import type { PlaceholderSentinel } from "./Common/sentinels";
10
+ import {
11
+ makePlaceholderSentinel,
12
+ isPlaceholderSentinel,
13
+ } from "./Common/sentinels";
9
14
  import { Field } from "./Common/SelectStyles";
10
15
  import {
11
16
  ComboboxGroup,
@@ -29,6 +34,7 @@ import { StyledChevron, ChevronIcon } from "./Common/SelectIcons";
29
34
  interface SingleSearchableSelectBaseProps {
30
35
  id?: string;
31
36
  placeholder?: string;
37
+ includePlaceholderItem?: boolean;
32
38
  searchPlaceholder?: string;
33
39
  emptyText?: string;
34
40
  isLoading?: boolean;
@@ -92,6 +98,7 @@ export function SingleSearchableSelect<T extends DataWithId>(
92
98
  const {
93
99
  id,
94
100
  placeholder = "Select...",
101
+ includePlaceholderItem,
95
102
  searchPlaceholder = "Search...",
96
103
  emptyText = "No results found.",
97
104
  isLoading = false,
@@ -162,10 +169,14 @@ export function SingleSearchableSelect<T extends DataWithId>(
162
169
  ? idToItem(selectedItemId as T["id"] | null)
163
170
  : internalValue;
164
171
 
165
- function handleValueChange(newItem: T | null) {
166
- if (!isControlled) setInternalValue(newItem);
172
+ type ItemOrSentinel = T | PlaceholderSentinel;
173
+
174
+ function handleValueChange(newItem: ItemOrSentinel | null) {
175
+ const realItem =
176
+ newItem == null || isPlaceholderSentinel(newItem) ? null : newItem;
177
+ if (!isControlled) setInternalValue(realItem);
167
178
  if (onSelectedItemIdChange) {
168
- onSelectedItemIdChange(newItem ? newItem.id : null);
179
+ onSelectedItemIdChange(realItem ? realItem.id : null);
169
180
  }
170
181
  }
171
182
 
@@ -181,11 +192,22 @@ export function SingleSearchableSelect<T extends DataWithId>(
181
192
  id={id}
182
193
  value={value}
183
194
  disabled={props.disabled}
184
- onValueChange={handleValueChange}
185
- itemToStringLabel={itemToString}
186
- isItemEqualToValue={(a, b) => a != null && b != null && a.id === b.id}
195
+ onValueChange={handleValueChange as (item: T | null) => void}
196
+ itemToStringLabel={(item: T | null) =>
197
+ isPlaceholderSentinel(item) ? item.label : itemToString(item)
198
+ }
199
+ isItemEqualToValue={(a, b) => {
200
+ if (isPlaceholderSentinel(a) && isPlaceholderSentinel(b)) return true;
201
+ if (isPlaceholderSentinel(a)) return b == null;
202
+ if (isPlaceholderSentinel(b)) return a == null;
203
+ return a != null && b != null && a.id === b.id;
204
+ }}
187
205
  items={
188
- isVirtualized ? data : groups ?? (isChildrenMode ? undefined : data)
206
+ isVirtualized
207
+ ? includePlaceholderItem
208
+ ? [makePlaceholderSentinel(placeholder) as unknown as T, ...data]
209
+ : data
210
+ : groups ?? (isChildrenMode ? undefined : data)
189
211
  }
190
212
  virtualized={isVirtualized}
191
213
  open={open}
@@ -218,7 +240,7 @@ export function SingleSearchableSelect<T extends DataWithId>(
218
240
  ? renderSelection
219
241
  ? renderSelection(value)
220
242
  : itemToString(value)
221
- : null}
243
+ : placeholder}
222
244
  </Combobox.Value>
223
245
  </SearchableSelectPlaceholder>
224
246
  <SearchableSelectTriggerIcon>
@@ -284,6 +306,7 @@ export function SingleSearchableSelect<T extends DataWithId>(
284
306
  value={item}
285
307
  itemId={String(item.id)}
286
308
  label={itemToString(item)}
309
+ disabled={item.disabled}
287
310
  inputType={inputType}
288
311
  renderItem={
289
312
  renderItem
@@ -298,18 +321,34 @@ export function SingleSearchableSelect<T extends DataWithId>(
298
321
  </React.Fragment>
299
322
  )
300
323
  ) : (
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
- )
324
+ <>
325
+ {includePlaceholderItem && (
326
+ <ComboboxItem
327
+ key="placeholder"
328
+ value={
329
+ makePlaceholderSentinel(placeholder) as unknown as T
330
+ }
331
+ itemId="placeholder"
332
+ label={placeholder}
333
+ inputType={inputType}
334
+ />
335
+ )}
336
+ <Combobox.Collection>
337
+ {(item: T) => (
338
+ <ComboboxItem
339
+ key={item.id}
340
+ value={item}
341
+ itemId={String(item.id)}
342
+ label={itemToString(item)}
343
+ disabled={item.disabled}
344
+ inputType={inputType}
345
+ renderItem={
346
+ renderItem ? () => renderItem(item) : undefined
347
+ }
348
+ />
349
+ )}
350
+ </Combobox.Collection>
351
+ </>
313
352
  )}
314
353
  </SearchableSelectList>
315
354
  </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