@sproutsocial/seeds-react-menu 1.12.0 → 1.12.2
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 +16 -16
- package/CHANGELOG.md +19 -0
- package/dist/esm/v3/index.js +212 -63
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/v3/index.d.mts +13 -1
- package/dist/v3/index.d.ts +13 -1
- package/dist/v3/index.js +212 -63
- package/dist/v3/index.js.map +1 -1
- package/package.json +9 -9
- package/src/v3/Common/VirtualizedComboboxList.tsx +29 -2
- package/src/v3/Common/sentinels.ts +13 -0
- package/src/v3/MultiCombobox.stories.tsx +85 -1
- package/src/v3/MultiCombobox.tsx +238 -62
- package/src/v3/MultiSearchableSelect.tsx +6 -1
- package/src/v3/MultiSelect.tsx +3 -1
- package/src/v3/SingleCombobox.tsx +7 -1
- package/src/v3/SingleSearchableSelect.tsx +3 -1
- package/src/v3/SingleSelect.stories.tsx +19 -0
- package/src/v3/SingleSelect.tsx +3 -1
package/dist/v3/index.d.mts
CHANGED
|
@@ -13,6 +13,7 @@ interface SingleSelectBaseProps {
|
|
|
13
13
|
placeholder?: string;
|
|
14
14
|
includePlaceholderItem?: boolean;
|
|
15
15
|
disabled?: boolean;
|
|
16
|
+
"aria-describedby"?: string;
|
|
16
17
|
}
|
|
17
18
|
interface SingleSelectDataProps<T extends DataWithId> extends SingleSelectBaseProps {
|
|
18
19
|
data: T[];
|
|
@@ -47,6 +48,7 @@ interface MultiSelectBaseProps {
|
|
|
47
48
|
id?: string;
|
|
48
49
|
placeholder?: string;
|
|
49
50
|
disabled?: boolean;
|
|
51
|
+
"aria-describedby"?: string;
|
|
50
52
|
}
|
|
51
53
|
interface MultiSelectDataProps<T extends DataWithId> extends MultiSelectBaseProps {
|
|
52
54
|
data: T[];
|
|
@@ -89,6 +91,7 @@ interface SingleComboboxBaseProps {
|
|
|
89
91
|
emptyText?: string;
|
|
90
92
|
disabled?: boolean;
|
|
91
93
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
94
|
+
"aria-describedby"?: string;
|
|
92
95
|
}
|
|
93
96
|
interface SingleComboboxDataBaseProps<T extends DataWithId> extends SingleComboboxBaseProps {
|
|
94
97
|
data: T[];
|
|
@@ -134,6 +137,9 @@ interface MultiComboboxBaseProps {
|
|
|
134
137
|
loadingText?: string;
|
|
135
138
|
disabled?: boolean;
|
|
136
139
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
140
|
+
inputValue?: string;
|
|
141
|
+
onInputValueChange?: (value: string) => void;
|
|
142
|
+
"aria-describedby"?: string;
|
|
137
143
|
}
|
|
138
144
|
interface MultiComboboxDataProps<T extends DataWithId> extends MultiComboboxBaseProps {
|
|
139
145
|
data: T[];
|
|
@@ -148,10 +154,12 @@ interface MultiComboboxDataProps<T extends DataWithId> extends MultiComboboxBase
|
|
|
148
154
|
groupBy?: (item: T) => string;
|
|
149
155
|
renderGroupHeading?: (label: string) => react.ReactNode;
|
|
150
156
|
selectHeadings?: boolean;
|
|
151
|
-
selectAll?: boolean;
|
|
157
|
+
selectAll?: boolean | string;
|
|
152
158
|
isVirtualized?: boolean;
|
|
153
159
|
removeSelectedItems?: boolean;
|
|
154
160
|
maxTokens?: number;
|
|
161
|
+
creatable?: boolean;
|
|
162
|
+
onCreate?: (value: string) => T;
|
|
155
163
|
children?: never;
|
|
156
164
|
}
|
|
157
165
|
interface MultiComboboxChildrenProps extends MultiComboboxBaseProps {
|
|
@@ -170,6 +178,8 @@ interface MultiComboboxChildrenProps extends MultiComboboxBaseProps {
|
|
|
170
178
|
selectHeadings?: never;
|
|
171
179
|
selectAll?: never;
|
|
172
180
|
removeSelectedItems?: never;
|
|
181
|
+
creatable?: never;
|
|
182
|
+
onCreate?: never;
|
|
173
183
|
}
|
|
174
184
|
type MultiComboboxProps<T extends DataWithId> = MultiComboboxDataProps<T> | MultiComboboxChildrenProps;
|
|
175
185
|
declare function MultiCombobox<T extends DataWithId>(props: MultiComboboxProps<T>): react_jsx_runtime.JSX.Element;
|
|
@@ -184,6 +194,7 @@ interface SingleSearchableSelectBaseProps {
|
|
|
184
194
|
loadingText?: string;
|
|
185
195
|
disabled?: boolean;
|
|
186
196
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
197
|
+
"aria-describedby"?: string;
|
|
187
198
|
}
|
|
188
199
|
interface SingleSearchableSelectDataBaseProps<T extends DataWithId> extends SingleSearchableSelectBaseProps {
|
|
189
200
|
data: T[];
|
|
@@ -232,6 +243,7 @@ interface MultiSearchableSelectBaseProps {
|
|
|
232
243
|
loadingText?: string;
|
|
233
244
|
disabled?: boolean;
|
|
234
245
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
246
|
+
"aria-describedby"?: string;
|
|
235
247
|
}
|
|
236
248
|
interface MultiSearchableSelectDataProps<T extends DataWithId> extends MultiSearchableSelectBaseProps {
|
|
237
249
|
data: T[];
|
package/dist/v3/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ interface SingleSelectBaseProps {
|
|
|
13
13
|
placeholder?: string;
|
|
14
14
|
includePlaceholderItem?: boolean;
|
|
15
15
|
disabled?: boolean;
|
|
16
|
+
"aria-describedby"?: string;
|
|
16
17
|
}
|
|
17
18
|
interface SingleSelectDataProps<T extends DataWithId> extends SingleSelectBaseProps {
|
|
18
19
|
data: T[];
|
|
@@ -47,6 +48,7 @@ interface MultiSelectBaseProps {
|
|
|
47
48
|
id?: string;
|
|
48
49
|
placeholder?: string;
|
|
49
50
|
disabled?: boolean;
|
|
51
|
+
"aria-describedby"?: string;
|
|
50
52
|
}
|
|
51
53
|
interface MultiSelectDataProps<T extends DataWithId> extends MultiSelectBaseProps {
|
|
52
54
|
data: T[];
|
|
@@ -89,6 +91,7 @@ interface SingleComboboxBaseProps {
|
|
|
89
91
|
emptyText?: string;
|
|
90
92
|
disabled?: boolean;
|
|
91
93
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
94
|
+
"aria-describedby"?: string;
|
|
92
95
|
}
|
|
93
96
|
interface SingleComboboxDataBaseProps<T extends DataWithId> extends SingleComboboxBaseProps {
|
|
94
97
|
data: T[];
|
|
@@ -134,6 +137,9 @@ interface MultiComboboxBaseProps {
|
|
|
134
137
|
loadingText?: string;
|
|
135
138
|
disabled?: boolean;
|
|
136
139
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
140
|
+
inputValue?: string;
|
|
141
|
+
onInputValueChange?: (value: string) => void;
|
|
142
|
+
"aria-describedby"?: string;
|
|
137
143
|
}
|
|
138
144
|
interface MultiComboboxDataProps<T extends DataWithId> extends MultiComboboxBaseProps {
|
|
139
145
|
data: T[];
|
|
@@ -148,10 +154,12 @@ interface MultiComboboxDataProps<T extends DataWithId> extends MultiComboboxBase
|
|
|
148
154
|
groupBy?: (item: T) => string;
|
|
149
155
|
renderGroupHeading?: (label: string) => react.ReactNode;
|
|
150
156
|
selectHeadings?: boolean;
|
|
151
|
-
selectAll?: boolean;
|
|
157
|
+
selectAll?: boolean | string;
|
|
152
158
|
isVirtualized?: boolean;
|
|
153
159
|
removeSelectedItems?: boolean;
|
|
154
160
|
maxTokens?: number;
|
|
161
|
+
creatable?: boolean;
|
|
162
|
+
onCreate?: (value: string) => T;
|
|
155
163
|
children?: never;
|
|
156
164
|
}
|
|
157
165
|
interface MultiComboboxChildrenProps extends MultiComboboxBaseProps {
|
|
@@ -170,6 +178,8 @@ interface MultiComboboxChildrenProps extends MultiComboboxBaseProps {
|
|
|
170
178
|
selectHeadings?: never;
|
|
171
179
|
selectAll?: never;
|
|
172
180
|
removeSelectedItems?: never;
|
|
181
|
+
creatable?: never;
|
|
182
|
+
onCreate?: never;
|
|
173
183
|
}
|
|
174
184
|
type MultiComboboxProps<T extends DataWithId> = MultiComboboxDataProps<T> | MultiComboboxChildrenProps;
|
|
175
185
|
declare function MultiCombobox<T extends DataWithId>(props: MultiComboboxProps<T>): react_jsx_runtime.JSX.Element;
|
|
@@ -184,6 +194,7 @@ interface SingleSearchableSelectBaseProps {
|
|
|
184
194
|
loadingText?: string;
|
|
185
195
|
disabled?: boolean;
|
|
186
196
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
197
|
+
"aria-describedby"?: string;
|
|
187
198
|
}
|
|
188
199
|
interface SingleSearchableSelectDataBaseProps<T extends DataWithId> extends SingleSearchableSelectBaseProps {
|
|
189
200
|
data: T[];
|
|
@@ -232,6 +243,7 @@ interface MultiSearchableSelectBaseProps {
|
|
|
232
243
|
loadingText?: string;
|
|
233
244
|
disabled?: boolean;
|
|
234
245
|
filter?: ((item: unknown, query: string) => boolean) | null;
|
|
246
|
+
"aria-describedby"?: string;
|
|
235
247
|
}
|
|
236
248
|
interface MultiSearchableSelectDataProps<T extends DataWithId> extends MultiSearchableSelectBaseProps {
|
|
237
249
|
data: T[];
|
package/dist/v3/index.js
CHANGED
|
@@ -364,6 +364,7 @@ var StyledValue = (0, import_styled_components4.default)(import_select3.Select.V
|
|
|
364
364
|
`;
|
|
365
365
|
function SingleSelect(props) {
|
|
366
366
|
const { id, placeholder, includePlaceholderItem } = props;
|
|
367
|
+
const ariaDescribedBy = props["aria-describedby"];
|
|
367
368
|
const isChildrenMode = "children" in props && props.children != null;
|
|
368
369
|
const selectedItemId = props.selectedItemId;
|
|
369
370
|
const defaultSelectedItemId = props.defaultSelectedItemId;
|
|
@@ -421,7 +422,7 @@ function SingleSelect(props) {
|
|
|
421
422
|
onValueChange: handleValueChange,
|
|
422
423
|
id,
|
|
423
424
|
children: [
|
|
424
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(SelectTrigger, { children: [
|
|
425
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(SelectTrigger, { "aria-describedby": ariaDescribedBy, children: [
|
|
425
426
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StyledValue, { placeholder, children: renderSelection && selectedItem ? renderSelection(selectedItem) : void 0 }),
|
|
426
427
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SelectIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChevronIcon, {}) }) })
|
|
427
428
|
] }),
|
|
@@ -493,6 +494,7 @@ var Placeholder = import_styled_components5.default.div`
|
|
|
493
494
|
`;
|
|
494
495
|
function MultiSelect(props) {
|
|
495
496
|
const { id, placeholder = "Select..." } = props;
|
|
497
|
+
const ariaDescribedBy = props["aria-describedby"];
|
|
496
498
|
const isChildrenMode = "children" in props && props.children != null;
|
|
497
499
|
const data = isChildrenMode ? [] : props.data;
|
|
498
500
|
const itemToString = isChildrenMode ? () => "" : props.itemToString;
|
|
@@ -549,7 +551,7 @@ function MultiSelect(props) {
|
|
|
549
551
|
disabled: props.disabled,
|
|
550
552
|
id,
|
|
551
553
|
children: [
|
|
552
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(SelectTrigger, { children: [
|
|
554
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(SelectTrigger, { "aria-describedby": ariaDescribedBy, children: [
|
|
553
555
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectValue, { children: () => {
|
|
554
556
|
if (renderSelection) return renderSelection(selectedItems);
|
|
555
557
|
if (selectedItems.length === 0)
|
|
@@ -1160,6 +1162,12 @@ function makePlaceholderSentinel(label) {
|
|
|
1160
1162
|
function isPlaceholderSentinel(v) {
|
|
1161
1163
|
return typeof v === "object" && v !== null && "__placeholder" in v;
|
|
1162
1164
|
}
|
|
1165
|
+
function makeCreatableSentinel(label) {
|
|
1166
|
+
return { __creatable: true, label };
|
|
1167
|
+
}
|
|
1168
|
+
function isCreatableSentinel(v) {
|
|
1169
|
+
return typeof v === "object" && v !== null && "__creatable" in v;
|
|
1170
|
+
}
|
|
1163
1171
|
|
|
1164
1172
|
// src/v3/Common/VirtualizedComboboxList.tsx
|
|
1165
1173
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
@@ -1179,7 +1187,8 @@ function VirtualizedComboboxList({
|
|
|
1179
1187
|
itemToString,
|
|
1180
1188
|
inputType,
|
|
1181
1189
|
renderItem,
|
|
1182
|
-
renderGroupHeading
|
|
1190
|
+
renderGroupHeading,
|
|
1191
|
+
renderCreatableItem
|
|
1183
1192
|
}) {
|
|
1184
1193
|
const filteredItems = import_combobox2.Combobox.useFilteredItems();
|
|
1185
1194
|
const scrollElementRef = React7.useRef(null);
|
|
@@ -1297,6 +1306,17 @@ function VirtualizedComboboxList({
|
|
|
1297
1306
|
virtualItem.key
|
|
1298
1307
|
);
|
|
1299
1308
|
}
|
|
1309
|
+
if (isCreatableSentinel(row)) {
|
|
1310
|
+
if (renderCreatableItem) {
|
|
1311
|
+
return renderCreatableItem(
|
|
1312
|
+
row,
|
|
1313
|
+
baseStyle,
|
|
1314
|
+
virtualItem.index,
|
|
1315
|
+
virtualizer.measureElement
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
return null;
|
|
1319
|
+
}
|
|
1300
1320
|
const item = row;
|
|
1301
1321
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1302
1322
|
ComboboxItem_default,
|
|
@@ -1330,6 +1350,7 @@ function SingleCombobox(props) {
|
|
|
1330
1350
|
emptyText = "No results found.",
|
|
1331
1351
|
filter
|
|
1332
1352
|
} = props;
|
|
1353
|
+
const ariaDescribedBy = props["aria-describedby"];
|
|
1333
1354
|
const isChildrenMode = "children" in props && props.children != null;
|
|
1334
1355
|
const data = isChildrenMode ? [] : props.data;
|
|
1335
1356
|
const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
|
|
@@ -1400,7 +1421,14 @@ function SingleCombobox(props) {
|
|
|
1400
1421
|
} : void 0,
|
|
1401
1422
|
children: [
|
|
1402
1423
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ComboboxInputGroup, { children: [
|
|
1403
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1425
|
+
ComboboxInput,
|
|
1426
|
+
{
|
|
1427
|
+
placeholder,
|
|
1428
|
+
id,
|
|
1429
|
+
"aria-describedby": ariaDescribedBy
|
|
1430
|
+
}
|
|
1431
|
+
),
|
|
1404
1432
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ComboboxActionButtons, { children: [
|
|
1405
1433
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxClear, { "aria-label": "Clear selection", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ClearIcon, {}) }),
|
|
1406
1434
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronIcon, {}) }) })
|
|
@@ -1498,8 +1526,11 @@ function MultiCombobox(props) {
|
|
|
1498
1526
|
emptyText = "No results found.",
|
|
1499
1527
|
isLoading = false,
|
|
1500
1528
|
loadingText = "Loading...",
|
|
1501
|
-
filter
|
|
1529
|
+
filter,
|
|
1530
|
+
inputValue,
|
|
1531
|
+
onInputValueChange
|
|
1502
1532
|
} = props;
|
|
1533
|
+
const ariaDescribedBy = props["aria-describedby"];
|
|
1503
1534
|
const isChildrenMode = "children" in props && props.children != null;
|
|
1504
1535
|
const data = isChildrenMode ? [] : props.data;
|
|
1505
1536
|
const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
|
|
@@ -1512,14 +1543,20 @@ function MultiCombobox(props) {
|
|
|
1512
1543
|
const groupBy = isChildrenMode ? void 0 : props.groupBy;
|
|
1513
1544
|
const renderGroupHeading = isChildrenMode ? void 0 : props.renderGroupHeading;
|
|
1514
1545
|
const selectHeadings = isChildrenMode ? false : props.selectHeadings ?? false;
|
|
1515
|
-
const
|
|
1546
|
+
const selectAllProp = isChildrenMode ? false : props.selectAll ?? false;
|
|
1547
|
+
const selectAll = Boolean(selectAllProp);
|
|
1548
|
+
const selectAllLabel = typeof selectAllProp === "string" ? selectAllProp : "Select all";
|
|
1516
1549
|
const isVirtualized = isChildrenMode ? false : props.isVirtualized ?? false;
|
|
1550
|
+
const creatableProp = isChildrenMode ? false : props.creatable ?? false;
|
|
1551
|
+
const onCreateProp = isChildrenMode ? void 0 : props.onCreate;
|
|
1517
1552
|
const children = isChildrenMode ? props.children : void 0;
|
|
1518
1553
|
const selectedItemIds = props.selectedItemIds;
|
|
1519
1554
|
const defaultSelectedItemIds = props.defaultSelectedItemIds;
|
|
1520
1555
|
const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
|
|
1521
1556
|
const { containerRef, portalContainer } = useSeedsPortalContainer();
|
|
1522
1557
|
const [open, setOpen] = React9.useState(false);
|
|
1558
|
+
const [internalInputValue, setInternalInputValue] = React9.useState("");
|
|
1559
|
+
const skipNextInputChangeRef = React9.useRef(false);
|
|
1523
1560
|
const virtualizerRef = React9.useRef(null);
|
|
1524
1561
|
const isControlled = selectedItemIds !== void 0;
|
|
1525
1562
|
const idsToItems = React9.useCallback(
|
|
@@ -1538,22 +1575,51 @@ function MultiCombobox(props) {
|
|
|
1538
1575
|
() => groupBy ? groupItems(visibleData, groupBy) : null,
|
|
1539
1576
|
[visibleData, groupBy]
|
|
1540
1577
|
);
|
|
1578
|
+
const currentInputValue = inputValue ?? internalInputValue;
|
|
1579
|
+
const creatableSentinel = React9.useMemo(() => {
|
|
1580
|
+
if (!creatableProp) return null;
|
|
1581
|
+
const trimmed = currentInputValue.trim();
|
|
1582
|
+
if (!trimmed) return null;
|
|
1583
|
+
const lowered = trimmed.toLocaleLowerCase();
|
|
1584
|
+
const exactExists = data.some(
|
|
1585
|
+
(d) => itemToString(d).trim().toLocaleLowerCase() === lowered
|
|
1586
|
+
);
|
|
1587
|
+
if (exactExists) return null;
|
|
1588
|
+
return makeCreatableSentinel(trimmed);
|
|
1589
|
+
}, [creatableProp, currentInputValue, data, itemToString]);
|
|
1541
1590
|
const flatItems = React9.useMemo(() => {
|
|
1542
|
-
if (!
|
|
1591
|
+
if (!selectHeadings && !selectAll) return null;
|
|
1592
|
+
if (!groups && !selectAll) return null;
|
|
1543
1593
|
const rows = [];
|
|
1544
1594
|
if (selectAll) rows.push(SELECT_ALL_SENTINEL);
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1595
|
+
if (groups) {
|
|
1596
|
+
for (const group of groups) {
|
|
1597
|
+
rows.push(makeGroupHeaderSentinel(group.value));
|
|
1598
|
+
rows.push(...group.items);
|
|
1599
|
+
}
|
|
1600
|
+
} else {
|
|
1601
|
+
rows.push(...visibleData);
|
|
1548
1602
|
}
|
|
1549
1603
|
return rows;
|
|
1550
|
-
}, [groups, selectHeadings, selectAll]);
|
|
1604
|
+
}, [groups, visibleData, selectHeadings, selectAll]);
|
|
1551
1605
|
function setSelectedItems(items) {
|
|
1552
1606
|
if (!isControlled) setInternalValue(items);
|
|
1553
1607
|
if (onSelectedItemIdsChange)
|
|
1554
1608
|
onSelectedItemIdsChange(items.map((item) => item.id));
|
|
1555
1609
|
}
|
|
1556
1610
|
function handleValueChange(next) {
|
|
1611
|
+
const creatableClicked = next.find(isCreatableSentinel);
|
|
1612
|
+
if (creatableClicked) {
|
|
1613
|
+
const newItem = onCreateProp?.(creatableClicked.label);
|
|
1614
|
+
const realItems2 = next.filter(
|
|
1615
|
+
(v) => !isGroupHeaderSentinel2(v) && !isSelectAllSentinel2(v) && !isCreatableSentinel(v)
|
|
1616
|
+
);
|
|
1617
|
+
setSelectedItems(newItem ? [...realItems2, newItem] : realItems2);
|
|
1618
|
+
skipNextInputChangeRef.current = true;
|
|
1619
|
+
setInternalInputValue("");
|
|
1620
|
+
onInputValueChange?.("");
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1557
1623
|
const selectAllClicked = next.filter(isSelectAllSentinel2);
|
|
1558
1624
|
const groupSentinels = next.filter(isGroupHeaderSentinel2);
|
|
1559
1625
|
const realItems = next.filter(
|
|
@@ -1591,6 +1657,16 @@ function MultiCombobox(props) {
|
|
|
1591
1657
|
setSelectedItems(updated);
|
|
1592
1658
|
}
|
|
1593
1659
|
function handleSimpleValueChange(newItems) {
|
|
1660
|
+
const creatableClicked = newItems.find(isCreatableSentinel);
|
|
1661
|
+
if (creatableClicked) {
|
|
1662
|
+
const newItem = onCreateProp?.(creatableClicked.label);
|
|
1663
|
+
const realItems = newItems.filter((v) => !isCreatableSentinel(v));
|
|
1664
|
+
setSelectedItems(newItem ? [...realItems, newItem] : realItems);
|
|
1665
|
+
skipNextInputChangeRef.current = true;
|
|
1666
|
+
setInternalInputValue("");
|
|
1667
|
+
onInputValueChange?.("");
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
1594
1670
|
setSelectedItems(newItems);
|
|
1595
1671
|
}
|
|
1596
1672
|
function removeItem(item, e) {
|
|
@@ -1605,7 +1681,7 @@ function MultiCombobox(props) {
|
|
|
1605
1681
|
const state = selectedCount === 0 ? "none" : selectedCount === totalCount ? "all" : "partial";
|
|
1606
1682
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxSelectAllItem, { value: row, children: [
|
|
1607
1683
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxGroupHeaderCheckbox, { $state: state, id: "__selectAll" }),
|
|
1608
|
-
|
|
1684
|
+
selectAllLabel
|
|
1609
1685
|
] }, "__selectAll");
|
|
1610
1686
|
}
|
|
1611
1687
|
if (isGroupHeaderSentinel2(row)) {
|
|
@@ -1626,6 +1702,9 @@ function MultiCombobox(props) {
|
|
|
1626
1702
|
renderGroupHeading ? renderGroupHeading(row.groupName) : row.groupName
|
|
1627
1703
|
] }, `__header-${row.groupName}`);
|
|
1628
1704
|
}
|
|
1705
|
+
if (isCreatableSentinel(row)) {
|
|
1706
|
+
return renderCreatableItem(row);
|
|
1707
|
+
}
|
|
1629
1708
|
const item = row;
|
|
1630
1709
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1631
1710
|
ComboboxItem_default,
|
|
@@ -1640,7 +1719,28 @@ function MultiCombobox(props) {
|
|
|
1640
1719
|
item.id
|
|
1641
1720
|
);
|
|
1642
1721
|
}
|
|
1643
|
-
|
|
1722
|
+
function renderCreatableItem(sentinel, style, index, measureRef) {
|
|
1723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1724
|
+
ComboboxItem_default,
|
|
1725
|
+
{
|
|
1726
|
+
value: sentinel,
|
|
1727
|
+
itemId: "__creatable",
|
|
1728
|
+
label: `Create "${sentinel.label}"`,
|
|
1729
|
+
inputType: "none",
|
|
1730
|
+
renderItem: () => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1731
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_seeds_react_icon3.default, { name: "plus-outline", size: "mini" }),
|
|
1732
|
+
`Create "${sentinel.label}"`
|
|
1733
|
+
] }),
|
|
1734
|
+
style,
|
|
1735
|
+
index,
|
|
1736
|
+
"data-index": index,
|
|
1737
|
+
ref: measureRef
|
|
1738
|
+
},
|
|
1739
|
+
"__creatable"
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
const baseItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
|
|
1743
|
+
const rootItems = creatableSentinel && Array.isArray(baseItems) ? [...baseItems, creatableSentinel] : baseItems;
|
|
1644
1744
|
const hasSentinels = selectAll || selectHeadings;
|
|
1645
1745
|
const rootValue = hasSentinels ? [...value] : value;
|
|
1646
1746
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Field, { children: [
|
|
@@ -1653,8 +1753,27 @@ function MultiCombobox(props) {
|
|
|
1653
1753
|
virtualized: isVirtualized,
|
|
1654
1754
|
open,
|
|
1655
1755
|
disabled: props.disabled,
|
|
1656
|
-
onOpenChange:
|
|
1657
|
-
|
|
1756
|
+
onOpenChange: (nextOpen, eventDetails) => {
|
|
1757
|
+
if (!nextOpen && eventDetails.reason === "item-press") return;
|
|
1758
|
+
setOpen(nextOpen);
|
|
1759
|
+
},
|
|
1760
|
+
filter: creatableProp ? (item, query) => {
|
|
1761
|
+
if (isCreatableSentinel(item)) return true;
|
|
1762
|
+
if (filter) return filter(item, query);
|
|
1763
|
+
if (isGroupHeaderSentinel2(item) || isSelectAllSentinel2(item))
|
|
1764
|
+
return true;
|
|
1765
|
+
const label = itemToString(item);
|
|
1766
|
+
return label.toLowerCase().includes(query.toLowerCase());
|
|
1767
|
+
} : filter,
|
|
1768
|
+
inputValue: creatableProp ? currentInputValue : inputValue,
|
|
1769
|
+
onInputValueChange: creatableProp ? (v) => {
|
|
1770
|
+
if (skipNextInputChangeRef.current) {
|
|
1771
|
+
skipNextInputChangeRef.current = false;
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
setInternalInputValue(v);
|
|
1775
|
+
onInputValueChange?.(v);
|
|
1776
|
+
} : onInputValueChange,
|
|
1658
1777
|
onItemHighlighted: isVirtualized ? (item, { reason, index }) => {
|
|
1659
1778
|
const virt = virtualizerRef.current;
|
|
1660
1779
|
if (!item || !virt) return;
|
|
@@ -1674,15 +1793,17 @@ function MultiCombobox(props) {
|
|
|
1674
1793
|
hasSentinels ? handleValueChange : handleSimpleValueChange
|
|
1675
1794
|
),
|
|
1676
1795
|
itemToStringLabel: (item) => {
|
|
1677
|
-
if (!item || isGroupHeaderSentinel2(item) || isSelectAllSentinel2(item))
|
|
1796
|
+
if (!item || isGroupHeaderSentinel2(item) || isSelectAllSentinel2(item) || isCreatableSentinel(item))
|
|
1678
1797
|
return "";
|
|
1679
1798
|
return itemToString(item);
|
|
1680
1799
|
},
|
|
1681
1800
|
isItemEqualToValue: (a, b) => {
|
|
1801
|
+
if (isCreatableSentinel(a) && isCreatableSentinel(b))
|
|
1802
|
+
return a.label === b.label;
|
|
1682
1803
|
if (isGroupHeaderSentinel2(a) && isGroupHeaderSentinel2(b))
|
|
1683
1804
|
return a.groupName === b.groupName;
|
|
1684
1805
|
if (isSelectAllSentinel2(a) && isSelectAllSentinel2(b)) return true;
|
|
1685
|
-
if (!isGroupHeaderSentinel2(a) && !isSelectAllSentinel2(a) && !isGroupHeaderSentinel2(b) && !isSelectAllSentinel2(b))
|
|
1806
|
+
if (!isGroupHeaderSentinel2(a) && !isSelectAllSentinel2(a) && !isCreatableSentinel(a) && !isGroupHeaderSentinel2(b) && !isSelectAllSentinel2(b) && !isCreatableSentinel(b))
|
|
1686
1807
|
return a.id === b.id;
|
|
1687
1808
|
return false;
|
|
1688
1809
|
},
|
|
@@ -1715,7 +1836,8 @@ function MultiCombobox(props) {
|
|
|
1715
1836
|
ComboboxTokenInput,
|
|
1716
1837
|
{
|
|
1717
1838
|
id,
|
|
1718
|
-
placeholder: value.length > 0 ? "" : placeholder
|
|
1839
|
+
placeholder: value.length > 0 ? "" : placeholder,
|
|
1840
|
+
"aria-describedby": ariaDescribedBy
|
|
1719
1841
|
}
|
|
1720
1842
|
),
|
|
1721
1843
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxActionButtons, { children: [
|
|
@@ -1752,37 +1874,55 @@ function MultiCombobox(props) {
|
|
|
1752
1874
|
itemToString,
|
|
1753
1875
|
inputType,
|
|
1754
1876
|
renderItem,
|
|
1755
|
-
renderGroupHeading
|
|
1877
|
+
renderGroupHeading,
|
|
1878
|
+
renderCreatableItem: creatableProp ? (sentinel, style, index, measureRef) => renderCreatableItem(
|
|
1879
|
+
sentinel,
|
|
1880
|
+
style,
|
|
1881
|
+
index,
|
|
1882
|
+
measureRef
|
|
1883
|
+
) : void 0
|
|
1756
1884
|
}
|
|
1757
|
-
) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) =>
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
}
|
|
1784
|
-
item
|
|
1785
|
-
|
|
1885
|
+
) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
|
|
1886
|
+
if (isCreatableSentinel(group)) {
|
|
1887
|
+
return renderCreatableItem(group);
|
|
1888
|
+
}
|
|
1889
|
+
const g = group;
|
|
1890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(React9.Fragment, { children: [
|
|
1891
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxGroup, { items: g.items, children: [
|
|
1892
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
|
|
1893
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_combobox4.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1894
|
+
ComboboxItem_default,
|
|
1895
|
+
{
|
|
1896
|
+
value: item,
|
|
1897
|
+
itemId: String(item.id),
|
|
1898
|
+
label: itemToString(item),
|
|
1899
|
+
disabled: item.disabled,
|
|
1900
|
+
inputType,
|
|
1901
|
+
renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
|
|
1902
|
+
},
|
|
1903
|
+
item.id
|
|
1904
|
+
) })
|
|
1905
|
+
] }),
|
|
1906
|
+
index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxSeparator, {})
|
|
1907
|
+
] }, g.value);
|
|
1908
|
+
} : (item) => {
|
|
1909
|
+
if (isCreatableSentinel(item)) {
|
|
1910
|
+
return renderCreatableItem(item);
|
|
1911
|
+
}
|
|
1912
|
+
const dataItem = item;
|
|
1913
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1914
|
+
ComboboxItem_default,
|
|
1915
|
+
{
|
|
1916
|
+
value: dataItem,
|
|
1917
|
+
itemId: String(dataItem.id),
|
|
1918
|
+
label: itemToString(dataItem),
|
|
1919
|
+
disabled: dataItem.disabled,
|
|
1920
|
+
inputType,
|
|
1921
|
+
renderItem: renderItem ? () => renderItem(dataItem) : () => itemToString(dataItem)
|
|
1922
|
+
},
|
|
1923
|
+
dataItem.id
|
|
1924
|
+
);
|
|
1925
|
+
}
|
|
1786
1926
|
}
|
|
1787
1927
|
)
|
|
1788
1928
|
]
|
|
@@ -1810,6 +1950,7 @@ function SingleSearchableSelect(props) {
|
|
|
1810
1950
|
loadingText = "Loading...",
|
|
1811
1951
|
filter
|
|
1812
1952
|
} = props;
|
|
1953
|
+
const ariaDescribedBy = props["aria-describedby"];
|
|
1813
1954
|
const isChildrenMode = "children" in props && props.children != null;
|
|
1814
1955
|
const data = isChildrenMode ? [] : props.data;
|
|
1815
1956
|
const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
|
|
@@ -1884,7 +2025,7 @@ function SingleSearchableSelect(props) {
|
|
|
1884
2025
|
}
|
|
1885
2026
|
} : void 0,
|
|
1886
2027
|
children: [
|
|
1887
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SearchableSelectTrigger, { id, children: [
|
|
2028
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SearchableSelectTrigger, { id, "aria-describedby": ariaDescribedBy, children: [
|
|
1888
2029
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchableSelectPlaceholder, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_combobox5.Combobox.Value, { placeholder, children: value ? renderSelection ? renderSelection(value) : itemToString(value) : placeholder }) }),
|
|
1889
2030
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchableSelectTriggerIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChevronIcon, {}) }) })
|
|
1890
2031
|
] }),
|
|
@@ -2009,6 +2150,7 @@ function MultiSearchableSelect(props) {
|
|
|
2009
2150
|
loadingText = "Loading...",
|
|
2010
2151
|
filter
|
|
2011
2152
|
} = props;
|
|
2153
|
+
const ariaDescribedBy = props["aria-describedby"];
|
|
2012
2154
|
const isChildrenMode = "children" in props && props.children != null;
|
|
2013
2155
|
const data = isChildrenMode ? [] : props.data;
|
|
2014
2156
|
const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
|
|
@@ -2192,20 +2334,27 @@ function MultiSearchableSelect(props) {
|
|
|
2192
2334
|
},
|
|
2193
2335
|
items: rootItems,
|
|
2194
2336
|
children: [
|
|
2195
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2337
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2338
|
+
SearchableSelectTokenTrigger,
|
|
2339
|
+
{
|
|
2340
|
+
id,
|
|
2341
|
+
"aria-describedby": ariaDescribedBy,
|
|
2342
|
+
children: [
|
|
2343
|
+
renderSelection ? renderSelection(value) : value.length > 0 ? (() => {
|
|
2344
|
+
const visibleItems = maxSelections != null ? value.slice(0, maxSelections) : value;
|
|
2345
|
+
const overflowCount = maxSelections != null && value.length > maxSelections ? value.length - maxSelections : 0;
|
|
2346
|
+
const text = visibleItems.map(
|
|
2347
|
+
(item) => customRenderSelections ? customRenderSelections(item) : itemToString(item)
|
|
2348
|
+
).join(", ");
|
|
2349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(SelectionText2, { children: [
|
|
2350
|
+
text,
|
|
2351
|
+
overflowCount > 0 ? `, +${overflowCount}` : ""
|
|
2352
|
+
] });
|
|
2353
|
+
})() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SearchableSelectPlaceholder, { children: placeholder }),
|
|
2354
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SearchableSelectTriggerIcon, { style: { marginLeft: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ChevronIcon, {}) }) })
|
|
2355
|
+
]
|
|
2356
|
+
}
|
|
2357
|
+
),
|
|
2209
2358
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_combobox6.Combobox.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComboboxPositioner, { sideOffset: 4, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2210
2359
|
SearchableSelectPopup,
|
|
2211
2360
|
{
|