@sproutsocial/seeds-react-menu 1.12.2 → 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.
@@ -10,26 +10,26 @@ $ tsup --dts
10
10
  ESM Build start
11
11
  CJS dist/index.js 92.65 KB
12
12
  CJS dist/v2/index.js 73.18 KB
13
- CJS dist/v3/index.js 99.79 KB
13
+ CJS dist/v3/index.js 104.35 KB
14
14
  CJS dist/index.js.map 180.28 KB
15
15
  CJS dist/v2/index.js.map 152.19 KB
16
- CJS dist/v3/index.js.map 173.17 KB
17
- CJS ⚡️ Build success in 91ms
16
+ CJS dist/v3/index.js.map 181.62 KB
17
+ CJS ⚡️ Build success in 64ms
18
18
  ESM dist/esm/index.js 73.60 KB
19
- ESM dist/esm/v3/index.js 88.52 KB
19
+ ESM dist/esm/v3/index.js 92.96 KB
20
20
  ESM dist/esm/chunk-ROQATIB7.js 9.15 KB
21
21
  ESM dist/esm/v2/index.js 62.63 KB
22
22
  ESM dist/esm/index.js.map 156.29 KB
23
- ESM dist/esm/v3/index.js.map 173.24 KB
23
+ ESM dist/esm/v3/index.js.map 181.70 KB
24
24
  ESM dist/esm/chunk-ROQATIB7.js.map 22.93 KB
25
25
  ESM dist/esm/v2/index.js.map 132.57 KB
26
- ESM ⚡️ Build success in 91ms
26
+ ESM ⚡️ Build success in 65ms
27
27
  DTS Build start
28
- DTS ⚡️ Build success in 6715ms
28
+ DTS ⚡️ Build success in 6525ms
29
29
  DTS dist/index.d.ts 39.11 KB
30
30
  DTS dist/v2/index.d.ts 5.55 KB
31
- DTS dist/v3/index.d.ts 18.28 KB
31
+ DTS dist/v3/index.d.ts 18.39 KB
32
32
  DTS dist/index.d.mts 39.11 KB
33
33
  DTS dist/v2/index.d.mts 5.55 KB
34
- DTS dist/v3/index.d.mts 18.28 KB
35
- Done in 7.46s.
34
+ DTS dist/v3/index.d.mts 18.39 KB
35
+ Done in 7.26s.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @sproutsocial/seeds-react-menu
2
2
 
3
+ ## 1.12.3
4
+
5
+ ### Patch Changes
6
+
7
+ - c806305: Bugfix for selecting and searching, add creatable to SearchableSelect
8
+
3
9
  ## 1.12.2
4
10
 
5
11
  ### Patch Changes
@@ -1692,15 +1692,23 @@ function MultiCombobox(props) {
1692
1692
  const label = itemToString(item);
1693
1693
  return label.toLowerCase().includes(query.toLowerCase());
1694
1694
  } : filter,
