@sproutsocial/seeds-react-menu 1.12.2 → 1.13.0

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.
@@ -137,10 +137,10 @@ import { Select as Select2 } from "@base-ui/react/select";
137
137
  import styled2 from "styled-components";
138
138
  import { focusRing } from "@sproutsocial/seeds-react-mixins";
139
139
  var Field = styled2.div`
140
- display: flex;
140
+ display: ${({ $fullWidth }) => $fullWidth === false ? "inline-flex" : "flex"};
141
141
  flex-direction: column;
142
142
  gap: ${({ theme }) => theme.space[200]};
143
- width: 100%;
143
+ ${({ $fullWidth }) => $fullWidth !== false && "width: 100%;"}
144
144
  `;
145
145
  var SelectLabel = styled2(Select2.Label)`
146
146
  font-size: ${({ theme }) => theme.typography[200].fontSize};
@@ -290,7 +290,7 @@ var StyledValue = styled4(Select3.Value)`
290
290
  }
291
291
  `;
292
292
  function SingleSelect(props) {
293
- const { id, placeholder, includePlaceholderItem } = props;
293
+ const { id, placeholder, includePlaceholderItem, fullWidth = true } = props;
294
294
  const ariaDescribedBy = props["aria-describedby"];
295
295
  const isChildrenMode = "children" in props && props.children != null;
296
296
  const selectedItemId = props.selectedItemId;
@@ -338,7 +338,7 @@ function SingleSelect(props) {
338
338
  }
339
339
  }
340
340
  }
341
- return /* @__PURE__ */ jsxs2(Field, { children: [
341
+ return /* @__PURE__ */ jsxs2(Field, { $fullWidth: fullWidth, children: [
342
342
  /* @__PURE__ */ jsx3("div", { ref: containerRef, style: { position: "relative" } }),
343
343
  /* @__PURE__ */ jsxs2(
344
344
  Select3.Root,
@@ -420,7 +420,7 @@ var Placeholder = styled5.div`
420
420
  margin: 2px 8px 0px 0px;
