@sproutsocial/seeds-react-menu 1.12.1 → 1.12.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/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)(ComboboxInput, { placeholder, id }),
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, {}) }) })
@@ -1502,6 +1530,7 @@ function MultiCombobox(props) {
1502
1530
  inputValue,
1503
1531
  onInputValueChange
1504
1532
  } = props;
1533
+ const ariaDescribedBy = props["aria-describedby"];
1505
1534
  const isChildrenMode = "children" in props && props.children != null;
1506
1535
  const data = isChildrenMode ? [] : props.data;
1507
1536
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1518,12 +1547,16 @@ function MultiCombobox(props) {
1518
1547
  const selectAll = Boolean(selectAllProp);
1519
1548
  const selectAllLabel = typeof selectAllProp === "string" ? selectAllProp : "Select all";
1520
1549
  const isVirtualized = isChildrenMode ? false : props.isVirtualized ?? false;
1550
+ const creatableProp = isChildrenMode ? false : props.creatable ?? false;
1551
+ const onCreateProp = isChildrenMode ? void 0 : props.onCreate;
1521
1552
  const children = isChildrenMode ? props.children : void 0;
1522
1553
  const selectedItemIds = props.selectedItemIds;
1523
1554
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
1524
1555
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
1525
1556
  const { containerRef, portalContainer } = useSeedsPortalContainer();
1526
1557
  const [open, setOpen] = React9.useState(false);
1558
+ const [internalInputValue, setInternalInputValue] = React9.useState("");
1559
+ const skipNextInputChangeRef = React9.useRef(false);
1527
1560
  const virtualizerRef = React9.useRef(null);
1528
1561
  const isControlled = selectedItemIds !== void 0;
1529
1562
  const idsToItems = React9.useCallback(
@@ -1542,6 +1575,18 @@ function MultiCombobox(props) {
1542
1575
  () => groupBy ? groupItems(visibleData, groupBy) : null,
1543
1576
  [visibleData, groupBy]
1544
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]);
1545
1590
  const flatItems = React9.useMemo(() => {
1546
1591
  if (!selectHeadings && !selectAll) return null;
1547
1592
  if (!groups && !selectAll) return null;
@@ -1563,6 +1608,18 @@ function MultiCombobox(props) {
1563
1608
  onSelectedItemIdsChange(items.map((item) => item.id));
1564
1609
  }
1565
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
+ }
1566
1623
  const selectAllClicked = next.filter(isSelectAllSentinel2);
1567
1624
  const groupSentinels = next.filter(isGroupHeaderSentinel2);
1568
1625
  const realItems = next.filter(
@@ -1600,6 +1657,16 @@ function MultiCombobox(props) {
1600
1657
  setSelectedItems(updated);
1601
1658
  }
1602
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
+ }
1603
1670
  setSelectedItems(newItems);
1604
1671
  }
1605
1672
  function removeItem(item, e) {
@@ -1635,6 +1702,9 @@ function MultiCombobox(props) {
1635
1702
  renderGroupHeading ? renderGroupHeading(row.groupName) : row.groupName
1636
1703
  ] }, `__header-${row.groupName}`);
1637
1704
  }
1705
+ if (isCreatableSentinel(row)) {
1706
+ return renderCreatableItem(row);
1707
+ }
1638
1708
  const item = row;
1639
1709
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1640
1710
  ComboboxItem_default,
@@ -1649,7 +1719,28 @@ function MultiCombobox(props) {
1649
1719
  item.id
1650
1720
  );
1651
1721
  }
1652
- const rootItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
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;
1653
1744
  const hasSentinels = selectAll || selectHeadings;
1654
1745
  const rootValue = hasSentinels ? [...value] : value;