1695
- inputValue: creatableProp ? currentInputValue : inputValue,
1696
- onInputValueChange: creatableProp ? (v) => {
1697
- if (skipNextInputChangeRef.current) {
1698
- skipNextInputChangeRef.current = false;
1699
- return;
1695
+ inputValue: creatableProp ? currentInputValue : inputValue ?? internalInputValue,
1696
+ onInputValueChange: (v, eventDetails) => {
1697
+ if (eventDetails.reason === "input-clear" && open) return;
1698
+ if (creatableProp) {
1699
+ if (skipNextInputChangeRef.current) {
1700
+ skipNextInputChangeRef.current = false;
1701
+ return;
1702
+ }
1703
+ setInternalInputValue(v);
1704
+ onInputValueChange?.(v);
1705
+ } else {
1706
+ if (inputValue === void 0) {
1707
+ setInternalInputValue(v);
1708
+ }
1709
+ onInputValueChange?.(v);
1700
1710
  }
1701
- setInternalInputValue(v);
1702
- onInputValueChange?.(v);
1703
- } : onInputValueChange,
1711
+ },
1704
1712
  onItemHighlighted: isVirtualized ? (item, { reason, index }) => {
1705
1713
  const virt = virtualizerRef.current;
1706
1714
  if (!item || !virt) return;
@@ -2049,8 +2057,9 @@ function SingleSearchableSelect(props) {
2049
2057
  import * as React11 from "react";
2050
2058
  import { Combobox as Combobox6 } from "@base-ui/react/combobox";
2051
2059
  import "@tanstack/react-virtual";
2060
+ import Icon4 from "@sproutsocial/seeds-react-icon";
2052
2061
  import styled7 from "styled-components";
2053
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2062
+ import { Fragment as Fragment10, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2054
2063
  var SelectionText2 = styled7.span`
2055
2064
  flex: 1;
2056
2065
  overflow: hidden;
@@ -2092,12 +2101,16 @@ function MultiSearchableSelect(props) {
2092
2101
  const selectHeadings = isChildrenMode ? false : props.selectHeadings ?? false;
2093
2102
  const selectAll = isChildrenMode ? false : props.selectAll ?? false;
2094
2103
  const isVirtualized = isChildrenMode ? false : props.isVirtualized ?? false;
2104
+ const creatableProp = isChildrenMode ? false : props.creatable ?? false;
2105
+ const onCreateProp = isChildrenMode ? void 0 : props.onCreate;
2095
2106
  const children = isChildrenMode ? props.children : void 0;
2096
2107
  const selectedItemIds = props.selectedItemIds;
2097
2108
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
2098
2109
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
2099
2110
  const { containerRef, portalContainer } = useSeedsPortalContainer();
2100
2111
  const [open, setOpen] = React11.useState(false);
2112
+ const [internalInputValue, setInternalInputValue] = React11.useState("");
2113
+ const skipNextInputChangeRef = React11.useRef(false);
2101
2114
  const virtualizerRef = React11.useRef(null);
2102
2115
  const isControlled = selectedItemIds !== void 0;
2103
2116
  const idsToItems = React11.useCallback(
@@ -2116,6 +2129,18 @@ function MultiSearchableSelect(props) {
2116
2129
  () => groupBy ? groupItems(visibleData, groupBy) : null,
2117
2130
  [visibleData, groupBy]
2118
2131
  );
2132
+ const currentInputValue = internalInputValue;
2133
+ const creatableSentinel = React11.useMemo(() => {
2134
+ if (!creatableProp) return null;
2135
+ const trimmed = currentInputValue.trim();
2136
+ if (!trimmed) return null;
2137
+ const lowered = trimmed.toLocaleLowerCase();
2138
+ const exactExists = data.some(
2139
+ (d) => itemToString(d).trim().toLocaleLowerCase() === lowered
2140
+ );
2141
+ if (exactExists) return null;
2142
+ return makeCreatableSentinel(trimmed);
2143
+ }, [creatableProp, currentInputValue, data, itemToString]);
2119
2144
  const flatItems = React11.useMemo(() => {
2120
2145
  if (!groups || !selectHeadings && !selectAll) return null;
2121
2146
  const rows = [];
@@ -2132,10 +2157,21 @@ function MultiSearchableSelect(props) {
2132
2157
  onSelectedItemIdsChange(items.map((item) => item.id));
2133
2158
  }
2134
2159
  function handleValueChange(next) {
2160
+ const creatableClicked = next.find(isCreatableSentinel);
2161
+ if (creatableClicked) {
2162
+ const newItem = onCreateProp?.(creatableClicked.label);
2163
+ const realItems2 = next.filter(
2164
+ (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v) && !isCreatableSentinel(v)
2165
+ );
2166
+ setSelectedItems(newItem ? [...realItems2, newItem] : realItems2);
2167
+ skipNextInputChangeRef.current = true;
2168
+ setInternalInputValue("");
2169
+ return;
2170
+ }
2135
2171
  const selectAllClicked = next.filter(isSelectAllSentinel3);
2136
2172
  const groupSentinels = next.filter(isGroupHeaderSentinel3);
2137
2173
  const realItems = next.filter(
2138
- (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v)
2174
+ (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v) && !isCreatableSentinel(v)
2139
2175
  );
2140
2176
  if (selectAllClicked.length > 0) {
2141
2177
  const allSelected = data.every(
@@ -2169,6 +2205,15 @@ function MultiSearchableSelect(props) {
2169
2205
  setSelectedItems(updated);
2170
2206
  }
2171
2207
  function handleSimpleValueChange(newItems) {
2208
+ const creatableClicked = newItems.find(isCreatableSentinel);
2209
+ if (creatableClicked) {
2210
+ const newItem = onCreateProp?.(creatableClicked.label);
2211
+ const realItems = newItems.filter((v) => !isCreatableSentinel(v));
2212
+ setSelectedItems(newItem ? [...realItems, newItem] : realItems);
2213
+ skipNextInputChangeRef.current = true;
2214
+ setInternalInputValue("");
2215
+ return;
2216
+ }
2172
2217
  setSelectedItems(newItems);
2173
2218
  }
2174
2219
  function renderSentinelRow(row) {
@@ -2199,6 +2244,9 @@ function MultiSearchableSelect(props) {
2199
2244
  renderGroupHeading ? renderGroupHeading(row.groupName) : row.groupName
2200
2245
  ] }, `__header-${row.groupName}`);
2201
2246
  }
2247
+ if (isCreatableSentinel(row)) {
2248
+ return renderCreatableItem(row);
2249
+ }
2202
2250
  const item = row;
2203
2251
  return /* @__PURE__ */ jsx11(
2204
2252
  ComboboxItem_default,
@@ -2213,7 +2261,28 @@ function MultiSearchableSelect(props) {
2213
2261
  item.id
2214
2262
  );
2215
2263
  }
2216
- const rootItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
2264
+ function renderCreatableItem(sentinel, style, index, measureRef) {
2265
+ return /* @__PURE__ */ jsx11(
2266
+ ComboboxItem_default,
2267
+ {
2268
+ value: sentinel,
2269
+ itemId: "__creatable",
2270
+ label: `Create "${sentinel.label}"`,
2271
+ inputType: "none",
2272
+ renderItem: () => /* @__PURE__ */ jsxs9(Fragment10, { children: [
2273
+ /* @__PURE__ */ jsx11(Icon4, { name: "plus-outline", size: "mini" }),
2274
+ `Create "${sentinel.label}"`
2275
+ ] }),
2276
+ style,
2277
+ index,
2278
+ "data-index": index,
2279
+ ref: measureRef
2280
+ },
2281
+ "__creatable"
2282
+ );
2283
+ }
2284
+ const baseItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
2285
+ const rootItems = creatableSentinel && Array.isArray(baseItems) ? [...baseItems, creatableSentinel] : baseItems;
2217
2286
  const hasSentinels = selectAll || selectHeadings;
2218
2287
  const rootValue = hasSentinels ? [...value] : value;
2219
2288
  return /* @__PURE__ */ jsxs9(Field, { children: [
@@ -2224,7 +2293,23 @@ function MultiSearchableSelect(props) {
2224
2293
  multiple: true,
2225
2294
  id,
2226
2295
  virtualized: isVirtualized,
2227
- filter,
2296
+ filter: creatableProp ? (item, query) => {
2297
+ if (isCreatableSentinel(item)) return true;
2298
+ if (filter) return filter(item, query);
2299
+ if (isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item))
2300
+ return true;
2301
+ const label = itemToString(item);
2302
+ return label.toLowerCase().includes(query.toLowerCase());
2303
+ } : filter,
2304
+ inputValue: internalInputValue,
2305
+ onInputValueChange: (v, eventDetails) => {
2306
+ if (eventDetails.reason === "input-clear" && open) return;
2307
+ if (skipNextInputChangeRef.current) {
2308
+ skipNextInputChangeRef.current = false;
2309
+ return;
2310
+ }
2311
+ setInternalInputValue(v);
2312
+ },
2228
2313
  open,
2229
2314
  disabled: props.disabled,
2230
2315
  onOpenChange: setOpen,
@@ -2247,15 +2332,17 @@ function MultiSearchableSelect(props) {
2247
2332
  hasSentinels ? handleValueChange : handleSimpleValueChange
2248
2333
  ),
2249
2334
  itemToStringLabel: (item) => {
2250
- if (!item || isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item))
2335
+ if (!item || isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item) || isCreatableSentinel(item))
2251
2336
  return "";
2252
2337
  return itemToString(item);
2253
2338
  },
2254
2339
  isItemEqualToValue: (a, b) => {
2340
+ if (isCreatableSentinel(a) && isCreatableSentinel(b))
2341
+ return a.label === b.label;
2255
2342
  if (isGroupHeaderSentinel3(a) && isGroupHeaderSentinel3(b))
2256
2343
  return a.groupName === b.groupName;
2257
2344
  if (isSelectAllSentinel3(a) && isSelectAllSentinel3(b)) return true;
2258
- if (!isGroupHeaderSentinel3(a) && !isSelectAllSentinel3(a) && !isGroupHeaderSentinel3(b) && !isSelectAllSentinel3(b))
2345
+ if (!isGroupHeaderSentinel3(a) && !isSelectAllSentinel3(a) && !isCreatableSentinel(a) && !isGroupHeaderSentinel3(b) && !isSelectAllSentinel3(b) && !isCreatableSentinel(b))
2259
2346
  return a.id === b.id;
2260
2347
  return false;
2261
2348
  },
@@ -2318,37 +2405,55 @@ function MultiSearchableSelect(props) {
2318
2405
  itemToString,
2319
2406
  inputType,
2320
2407
  renderItem,
2321
- renderGroupHeading
2408
+ renderGroupHeading,
2409
+ renderCreatableItem: creatableProp ? (sentinel, style, index, measureRef) => renderCreatableItem(
2410
+ sentinel,
2411
+ style,
2412
+ index,
2413
+ measureRef
2414
+ ) : void 0
2322
2415
  }
2323
- ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => /* @__PURE__ */ jsxs9(React11.Fragment, { children: [
2324
- /* @__PURE__ */ jsxs9(ComboboxGroup, { items: group.items, children: [
2325
- /* @__PURE__ */ jsx11(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(group.value) : group.value }),
2326
- /* @__PURE__ */ jsx11(Combobox6.Collection, { children: (item) => /* @__PURE__ */ jsx11(
2327
- ComboboxItem_default,
2328
- {
2329
- value: item,
2330
- itemId: String(item.id),
2331
- label: itemToString(item),
2332
- disabled: item.disabled,
2333
- inputType,
2334
- renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
2335
- },
2336
- item.id
2337
- ) })
2338
- ] }),
2339
- index < groups.length - 1 && /* @__PURE__ */ jsx11(ComboboxSeparator, {})
2340
- ] }, group.value) : (item) => /* @__PURE__ */ jsx11(
2341
- ComboboxItem_default,
2342
- {
2343
- value: item,
2344
- itemId: String(item.id),
2345
- label: itemToString(item),
2346
- disabled: item.disabled,
2347
- inputType,
2348
- renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
2349
- },
2350
- item.id
2351
- )
2416
+ ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
2417
+ if (isCreatableSentinel(group)) {
2418
+ return renderCreatableItem(group);
2419
+ }
2420
+ const g = group;
2421
+ return /* @__PURE__ */ jsxs9(React11.Fragment, { children: [
2422
+ /* @__PURE__ */ jsxs9(ComboboxGroup, { items: g.items, children: [
2423
+ /* @__PURE__ */ jsx11(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
2424
+ /* @__PURE__ */ jsx11(Combobox6.Collection, { children: (item) => /* @__PURE__ */ jsx11(
2425
+ ComboboxItem_default,
2426
+ {
2427
+ value: item,
2428
+ itemId: String(item.id),
2429
+ label: itemToString(item),
2430
+ disabled: item.disabled,
2431
+ inputType,
2432
+ renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
2433
+ },
2434
+ item.id
2435
+ ) })
2436
+ ] }),
2437
+ index < groups.length - 1 && /* @__PURE__ */ jsx11(ComboboxSeparator, {})
2438
+ ] }, g.value);
2439
+ } : (item) => {
2440
+ if (isCreatableSentinel(item)) {
2441
+ return renderCreatableItem(item);
2442
+ }
2443
+ const dataItem = item;
2444
+ return /* @__PURE__ */ jsx11(
2445
+ ComboboxItem_default,
2446
+ {
2447
+ value: dataItem,
2448
+ itemId: String(dataItem.id),
2449
+ label: itemToString(dataItem),
2450
+ disabled: dataItem.disabled,
2451
+ inputType,
2452
+ renderItem: renderItem ? () => renderItem(dataItem) : () => itemToString(dataItem)
2453
+ },
2454
+ dataItem.id
2455
+ );
2456
+ }
2352
2457
  }
2353
2458
  )
2354
2459
  ]