421
421
  `;
422
422
  function MultiSelect(props) {
423
- const { id, placeholder = "Select..." } = props;
423
+ const { id, placeholder = "Select...", fullWidth = true } = props;
424
424
  const ariaDescribedBy = props["aria-describedby"];
425
425
  const isChildrenMode = "children" in props && props.children != null;
426
426
  const data = isChildrenMode ? [] : props.data;
@@ -466,7 +466,7 @@ function MultiSelect(props) {
466
466
  onSelectedItemIdsChange(ids);
467
467
  }
468
468
  }
469
- return /* @__PURE__ */ jsxs3(Field, { children: [
469
+ return /* @__PURE__ */ jsxs3(Field, { $fullWidth: fullWidth, children: [
470
470
  /* @__PURE__ */ jsx4("div", { ref: containerRef, style: { position: "relative" } }),
471
471
  /* @__PURE__ */ jsxs3(
472
472
  Select4.Root,
@@ -1275,7 +1275,8 @@ function SingleCombobox(props) {
1275
1275
  id,
1276
1276
  placeholder = "Search...",
1277
1277
  emptyText = "No results found.",
1278
- filter
1278
+ filter,
1279
+ fullWidth = true
1279
1280
  } = props;
1280
1281
  const ariaDescribedBy = props["aria-describedby"];
1281
1282
  const isChildrenMode = "children" in props && props.children != null;
@@ -1317,7 +1318,7 @@ function SingleCombobox(props) {
1317
1318
  () => groupBy ? groupItems(data, groupBy) : null,
1318
1319
  [data, groupBy]
1319
1320
  );
1320
- return /* @__PURE__ */ jsxs6(Field, { children: [
1321
+ return /* @__PURE__ */ jsxs6(Field, { $fullWidth: fullWidth, children: [
1321
1322
  /* @__PURE__ */ jsx8("div", { ref: containerRef, style: { position: "relative" } }),
1322
1323
  /* @__PURE__ */ jsxs6(
1323
1324
  Combobox3.Root,
@@ -1455,7 +1456,8 @@ function MultiCombobox(props) {
1455
1456
  loadingText = "Loading...",
1456
1457
  filter,
1457
1458
  inputValue,
1458
- onInputValueChange
1459
+ onInputValueChange,
1460
+ fullWidth = true
1459
1461
  } = props;
1460
1462
  const ariaDescribedBy = props["aria-describedby"];
1461
1463
  const isChildrenMode = "children" in props && props.children != null;
@@ -1670,7 +1672,7 @@ function MultiCombobox(props) {
1670
1672
  const rootItems = creatableSentinel && Array.isArray(baseItems) ? [...baseItems, creatableSentinel] : baseItems;
1671
1673
  const hasSentinels = selectAll || selectHeadings;
1672
1674
  const rootValue = hasSentinels ? [...value] : value;
1673
- return /* @__PURE__ */ jsxs7(Field, { children: [
1675
+ return /* @__PURE__ */ jsxs7(Field, { $fullWidth: fullWidth, children: [
1674
1676
  /* @__PURE__ */ jsx9("div", { ref: containerRef, style: { position: "relative" } }),
1675
1677
  /* @__PURE__ */ jsxs7(
1676
1678
  Combobox4.Root,
@@ -1692,15 +1694,23 @@ function MultiCombobox(props) {
1692
1694
  const label = itemToString(item);
1693
1695
  return label.toLowerCase().includes(query.toLowerCase());
1694
1696
  } : filter,
1695
- inputValue: creatableProp ? currentInputValue : inputValue,
1696
- onInputValueChange: creatableProp ? (v) => {
1697
- if (skipNextInputChangeRef.current) {
1698
- skipNextInputChangeRef.current = false;
1699
- return;
1697
+ inputValue: creatableProp ? currentInputValue : inputValue ?? internalInputValue,
1698
+ onInputValueChange: (v, eventDetails) => {
1699
+ if (eventDetails.reason === "input-clear" && open) return;
1700
+ if (creatableProp) {
1701
+ if (skipNextInputChangeRef.current) {
1702
+ skipNextInputChangeRef.current = false;
1703
+ return;
1704
+ }
1705
+ setInternalInputValue(v);
1706
+ onInputValueChange?.(v);
1707
+ } else {
1708
+ if (inputValue === void 0) {
1709
+ setInternalInputValue(v);
1710
+ }
1711
+ onInputValueChange?.(v);
1700
1712
  }
1701
- setInternalInputValue(v);
1702
- onInputValueChange?.(v);
1703
- } : onInputValueChange,
1713
+ },
1704
1714
  onItemHighlighted: isVirtualized ? (item, { reason, index }) => {
1705
1715
  const virt = virtualizerRef.current;
1706
1716
  if (!item || !virt) return;
@@ -1875,7 +1885,8 @@ function SingleSearchableSelect(props) {
1875
1885
  emptyText = "No results found.",
1876
1886
  isLoading = false,
1877
1887
  loadingText = "Loading...",
1878
- filter
1888
+ filter,
1889
+ fullWidth = true
1879
1890
  } = props;
1880
1891
  const ariaDescribedBy = props["aria-describedby"];
1881
1892
  const isChildrenMode = "children" in props && props.children != null;
@@ -1917,7 +1928,7 @@ function SingleSearchableSelect(props) {
1917
1928
  () => groupBy ? groupItems(data, groupBy) : null,
1918
1929
  [data, groupBy]
1919
1930
  );
1920
- return /* @__PURE__ */ jsxs8(Field, { children: [
1931
+ return /* @__PURE__ */ jsxs8(Field, { $fullWidth: fullWidth, children: [
1921
1932
  /* @__PURE__ */ jsx10("div", { ref: containerRef, style: { position: "relative" } }),
1922
1933
  /* @__PURE__ */ jsxs8(
1923
1934
  Combobox5.Root,
@@ -2049,8 +2060,9 @@ function SingleSearchableSelect(props) {
2049
2060
  import * as React11 from "react";
2050
2061
  import { Combobox as Combobox6 } from "@base-ui/react/combobox";
2051
2062
  import "@tanstack/react-virtual";
2063
+ import Icon4 from "@sproutsocial/seeds-react-icon";
2052
2064
  import styled7 from "styled-components";
2053
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2065
+ import { Fragment as Fragment10, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
2054
2066
  var SelectionText2 = styled7.span`
2055
2067
  flex: 1;
2056
2068
  overflow: hidden;
@@ -2075,7 +2087,8 @@ function MultiSearchableSelect(props) {
2075
2087
  emptyText = "No results found.",
2076
2088
  isLoading = false,
2077
2089
  loadingText = "Loading...",
2078
- filter
2090
+ filter,
2091
+ fullWidth = true
2079
2092
  } = props;
2080
2093
  const ariaDescribedBy = props["aria-describedby"];