1655
1746
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Field, { children: [
@@ -1666,9 +1757,31 @@ function MultiCombobox(props) {
1666
1757
  if (!nextOpen && eventDetails.reason === "item-press") return;
1667
1758
  setOpen(nextOpen);
1668
1759
  },
1669
- filter,
1670
- inputValue,
1671
- onInputValueChange,
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 ?? internalInputValue,
1769
+ onInputValueChange: (v, eventDetails) => {
1770
+ if (eventDetails.reason === "input-clear" && open) return;
1771
+ if (creatableProp) {
1772
+ if (skipNextInputChangeRef.current) {
1773
+ skipNextInputChangeRef.current = false;
1774
+ return;
1775
+ }
1776
+ setInternalInputValue(v);
1777
+ onInputValueChange?.(v);
1778
+ } else {
1779
+ if (inputValue === void 0) {
1780
+ setInternalInputValue(v);
1781
+ }
1782
+ onInputValueChange?.(v);
1783
+ }
1784
+ },
1672
1785
  onItemHighlighted: isVirtualized ? (item, { reason, index }) => {
1673
1786
  const virt = virtualizerRef.current;
1674
1787
  if (!item || !virt) return;
@@ -1688,15 +1801,17 @@ function MultiCombobox(props) {
1688
1801
  hasSentinels ? handleValueChange : handleSimpleValueChange
1689
1802
  ),
1690
1803
  itemToStringLabel: (item) => {
1691
- if (!item || isGroupHeaderSentinel2(item) || isSelectAllSentinel2(item))
1804
+ if (!item || isGroupHeaderSentinel2(item) || isSelectAllSentinel2(item) || isCreatableSentinel(item))
1692
1805
  return "";
1693
1806
  return itemToString(item);
1694
1807
  },
1695
1808
  isItemEqualToValue: (a, b) => {
1809
+ if (isCreatableSentinel(a) && isCreatableSentinel(b))
1810
+ return a.label === b.label;
1696
1811
  if (isGroupHeaderSentinel2(a) && isGroupHeaderSentinel2(b))
1697
1812
  return a.groupName === b.groupName;
1698
1813
  if (isSelectAllSentinel2(a) && isSelectAllSentinel2(b)) return true;
1699
- if (!isGroupHeaderSentinel2(a) && !isSelectAllSentinel2(a) && !isGroupHeaderSentinel2(b) && !isSelectAllSentinel2(b))
1814
+ if (!isGroupHeaderSentinel2(a) && !isSelectAllSentinel2(a) && !isCreatableSentinel(a) && !isGroupHeaderSentinel2(b) && !isSelectAllSentinel2(b) && !isCreatableSentinel(b))
1700
1815
  return a.id === b.id;
1701
1816
  return false;
1702
1817
  },
@@ -1729,7 +1844,8 @@ function MultiCombobox(props) {
1729
1844
  ComboboxTokenInput,
1730
1845
  {
1731
1846
  id,
1732
- placeholder: value.length > 0 ? "" : placeholder
1847
+ placeholder: value.length > 0 ? "" : placeholder,
1848
+ "aria-describedby": ariaDescribedBy
1733
1849
  }
1734
1850
  ),
1735
1851
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxActionButtons, { children: [
@@ -1766,37 +1882,55 @@ function MultiCombobox(props) {
1766
1882
  itemToString,
1767
1883
  inputType,
1768
1884
  renderItem,
1769
- renderGroupHeading
1885
+ renderGroupHeading,
1886
+ renderCreatableItem: creatableProp ? (sentinel, style, index, measureRef) => renderCreatableItem(
1887
+ sentinel,
1888
+ style,
1889
+ index,
1890
+ measureRef
1891
+ ) : void 0
1770
1892
  }
1771
- ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(React9.Fragment, { children: [
1772
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxGroup, { items: group.items, children: [
1773
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(group.value) : group.value }),
1774
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_combobox4.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1775
- ComboboxItem_default,
1776
- {
1777
- value: item,
1778
- itemId: String(item.id),
1779
- label: itemToString(item),
1780
- disabled: item.disabled,
1781
- inputType,
1782
- renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
1783
- },
1784
- item.id
1785
- ) })
1786
- ] }),
1787
- index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxSeparator, {})
1788
- ] }, group.value) : (item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1789
- ComboboxItem_default,
1790
- {
1791
- value: item,
1792
- itemId: String(item.id),
1793
- label: itemToString(item),
1794
- disabled: item.disabled,
1795
- inputType,
1796
- renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
1797
- },
1798
- item.id
1799
- )
1893
+ ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
1894
+ if (isCreatableSentinel(group)) {
1895
+ return renderCreatableItem(group);
1896
+ }
1897
+ const g = group;
1898
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(React9.Fragment, { children: [
1899
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxGroup, { items: g.items, children: [
1900
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
1901
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_combobox4.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1902
+ ComboboxItem_default,
1903
+ {
1904
+ value: item,
1905
+ itemId: String(item.id),
1906
+ label: itemToString(item),
1907
+ disabled: item.disabled,
1908
+ inputType,
1909
+ renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
1910
+ },
1911
+ item.id
1912
+ ) })
1913
+ ] }),
1914
+ index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxSeparator, {})
1915
+ ] }, g.value);
1916
+ } : (item) => {
1917
+ if (isCreatableSentinel(item)) {
1918
+ return renderCreatableItem(item);
1919
+ }
1920
+ const dataItem = item;
1921
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1922
+ ComboboxItem_default,
1923
+ {
1924
+ value: dataItem,
1925
+ itemId: String(dataItem.id),
1926
+ label: itemToString(dataItem),
1927
+ disabled: dataItem.disabled,
1928
+ inputType,
1929
+ renderItem: renderItem ? () => renderItem(dataItem) : () => itemToString(dataItem)
1930
+ },
1931
+ dataItem.id
1932
+ );
1933
+ }
1800
1934
  }
