@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.
- package/.turbo/turbo-build.log +13 -13
- package/CHANGELOG.md +16 -0
- package/dist/esm/v3/index.js +517 -58
- package/dist/esm/v3/index.js.map +1 -1
- package/dist/index.d.mts +22 -22
- package/dist/index.d.ts +22 -22
- package/dist/v3/index.d.mts +160 -50
- package/dist/v3/index.d.ts +160 -50
- package/dist/v3/index.js +522 -57
- package/dist/v3/index.js.map +1 -1
- package/package.json +1 -1
- package/src/v3/ActionMenu.stories.tsx +260 -0
- package/src/v3/ActionMenu.tsx +345 -0
- package/src/v3/ActionMenuStyles.tsx +153 -0
- package/src/v3/Common/SelectStyles.tsx +4 -3
- package/src/v3/ModalStories.stories.tsx +159 -0
- package/src/v3/MultiCombobox.stories.tsx +17 -0
- package/src/v3/MultiCombobox.tsx +24 -13
- package/src/v3/MultiSearchableSelect.stories.tsx +18 -0
- package/src/v3/MultiSearchableSelect.tsx +214 -55
- package/src/v3/MultiSelect.stories.tsx +17 -0
- package/src/v3/MultiSelect.tsx +3 -2
- package/src/v3/SingleCombobox.stories.tsx +17 -0
- package/src/v3/SingleCombobox.tsx +3 -1
- package/src/v3/SingleSearchableSelect.stories.tsx +18 -0
- package/src/v3/SingleSearchableSelect.tsx +3 -1
- package/src/v3/SingleSelect.stories.tsx +17 -0
- package/src/v3/SingleSelect.tsx +3 -2
- package/src/v3/index.ts +1 -0
package/dist/esm/v3/index.js
CHANGED
|
@@ -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:
|
|
1697
|
-
if (
|
|
1698
|
-
|
|
1699
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) =>
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
}
|
|
2350
|
-
item
|
|
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,
|