2081
2094
  const isChildrenMode = "children" in props && props.children != null;
@@ -2092,12 +2105,16 @@ function MultiSearchableSelect(props) {
2092
2105
  const selectHeadings = isChildrenMode ? false : props.selectHeadings ?? false;
2093
2106
  const selectAll = isChildrenMode ? false : props.selectAll ?? false;
2094
2107
  const isVirtualized = isChildrenMode ? false : props.isVirtualized ?? false;
2108
+ const creatableProp = isChildrenMode ? false : props.creatable ?? false;
2109
+ const onCreateProp = isChildrenMode ? void 0 : props.onCreate;
2095
2110
  const children = isChildrenMode ? props.children : void 0;
2096
2111
  const selectedItemIds = props.selectedItemIds;
2097
2112
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
2098
2113
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
2099
2114
  const { containerRef, portalContainer } = useSeedsPortalContainer();
2100
2115
  const [open, setOpen] = React11.useState(false);
2116
+ const [internalInputValue, setInternalInputValue] = React11.useState("");
2117
+ const skipNextInputChangeRef = React11.useRef(false);
2101
2118
  const virtualizerRef = React11.useRef(null);
2102
2119
  const isControlled = selectedItemIds !== void 0;
2103
2120
  const idsToItems = React11.useCallback(
@@ -2116,6 +2133,18 @@ function MultiSearchableSelect(props) {
2116
2133
  () => groupBy ? groupItems(visibleData, groupBy) : null,
2117
2134
  [visibleData, groupBy]
2118
2135
  );
2136
+ const currentInputValue = internalInputValue;
2137
+ const creatableSentinel = React11.useMemo(() => {
2138
+ if (!creatableProp) return null;
2139
+ const trimmed = currentInputValue.trim();
2140
+ if (!trimmed) return null;
2141
+ const lowered = trimmed.toLocaleLowerCase();
2142
+ const exactExists = data.some(
2143
+ (d) => itemToString(d).trim().toLocaleLowerCase() === lowered
2144
+ );
2145
+ if (exactExists) return null;
2146
+ return makeCreatableSentinel(trimmed);
2147
+ }, [creatableProp, currentInputValue, data, itemToString]);
2119
2148
  const flatItems = React11.useMemo(() => {
2120
2149
  if (!groups || !selectHeadings && !selectAll) return null;
2121
2150
  const rows = [];
@@ -2132,10 +2161,21 @@ function MultiSearchableSelect(props) {
2132
2161
  onSelectedItemIdsChange(items.map((item) => item.id));
2133
2162
  }
2134
2163
  function handleValueChange(next) {
2164
+ const creatableClicked = next.find(isCreatableSentinel);
2165
+ if (creatableClicked) {
2166
+ const newItem = onCreateProp?.(creatableClicked.label);
2167
+ const realItems2 = next.filter(
2168
+ (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v) && !isCreatableSentinel(v)
2169
+ );
2170
+ setSelectedItems(newItem ? [...realItems2, newItem] : realItems2);
2171
+ skipNextInputChangeRef.current = true;
2172
+ setInternalInputValue("");
2173
+ return;
2174
+ }
2135
2175
  const selectAllClicked = next.filter(isSelectAllSentinel3);
2136
2176
  const groupSentinels = next.filter(isGroupHeaderSentinel3);
2137
2177
  const realItems = next.filter(
2138
- (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v)
2178
+ (v) => !isGroupHeaderSentinel3(v) && !isSelectAllSentinel3(v) && !isCreatableSentinel(v)
2139
2179
  );
2140
2180
  if (selectAllClicked.length > 0) {
2141
2181
  const allSelected = data.every(
@@ -2169,6 +2209,15 @@ function MultiSearchableSelect(props) {
2169
2209
  setSelectedItems(updated);
2170
2210
  }
2171
2211
  function handleSimpleValueChange(newItems) {
2212
+ const creatableClicked = newItems.find(isCreatableSentinel);
2213
+ if (creatableClicked) {
2214
+ const newItem = onCreateProp?.(creatableClicked.label);
2215
+ const realItems = newItems.filter((v) => !isCreatableSentinel(v));
2216
+ setSelectedItems(newItem ? [...realItems, newItem] : realItems);
2217
+ skipNextInputChangeRef.current = true;
2218
+ setInternalInputValue("");
2219
+ return;
2220
+ }
2172
2221
  setSelectedItems(newItems);
2173
2222
  }
2174
2223
  function renderSentinelRow(row) {
@@ -2199,6 +2248,9 @@ function MultiSearchableSelect(props) {
2199
2248
  renderGroupHeading ? renderGroupHeading(row.groupName) : row.groupName
2200
2249
  ] }, `__header-${row.groupName}`);
2201
2250
  }
2251
+ if (isCreatableSentinel(row)) {
2252
+ return renderCreatableItem(row);
2253
+ }
2202
2254
  const item = row;
2203
2255
  return /* @__PURE__ */ jsx11(
2204
2256
  ComboboxItem_default,
@@ -2213,10 +2265,31 @@ function MultiSearchableSelect(props) {
2213
2265
  item.id
2214
2266
  );
2215
2267
  }
2216
- const rootItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
2268
+ function renderCreatableItem(sentinel, style, index, measureRef) {
2269
+ return /* @__PURE__ */ jsx11(
2270
+ ComboboxItem_default,
2271
+ {
2272
+ value: sentinel,
2273
+ itemId: "__creatable",
2274
+ label: `Create "${sentinel.label}"`,
2275
+ inputType: "none",
2276
+ renderItem: () => /* @__PURE__ */ jsxs9(Fragment10, { children: [
2277
+ /* @__PURE__ */ jsx11(Icon4, { name: "plus-outline", size: "mini" }),
2278
+ `Create "${sentinel.label}"`
2279
+ ] }),
2280
+ style,
2281
+ index,
2282
+ "data-index": index,
2283
+ ref: measureRef
2284
+ },
2285
+ "__creatable"
2286
+ );
2287
+ }
2288
+ const baseItems = flatItems ?? groups ?? (isChildrenMode ? void 0 : visibleData);
2289
+ const rootItems = creatableSentinel && Array.isArray(baseItems) ? [...baseItems, creatableSentinel] : baseItems;
2217
2290
  const hasSentinels = selectAll || selectHeadings;
2218
2291
  const rootValue = hasSentinels ? [...value] : value;
2219
- return /* @__PURE__ */ jsxs9(Field, { children: [
2292
+ return /* @__PURE__ */ jsxs9(Field, { $fullWidth: fullWidth, children: [
2220
2293
  /* @__PURE__ */ jsx11("div", { ref: containerRef, style: { position: "relative" } }),
2221
2294
  /* @__PURE__ */ jsxs9(
2222
2295
  Combobox6.Root,
@@ -2224,7 +2297,23 @@ function MultiSearchableSelect(props) {
2224
2297
  multiple: true,
2225
2298
  id,
2226
2299
  virtualized: isVirtualized,
2227
- filter,
2300
+ filter: creatableProp ? (item, query) => {
2301
+ if (isCreatableSentinel(item)) return true;
2302
+ if (filter) return filter(item, query);
2303
+ if (isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item))
2304
+ return true;
2305
+ const label = itemToString(item);
2306
+ return label.toLowerCase().includes(query.toLowerCase());
2307
+ } : filter,
2308
+ inputValue: internalInputValue,
2309
+ onInputValueChange: (v, eventDetails) => {
2310
+ if (eventDetails.reason === "input-clear" && open) return;
2311
+ if (skipNextInputChangeRef.current) {
2312
+ skipNextInputChangeRef.current = false;
2313
+ return;
2314
+ }
2315
+ setInternalInputValue(v);
2316
+ },
2228
2317
  open,
2229
2318
  disabled: props.disabled,
2230
2319
  onOpenChange: setOpen,
@@ -2247,15 +2336,17 @@ function MultiSearchableSelect(props) {
2247
2336
  hasSentinels ? handleValueChange : handleSimpleValueChange
2248
2337
  ),
2249
2338
  itemToStringLabel: (item) => {
2250
- if (!item || isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item))
2339
+ if (!item || isGroupHeaderSentinel3(item) || isSelectAllSentinel3(item) || isCreatableSentinel(item))
2251
2340
  return "";
2252
2341
  return itemToString(item);
2253
2342
  },
2254
2343
  isItemEqualToValue: (a, b) => {
2344
+ if (isCreatableSentinel(a) && isCreatableSentinel(b))
2345
+ return a.label === b.label;
2255
2346
  if (isGroupHeaderSentinel3(a) && isGroupHeaderSentinel3(b))
2256
2347
  return a.groupName === b.groupName;
2257
2348
  if (isSelectAllSentinel3(a) && isSelectAllSentinel3(b)) return true;
2258
- if (!isGroupHeaderSentinel3(a) && !isSelectAllSentinel3(a) && !isGroupHeaderSentinel3(b) && !isSelectAllSentinel3(b))
2349
+ if (!isGroupHeaderSentinel3(a) && !isSelectAllSentinel3(a) && !isCreatableSentinel(a) && !isGroupHeaderSentinel3(b) && !isSelectAllSentinel3(b) && !isCreatableSentinel(b))
2259
2350
  return a.id === b.id;
2260
2351
  return false;
2261
2352
  },
@@ -2318,37 +2409,55 @@ function MultiSearchableSelect(props) {
2318
2409
  itemToString,
2319
2410
  inputType,
2320
2411
  renderItem,
2321
- renderGroupHeading
2412
+ renderGroupHeading,
2413
+ renderCreatableItem: creatableProp ? (sentinel, style, index, measureRef) => renderCreatableItem(
2414
+ sentinel,
2415
+ style,
2416
+ index,
2417
+ measureRef
2418
+ ) : void 0
2322
2419
  }
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
- )
2420
+ ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
2421
+ if (isCreatableSentinel(group)) {
2422
+ return renderCreatableItem(group);
2423
+ }
2424
+ const g = group;
2425
+ return /* @__PURE__ */ jsxs9(React11.Fragment, { children: [
2426
+ /* @__PURE__ */ jsxs9(ComboboxGroup, { items: g.items, children: [
2427
+ /* @__PURE__ */ jsx11(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
2428
+ /* @__PURE__ */ jsx11(Combobox6.Collection, { children: (item) => /* @__PURE__ */ jsx11(
2429
+ ComboboxItem_default,
2430
+ {
2431
+ value: item,
2432
+ itemId: String(item.id),
2433
+ label: itemToString(item),
2434
+ disabled: item.disabled,
2435
+ inputType,
2436
+ renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
2437
+ },
2438
+ item.id
2439
+ ) })
2440
+ ] }),
2441
+ index < groups.length - 1 && /* @__PURE__ */ jsx11(ComboboxSeparator, {})
2442
+ ] }, g.value);
2443
+ } : (item) => {
2444
+ if (isCreatableSentinel(item)) {
2445
+ return renderCreatableItem(item);
2446
+ }
2447
+ const dataItem = item;
2448
+ return /* @__PURE__ */ jsx11(
2449
+ ComboboxItem_default,
2450
+ {
2451
+ value: dataItem,
2452
+ itemId: String(dataItem.id),
2453
+ label: itemToString(dataItem),
2454
+ disabled: dataItem.disabled,
2455
+ inputType,
2456
+ renderItem: renderItem ? () => renderItem(dataItem) : () => itemToString(dataItem)
2457
+ },
2458
+ dataItem.id
2459
+ );
2460
+ }
2352
2461
  }
2353
2462
  )
2354
2463
  ]
@@ -2359,7 +2468,352 @@ function MultiSearchableSelect(props) {
2359
2468
  )
2360
2469
  ] });
2361
2470
  }
2471
+
2472
+ // src/v3/ActionMenu.tsx
2473
+ import * as React12 from "react";
2474
+ import { Menu as Menu2 } from "@base-ui/react/menu";
2475
+ import Radio3 from "@sproutsocial/seeds-react-radio";
2476
+ import Checkbox4 from "@sproutsocial/seeds-react-checkbox";
2477
+ import { Icon as Icon5 } from "@sproutsocial/seeds-react-icon";
2478
+
2479
+ // src/v3/ActionMenuStyles.tsx
2480
+ import { Menu } from "@base-ui/react/menu";
2481
+ import styled8, { css } from "styled-components";
2482
+ import "@sproutsocial/seeds-react-mixins";
2483
+ var ActionMenuTrigger = styled8(Menu.Trigger)``;
2484
+ var ActionMenuPositioner = styled8(Menu.Positioner)`
2485
+ min-width: var(--anchor-width);
2486
+ z-index: 7;
2487
+ `;
2488
+ var ActionMenuPopup = styled8(Menu.Popup)`
2489
+ font-family: ${({ theme }) => theme.fontFamily};
2490
+ background: ${({ theme }) => theme.colors.container.background.base};
2491
+ border: 1px solid ${({ theme }) => theme.colors.container.border.base};
2492
+ border-radius: ${({ theme }) => theme.radii[500]};
2493
+ box-shadow: ${({ theme }) => theme.shadows.low};
2494
+ outline: none;
2495
+ max-height: min(var(--base-ui-available-height, 400px), 400px);
2496
+ overflow-y: auto;
2497
+ padding: ${({ theme }) => theme.space[200]};
2498
+
2499
+ &[data-open] {
2500
+ animation: action-menu-popup-in 120ms ease-out;
2501
+ }
2502
+
2503
+ &[data-closed] {
2504
+ animation: action-menu-popup-out 100ms ease-in;
2505
+ }
2506
+
2507
+ @keyframes action-menu-popup-in {
2508
+ from {
2509
+ opacity: 0;
2510
+ transform: scale(0.95);
2511
+ }
2512
+ to {
2513
+ opacity: 1;
2514
+ transform: scale(1);
2515
+ }
2516
+ }
2517
+
2518
+ @keyframes action-menu-popup-out {
2519
+ from {
2520
+ opacity: 1;
2521
+ transform: scale(1);
2522
+ }
2523
+ to {
2524
+ opacity: 0;
2525
+ transform: scale(0.95);
2526
+ }
2527
+ }
2528
+ `;
2529
+ var ActionMenuGroup = styled8(Menu.Group)`
2530
+ display: block;
2531
+ `;
2532
+ var ActionMenuGroupLabel = styled8(Menu.GroupLabel)`
2533
+ padding: ${({ theme }) => `${theme.space[300]} ${theme.space[300]} ${theme.space[200]}`};
2534
+ font-size: ${({ theme }) => theme.typography[100].fontSize};
2535
+ font-weight: ${({ theme }) => theme.fontWeights.semibold};
2536
+ text-transform: uppercase;
2537
+ letter-spacing: 0.05em;
2538
+ color: ${({ theme }) => theme.colors.text.subtext};
2539
+ `;
2540
+ var ActionMenuSeparator = styled8(Menu.Separator)`
2541
+ height: 1px;
2542
+ margin: ${({ theme }) => `${theme.space[200]} ${theme.space[300]}`};
2543
+ background: ${({ theme }) => theme.colors.container.border.base};
2544
+ `;
2545
+ var menuItemStyles = css`
2546
+ box-sizing: border-box;
2547
+ display: block;
2548
+ width: 100%;
2549
+ border-radius: ${({ theme }) => theme.radii[500]};
2550
+ background-color: ${({ theme }) => theme.colors.listItem.background.base};
2551
+ border: 1px solid ${({ theme }) => theme.colors.listItem.background.base};
2552
+ color: ${({ theme }) => theme.colors.text.body};
2553
+ font-family: ${({ theme }) => theme.fontFamily};
2554
+ font-weight: ${({ theme }) => theme.fontWeights.normal};
2555
+ text-align: left;
2556
+ text-decoration: none;
2557
+ padding: ${({ theme }) => theme.space[300]};
2558
+ outline: 0;
2559
+ ${({ theme }) => theme.typography[200]};
2560
+ transition: all ${({ theme }) => theme.duration.fast};
2561
+ cursor: pointer;
2562
+ user-select: none;
2563
+
2564
+ &[data-highlighted] {
2565
+ border-color: ${({ theme }) => theme.colors.listItem.border.base};
2566
+ background-color: ${({ theme }) => theme.colors.listItem.background.hover};
2567
+ color: ${({ theme }) => theme.colors.text.body};
2568
+ text-decoration: none;
2569
+ }
2570
+
2571
+ &[data-disabled] {
2572
+ cursor: not-allowed;
2573
+ opacity: 0.4;
2574
+ }
2575
+ `;
2576
+ var StyledMenuItem = styled8(Menu.Item)`
2577
+ ${menuItemStyles}
2578
+ `;
2579
+ var StyledCheckboxItem = styled8(Menu.CheckboxItem)`
2580
+ ${menuItemStyles}
2581
+ display: flex;
2582
+ align-items: center;
2583
+ gap: ${({ theme }) => theme.space[300]};
2584
+ `;
2585
+ var StyledRadioItem = styled8(Menu.RadioItem)`
2586
+ ${menuItemStyles}
2587
+ display: flex;
2588
+ align-items: center;
2589
+ gap: ${({ theme }) => theme.space[300]};
2590
+ `;
2591
+ var StyledCheckboxItemIndicator = styled8(Menu.CheckboxItemIndicator)`
2592
+ display: flex;
2593
+ align-items: center;
2594
+ width: 16px;
2595
+ color: ${({ theme }) => theme.colors.text.body};
2596
+ `;
2597
+ var StyledRadioItemIndicator = styled8(Menu.RadioItemIndicator)`
2598
+ display: flex;
2599
+ align-items: center;
2600
+ width: 16px;
2601
+ color: ${({ theme }) => theme.colors.text.body};
2602
+ `;
2603
+ var StyledSubmenuTrigger = styled8(Menu.SubmenuTrigger)`
2604
+ ${menuItemStyles}
2605
+ display: flex;
2606
+ align-items: center;
2607
+ gap: ${({ theme }) => theme.space[300]};
2608
+ justify-content: space-between;
2609
+
2610
+ &[data-popup-open] {
2611
+ border-color: ${({ theme }) => theme.colors.listItem.border.base};
2612
+ background-color: ${({ theme }) => theme.colors.listItem.background.hover};
2613
+ }
2614
+ `;
2615
+ var StyledLinkItem = styled8(Menu.LinkItem)`
2616
+ ${menuItemStyles}
2617
+ `;
2618
+
2619
+ // src/v3/ActionMenu.tsx
2620
+ import { Fragment as Fragment11, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2621
+ function ActionMenu({
2622
+ trigger,
2623
+ children,
2624
+ open,
2625
+ defaultOpen,
2626
+ onOpenChange,
2627
+ disabled
2628
+ }) {
2629
+ const { containerRef, portalContainer } = useSeedsPortalContainer();
2630
+ return /* @__PURE__ */ jsxs10(
2631
+ Menu2.Root,
2632
+ {
2633
+ open,
2634
+ defaultOpen,
2635
+ onOpenChange,
2636
+ children: [
2637
+ /* @__PURE__ */ jsx12("div", { ref: containerRef, style: { position: "relative" } }),
2638
+ /* @__PURE__ */ jsx12(ActionMenuTrigger, { render: trigger, disabled }),
2639
+ /* @__PURE__ */ jsx12(Menu2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx12(ActionMenuPositioner, { sideOffset: 8, children: /* @__PURE__ */ jsx12(ActionMenuPopup, { children }) }) })
2640
+ ]
2641
+ }
2642
+ );
2643
+ }
2644
+ function MenuGroup({
2645
+ children,
2646
+ label,
2647
+ showSeparator = false
2648
+ }) {
2649
+ return /* @__PURE__ */ jsxs10(Fragment11, { children: [
2650
+ /* @__PURE__ */ jsxs10(ActionMenuGroup, { children: [
2651
+ label && /* @__PURE__ */ jsx12(ActionMenuGroupLabel, { children: label }),
2652
+ children
2653
+ ] }),
2654
+ showSeparator && /* @__PURE__ */ jsx12(ActionMenuSeparator, {})
2655
+ ] });
2656
+ }
2657
+ function MenuRadioGroup({
2658
+ children,
2659
+ value,
2660
+ defaultValue,
2661
+ onValueChange
2662
+ }) {
2663
+ return /* @__PURE__ */ jsx12(
2664
+ Menu2.RadioGroup,
2665
+ {
2666
+ value,
2667
+ defaultValue,
2668
+ onValueChange,
2669
+ children
2670
+ }
2671
+ );
2672
+ }
2673
+ function MenuItem(props) {
2674
+ const generatedId = React12.useId();
2675
+ if (props.type === "checkbox") {
2676
+ const {
2677
+ children: children2,
2678
+ checked,
2679
+ defaultChecked,
2680
+ onCheckedChange,
2681
+ disabled: disabled2,
2682
+ closeOnClick: closeOnClick2 = false,
2683
+ id
2684
+ } = props;
2685
+ const itemId = id ?? `checkbox-menu-item-${generatedId}`;
2686
+ return /* @__PURE__ */ jsxs10(
2687
+ StyledCheckboxItem,
2688
+ {
2689
+ checked,
2690
+ defaultChecked,
2691
+ onCheckedChange,
2692
+ disabled: disabled2,
2693
+ closeOnClick: closeOnClick2,
2694
+ children: [
2695
+ /* @__PURE__ */ jsx12(
2696
+ StyledCheckboxItemIndicator,
2697
+ {
2698
+ keepMounted: true,
2699
+ render: (_indicatorProps, state) => /* @__PURE__ */ jsx12(
2700
+ Checkbox4,
2701
+ {
2702
+ checked: state.checked,
2703
+ onChange: () => {
2704
+ },
2705
+ tabIndex: -1,
2706
+ id: itemId,
2707
+ name: "menu-checkbox-item"
2708
+ }
2709
+ )
2710
+ }
2711
+ ),
2712
+ children2
2713
+ ]
2714
+ }
2715
+ );
2716
+ }
2717
+ if (props.type === "radio") {
2718
+ const { children: children2, value, disabled: disabled2, closeOnClick: closeOnClick2 = false } = props;
2719
+ return /* @__PURE__ */ jsxs10(
2720
+ StyledRadioItem,
2721
+ {
2722
+ value,
2723
+ disabled: disabled2,
2724
+ closeOnClick: closeOnClick2,
2725
+ children: [
2726
+ /* @__PURE__ */ jsx12(
2727
+ StyledRadioItemIndicator,
2728
+ {
2729
+ keepMounted: true,
2730
+ render: (_indicatorProps, state) => /* @__PURE__ */ jsx12(
2731
+ Radio3,
2732
+ {
2733
+ checked: state.checked,
2734
+ onChange: () => {
2735
+ },
2736
+ tabIndex: -1,
2737
+ id: `radio-menu-item-${value}`,
2738
+ name: "menu-radio-item"
2739
+ }
2740
+ )
2741
+ }
2742
+ ),
2743
+ children2
2744
+ ]
2745
+ }
2746
+ );
2747
+ }
2748
+ const {
2749
+ children,
2750
+ onClick,
2751
+ disabled,
2752
+ closeOnClick = true,
2753
+ href,
2754
+ target
2755
+ } = props;
2756
+ if (href) {
2757
+ return /* @__PURE__ */ jsx12(StyledLinkItem, { href, target, closeOnClick, children });
2758
+ }
2759
+ return /* @__PURE__ */ jsx12(
2760
+ StyledMenuItem,
2761
+ {
2762
+ onClick,
2763
+ disabled,
2764
+ closeOnClick,
2765
+ children
2766
+ }
2767
+ );
2768
+ }
2769
+ function MenuSub({
2770
+ trigger,
2771
+ children,
2772
+ open,
2773
+ defaultOpen,
2774
+ onOpenChange,
2775
+ closeParentOnEsc = false
2776
+ }) {
2777
+ const { containerRef, portalContainer } = useSeedsPortalContainer();
2778
+ return /* @__PURE__ */ jsxs10(
2779
+ Menu2.SubmenuRoot,
2780
+ {
2781
+ open,
2782
+ defaultOpen,
2783
+ onOpenChange,
2784
+ closeParentOnEsc,
2785
+ children: [
2786
+ /* @__PURE__ */ jsx12("div", { ref: containerRef, style: { position: "relative" } }),
2787
+ trigger,
2788
+ /* @__PURE__ */ jsx12(Menu2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx12(ActionMenuPositioner, { sideOffset: getOffset, alignOffset: getOffset, children: /* @__PURE__ */ jsx12(ActionMenuPopup, { children }) }) })
2789
+ ]
2790
+ }
2791
+ );
2792
+ }
2793
+ function getOffset({ side }) {
2794
+ return side === "top" || side === "bottom" ? 4 : -8;
2795
+ }
2796
+ function MenuSubTrigger({
2797
+ children,
2798
+ disabled,
2799
+ label,
2800
+ openOnHover = true
2801
+ }) {
2802
+ return /* @__PURE__ */ jsxs10(
2803
+ StyledSubmenuTrigger,
2804
+ {
2805
+ disabled,
2806
+ label,
2807
+ openOnHover,
2808
+ children: [
2809
+ children,
2810
+ /* @__PURE__ */ jsx12(Icon5, { name: "chevron-right-outline", fixedWidth: true, "aria-hidden": true })
2811
+ ]
2812
+ }
2813
+ );
2814
+ }
2362
2815
  export {
2816
+ ActionMenu,
2363
2817
  ComboboxActionButtons,
2364
2818
  ComboboxClear,
2365
2819
  ComboboxEmpty,
@@ -2382,6 +2836,11 @@ export {
2382
2836
  ComboboxTokenInput,
2383
2837
  ComboboxTokenInputGroup,
2384
2838
  ComboboxTrigger,
2839
+ MenuGroup,
2840
+ MenuItem,
2841
+ MenuRadioGroup,
2842
+ MenuSub,
2843
+ MenuSubTrigger,
2385
2844
  MultiCombobox,
2386
2845
  MultiSearchableSelect,
2387
2846
  MultiSelect,