1801
1935
  )
1802
1936
  ]
@@ -1824,6 +1958,7 @@ function SingleSearchableSelect(props) {
1824
1958
  loadingText = "Loading...",
1825
1959
  filter
1826
1960
  } = props;
1961
+ const ariaDescribedBy = props["aria-describedby"];
1827
1962
  const isChildrenMode = "children" in props && props.children != null;
1828
1963
  const data = isChildrenMode ? [] : props.data;
1829
1964
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1898,7 +2033,7 @@ function SingleSearchableSelect(props) {
1898
2033
  }
1899
2034
  } : void 0,
1900
2035
  children: [
1901
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SearchableSelectTrigger, { id, children: [
2036
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SearchableSelectTrigger, { id, "aria-describedby": ariaDescribedBy, children: [
1902
2037
  /* @__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 }) }),
1903
2038
  /* @__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, {}) }) })
1904
2039
  ] }),
@@ -1995,6 +2130,7 @@ function SingleSearchableSelect(props) {
1995
2130
  var React11 = __toESM(require("react"));
1996
2131
  var import_combobox6 = require("@base-ui/react/combobox");
1997
2132
  var import_react_virtual5 = require("@tanstack/react-virtual");
2133
+ var import_seeds_react_icon4 = __toESM(require("@sproutsocial/seeds-react-icon"));
1998
2134
  var import_styled_components7 = __toESM(require("styled-components"));
1999
2135
  var import_jsx_runtime11 = require("react/jsx-runtime");
2000
2136
  var SelectionText2 = import_styled_components7.default.span`
@@ -2023,6 +2159,7 @@ function MultiSearchableSelect(props) {
2023
2159
  loadingText = "Loading...",
2024
2160
  filter
2025
2161
  } = props;
2162
+ const ariaDescribedBy = props["aria-describedby"];
2026
2163
  const isChildrenMode = "children" in props && props.children != null;
2027
2164
  const data = isChildrenMode ? [] : props.data;
2028
2165
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -2037,12 +2174,16 @@ function MultiSearchableSelect(props) {
2037
2174
  const selectHeadings = isChildrenMode ? false : props.selectHeadings ?? false;
2038
2175
  const selectAll = isChildrenMode ? false : props.selectAll ?? false;
2039
2176
  const isVirtualized = isChildrenMode ? false : props.isVirtualized ?? false;
2177
+ const creatableProp = isChildrenMode ? false : props.creatable ?? false;
2178
+ const onCreateProp = isChildrenMode ? void 0 : props.onCreate;
2040
2179
  const children = isChildrenMode ? props.children : void 0;
2041
2180
  const selectedItemIds = props.selectedItemIds;
2042
2181
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
2043
2182
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
2044
2183
  const { containerRef, portalContainer } = useSeedsPortalContainer();
2045
2184
  const [open, setOpen] = React11.useState(false);
2185
+ const [internalInputValue, setInternalInputValue] = React11.useState("");
2186
+ const skipNextInputChangeRef = React11.useRef(false);
2046
2187
  const virtualizerRef = React11.useRef(null);
2047
2188
  const isControlled = selectedItemIds !== void 0;
2048
2189
  const idsToItems = React11.useCallback(
@@ -2061,6 +2202,18 @@ function MultiSearchableSelect(props) {
2061
2202
  () => groupBy ? groupItems(visibleData, groupBy) : null,
2062
2203
  [visibleData, groupBy]
2063
2204
  );
2205
+ const currentInputValue = internalInputValue;
2206
+ const creatableSentinel = React11.useMemo(() => {
2207
+ if (!creatableProp) return null;
2208
+ const trimmed = currentInputValue.trim();
2209
+ if (!trimmed) return null;
2210
+ const lowered = trimmed.toLocaleLowerCase();
2211
+ const exactExists = data.some(
2212
+ (d) => itemToString(d).trim().toLocaleLowerCase() === lowered
2213
+ );
2214
+ if (exactExists) return null;
2215
+ return makeCreatableSentinel(trimmed);
2216
+ }, [creatableProp, currentInputValue, data, itemToString]);
2064
2217
  const flatItems = React11.useMemo(() => {
2065
2218
  if (!groups || !selectHeadings && !selectAll) return null;
2066
2219
  const rows = [];
@@ -2077,10 +2230,21 @@ function MultiSearchableSelect(props) {
2077
2230
  onSelectedItemIdsChange(items.map((item) => item.id));
2078
2231
  }
2079
2232
  function handleValueChange(next) {
2233
+ const creatableClicked = next.find(isCreatableSentinel);
2234
+ if (creatableClicked) {
2235
+ const newItem = onCreateProp?.(creatableClicked.label);
2236
+ const realItems2 = next.filter(
2237
+ (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v) && !isCreatableSentinel(v)
2238
+ );
2239
+ setSelectedItems(newItem ? [...realItems2, newItem] : realItems2);
2240
+ skipNextInputChangeRef.current = true;
2241
+ setInternalInputValue("");
2242
+ return;
2243
+ }
2080
2244
  const selectAllClicked = next.filter(isSelectAllSentinel3);
2081
2245
  const groupSentinels = next.filter(isGroupHeaderSentinel3);
2082
2246
  const realItems = next.filter(
2083
- (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v)
2247
+ (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v) && !isCreatableSentinel(v)
2084
2248
  );
2085
2249
  if (selectAllClicked.length > 0) {
2086
2250
  const allSelected = data.every(
@@ -2114,6 +2278,15 @@ function MultiSearchableSelect(props) {
2114
2278
  setSelectedItems(updated);
2115
2279
  }
2116
2280
  function handleSimpleValueChange(newItems) {
2281
+ const creatableClicked = newItems.find(isCreatableSentinel);
2282
+ if (creatableClicked) {
2283
+ const newItem = onCreateProp?.(creatableClicked.label);
2284
+ const realItems = newItems.filter((v) => !isCreatableSentinel(v));
2285
+ setSelectedItems(newItem ? [...realItems, newItem] : realItems);
2286
+ skipNextInputChangeRef.current = true;
2287
+ setInternalInputValue("");
2288
+ return;
2289
+ }
2117
2290
  setSelectedItems(newItems);
2118
2291
  }
2119
2292
  function renderSentinelRow(row) {
@@ -2144,6 +2317,9 @@ function MultiSearchableSelect(props) {
2144
2317
  renderGroupHeading ? renderGroupHeading(row.groupName) : row.groupName
2145
2318
  ] }, `__header-${row.groupName}`);
2146
2319
  }
2320
+ if (isCreatableSentinel(row)) {
2321
+ return renderCreatableItem(row);
2322
+ }
2147
2323
  const item = row;
2148
2324
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2149
2325
  ComboboxItem_default,
@@ -2158,7 +2334,28 @@ function MultiSearchableSelect(props) {
2158
2334
  item.id
2159
2335
  );
2160
2336
  }
2161
- const rootItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
2337
+ function renderCreatableItem(sentinel, style, index, measureRef) {
2338
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2339
+ ComboboxItem_default,
2340
+ {
2341
+ value: sentinel,
2342
+ itemId: "__creatable",
2343
+ label: `Create "${sentinel.label}"`,
2344
+ inputType: "none",
2345
+ renderItem: () => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2346
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_seeds_react_icon4.default, { name: "plus-outline", size: "mini" }),
2347
+ `Create "${sentinel.label}"`
2348
+ ] }),
2349
+ style,
2350
+ index,
2351
+ "data-index": index,
2352
+ ref: measureRef
2353
+ },
2354
+ "__creatable"
2355
+ );
2356
+ }
2357
+ const baseItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
2358
+ const rootItems = creatableSentinel && Array.isArray(baseItems) ? [...baseItems, creatableSentinel] : baseItems;
2162
2359
  const hasSentinels = selectAll || selectHeadings;
2163
2360
  const rootValue = hasSentinels ? [...value] : value;
2164
2361
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Field, { children: [
@@ -2169,7 +2366,23 @@ function MultiSearchableSelect(props) {
2169
2366
  multiple: true,
2170
2367
  id,
2171
2368
  virtualized: isVirtualized,
2172
- filter,
2369
+ filter: creatableProp ? (item, query) => {
2370
+ if (isCreatableSentinel(item)) return true;
2371
+ if (filter) return filter(item, query);
2372
+ if (isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item))
2373
+ return true;
2374
+ const label = itemToString(item);
2375
+ return label.toLowerCase().includes(query.toLowerCase());
2376
+ } : filter,
2377
+ inputValue: internalInputValue,
2378
+ onInputValueChange: (v, eventDetails) => {
2379
+ if (eventDetails.reason === "input-clear" && open) return;
2380
+ if (skipNextInputChangeRef.current) {
2381
+ skipNextInputChangeRef.current = false;
2382
+ return;
2383
+ }
2384
+ setInternalInputValue(v);
2385
+ },
2173
2386
  open,
2174
2387
  disabled: props.disabled,
2175
2388
  onOpenChange: setOpen,
@@ -2192,34 +2405,43 @@ function MultiSearchableSelect(props) {
2192
2405
  hasSentinels ? handleValueChange : handleSimpleValueChange
2193
2406
  ),
2194
2407
  itemToStringLabel: (item) => {
2195
- if (!item || isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item))
2408
+ if (!item || isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item) || isCreatableSentinel(item))
2196
2409
  return "";
2197
2410
  return itemToString(item);
2198
2411
  },
2199
2412
  isItemEqualToValue: (a, b) => {
2413
+ if (isCreatableSentinel(a) && isCreatableSentinel(b))
2414
+ return a.label === b.label;
2200
2415
  if (isGroupHeaderSentinel3(a) && isGroupHeaderSentinel3(b))
2201
2416
  return a.groupName === b.groupName;
2202
2417
  if (isSelectAllSentinel3(a) && isSelectAllSentinel3(b)) return true;
2203
- if (!isGroupHeaderSentinel3(a) && !isSelectAllSentinel3(a) && !isGroupHeaderSentinel3(b) && !isSelectAllSentinel3(b))
2418
+ if (!isGroupHeaderSentinel3(a) && !isSelectAllSentinel3(a) && !isCreatableSentinel(a) && !isGroupHeaderSentinel3(b) && !isSelectAllSentinel3(b) && !isCreatableSentinel(b))
2204
2419
  return a.id === b.id;
2205
2420
  return false;
2206
2421
  },
2207
2422
  items: rootItems,
2208
2423
  children: [
2209
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(SearchableSelectTokenTrigger, { id, children: [
2210
- renderSelection ? renderSelection(value) : value.length > 0 ? (() => {
2211
- const visibleItems = maxSelections != null ? value.slice(0, maxSelections) : value;
2212
- const overflowCount = maxSelections != null && value.length > maxSelections ? value.length - maxSelections : 0;
2213
- const text = visibleItems.map(
2214
- (item) => customRenderSelections ? customRenderSelections(item) : itemToString(item)
2215
- ).join(", ");
2216
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(SelectionText2, { children: [
2217
- text,
2218
- overflowCount > 0 ? `, +${overflowCount}` : ""
2219
- ] });
2220
- })() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SearchableSelectPlaceholder, { children: placeholder }),
2221
- /* @__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, {}) }) })
2222
- ] }),
2424
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2425
+ SearchableSelectTokenTrigger,
2426
+ {
2427
+ id,
2428
+ "aria-describedby": ariaDescribedBy,
2429
+ children: [
2430
+ renderSelection ? renderSelection(value) : value.length > 0 ? (() => {
2431
+ const visibleItems = maxSelections != null ? value.slice(0, maxSelections) : value;
2432
+ const overflowCount = maxSelections != null && value.length > maxSelections ? value.length - maxSelections : 0;
2433
+ const text = visibleItems.map(
2434
+ (item) => customRenderSelections ? customRenderSelections(item) : itemToString(item)
2435
+ ).join(", ");
2436
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(SelectionText2, { children: [
2437
+ text,
2438
+ overflowCount > 0 ? `, +${overflowCount}` : ""
2439
+ ] });
2440
+ })() : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SearchableSelectPlaceholder, { children: placeholder }),
2441
+ /* @__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, {}) }) })
2442
+ ]
2443
+ }
2444
+ ),
2223
2445
  /* @__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)(
2224
2446
  SearchableSelectPopup,
2225
2447
  {
@@ -2256,37 +2478,55 @@ function MultiSearchableSelect(props) {
2256
2478
  itemToString,
2257
2479
  inputType,
2258
2480
  renderItem,
2259
- renderGroupHeading
2481
+ renderGroupHeading,
2482
+ renderCreatableItem: creatableProp ? (sentinel, style, index, measureRef) => renderCreatableItem(
2483
+ sentinel,
2484
+ style,
2485
+ index,
2486
+ measureRef
2487
+ ) : void 0
2260
2488
  }
2261
- ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(React11.Fragment, { children: [
2262
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(ComboboxGroup, { items: group.items, children: [
2263
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(group.value) : group.value }),
2264
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_combobox6.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2265
- ComboboxItem_default,
2266
- {
2267
- value: item,
2268
- itemId: String(item.id),
2269
- label: itemToString(item),
2270
- disabled: item.disabled,
2271
- inputType,
2272
- renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
2273
- },
2274
- item.id
2275
- ) })
2276
- ] }),
2277
- index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComboboxSeparator, {})
2278
- ] }, group.value) : (item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2279
- ComboboxItem_default,
2280
- {
2281
- value: item,
2282
- itemId: String(item.id),
2283
- label: itemToString(item),
2284
- disabled: item.disabled,
2285
- inputType,
2286
- renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
2287
- },
2288
- item.id
2289
- )
2489
+ ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
2490
+ if (isCreatableSentinel(group)) {
2491
+ return renderCreatableItem(group);
2492
+ }
2493
+ const g = group;
2494
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(React11.Fragment, { children: [
2495
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(ComboboxGroup, { items: g.items, children: [
2496
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
2497
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_combobox6.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2498
+ ComboboxItem_default,
2499
+ {
2500
+ value: item,
2501
+ itemId: String(item.id),
2502
+ label: itemToString(item),
2503
+ disabled: item.disabled,
2504
+ inputType,
2505
+ renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
2506
+ },
2507
+ item.id
2508
+ ) })
2509
+ ] }),
2510
+ index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComboboxSeparator, {})
2511
+ ] }, g.value);
2512
+ } : (item) => {
2513
+ if (isCreatableSentinel(item)) {
2514
+ return renderCreatableItem(item);
2515
+ }
2516
+ const dataItem = item;
2517
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2518
+ ComboboxItem_default,
2519
+ {
2520
+ value: dataItem,
2521
+ itemId: String(dataItem.id),
2522
+ label: itemToString(dataItem),
2523
+ disabled: dataItem.disabled,
2524
+ inputType,
2525
+ renderItem: renderItem ? () => renderItem(dataItem) : () => itemToString(dataItem)
2526
+ },
2527
+ dataItem.id
2528
+ );
2529
+ }
2290
2530
  }
2291
2531
  )
2292
2532
  ]