@sproutsocial/seeds-react-menu 1.12.3 → 1.15.10

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.
Files changed (35) hide show
  1. package/.turbo/turbo-build.log +12 -12
  2. package/CHANGELOG.md +193 -0
  3. package/dist/esm/v3/index.js +726 -186
  4. package/dist/esm/v3/index.js.map +1 -1
  5. package/dist/index.d.mts +22 -22
  6. package/dist/index.d.ts +22 -22
  7. package/dist/v3/index.d.mts +199 -50
  8. package/dist/v3/index.d.ts +199 -50
  9. package/dist/v3/index.js +732 -185
  10. package/dist/v3/index.js.map +1 -1
  11. package/package.json +14 -14
  12. package/src/v3/ActionMenu.stories.tsx +260 -0
  13. package/src/v3/ActionMenu.tsx +345 -0
  14. package/src/v3/ActionMenuStyles.tsx +154 -0
  15. package/src/v3/Common/ComboboxStyles.tsx +41 -7
  16. package/src/v3/Common/SelectStyles.tsx +20 -6
  17. package/src/v3/Common/useSuppressEscapeClear.ts +20 -0
  18. package/src/v3/MenuButton.stories.tsx +118 -0
  19. package/src/v3/MenuButton.tsx +68 -0
  20. package/src/v3/MenuButtonStyles.tsx +38 -0
  21. package/src/v3/ModalStories.stories.tsx +159 -0
  22. package/src/v3/MultiCombobox.stories.tsx +157 -0
  23. package/src/v3/MultiCombobox.tsx +28 -8
  24. package/src/v3/MultiSearchableSelect.stories.tsx +42 -0
  25. package/src/v3/MultiSearchableSelect.tsx +11 -6
  26. package/src/v3/MultiSelect.stories.tsx +40 -0
  27. package/src/v3/MultiSelect.tsx +12 -3
  28. package/src/v3/SingleCombobox.stories.tsx +36 -0
  29. package/src/v3/SingleCombobox.tsx +17 -7
  30. package/src/v3/SingleSearchableSelect.stories.tsx +38 -0
  31. package/src/v3/SingleSearchableSelect.tsx +15 -7
  32. package/src/v3/SingleSelect.stories.tsx +36 -0
  33. package/src/v3/SingleSelect.tsx +12 -3
  34. package/src/v3/__tests__/MenuButton.test.tsx +80 -0
  35. package/src/v3/index.ts +2 -0
@@ -134,20 +134,50 @@ function groupItems(data, groupBy) {
134
134
 
135
135
  // src/v3/Common/SelectStyles.tsx
136
136
  import { Select as Select2 } from "@base-ui/react/select";
137
- import styled2 from "styled-components";
137
+ import styled3, { css } from "styled-components";
138
138
  import { focusRing } from "@sproutsocial/seeds-react-mixins";
139
- var Field = styled2.div`
139
+
140
+ // src/v3/Common/SelectIcons.tsx
141
+ import "react";
142
+ import styled2 from "styled-components";
143
+ import { Icon as Icon2 } from "@sproutsocial/seeds-react-icon";
144
+ import { jsx as jsx2 } from "react/jsx-runtime";
145
+ var StyledChevron = styled2.div`
140
146
  display: flex;
147
+ align-items: center;
148
+ transition: transform 0.15s;
149
+ ${({ $isOpen }) => $isOpen && "transform: rotate(-180deg);"}
150
+ `;
151
+ function ChevronIcon() {
152
+ return /* @__PURE__ */ jsx2(Icon2, { name: "chevron-down-outline", fixedWidth: true, "aria-hidden": true });
153
+ }
154
+ function ClearIcon() {
155
+ return /* @__PURE__ */ jsx2(Icon2, { name: "circle-x-outline", fixedWidth: true, "aria-hidden": true, size: "mini" });
156
+ }
157
+ function CheckIcon2() {
158
+ return /* @__PURE__ */ jsx2(Icon2, { name: "check-outline", fixedWidth: true, "aria-hidden": true });
159
+ }
160
+
161
+ // src/v3/Common/SelectStyles.tsx
162
+ var invalidStyles = css`
163
+ border-color: ${({ theme }) => theme.colors.form.border.error};
164
+
165
+ ${StyledChevron} {
166
+ color: ${({ theme }) => theme.colors.icon.error};
167
+ }
168
+ `;
169
+ var Field = styled3.div`
170
+ display: ${({ $fullWidth }) => $fullWidth === false ? "inline-flex" : "flex"};
141
171
  flex-direction: column;
142
172
  gap: ${({ theme }) => theme.space[200]};
143
- width: 100%;
173
+ ${({ $fullWidth }) => $fullWidth !== false && "width: 100%;"}
144
174
  `;
145
- var SelectLabel = styled2(Select2.Label)`
175
+ var SelectLabel = styled3(Select2.Label)`
146
176
  font-size: ${({ theme }) => theme.typography[200].fontSize};
147
177
  font-weight: ${({ theme }) => theme.fontWeights.semibold};
148
178
  color: ${({ theme }) => theme.colors.text.body};
149
179
  `;
150
- var SelectTrigger = styled2(Select2.Trigger)`
180
+ var SelectTrigger = styled3(Select2.Trigger)`
151
181
  display: flex;
152
182
  align-items: center;
153
183
  justify-content: space-between;
@@ -182,21 +212,23 @@ var SelectTrigger = styled2(Select2.Trigger)`
182
212
  opacity: 0.4;
183
213
  cursor: not-allowed;
184
214
  }
215
+
216
+ ${({ $isInvalid }) => $isInvalid && invalidStyles}
185
217
  `;
186
- var SelectValue = styled2(Select2.Value)`
218
+ var SelectValue = styled3(Select2.Value)`
187
219
  min-width: 0;
188
220
  overflow: hidden;
189
221
  `;
190
- var SelectIcon = styled2(Select2.Icon)`
222
+ var SelectIcon = styled3(Select2.Icon)`
191
223
  display: flex;
192
224
  align-items: center;
193
225
  color: ${({ theme }) => theme.colors.icon.base};
194
226
  flex-shrink: 0;
195
227
  `;
196
- var SelectGroup = styled2(Select2.Group)`
228
+ var SelectGroup = styled3(Select2.Group)`
197
229
  display: block;
198
230
  `;
199
- var SelectGroupLabel = styled2(Select2.GroupLabel)`
231
+ var SelectGroupLabel = styled3(Select2.GroupLabel)`
200
232
  padding: ${({ theme }) => `${theme.space[300]} ${theme.space[300]} ${theme.space[200]}`};
201
233
  font-size: ${({ theme }) => theme.typography[100].fontSize};
202
234
  font-weight: ${({ theme }) => theme.fontWeights.semibold};
@@ -204,23 +236,23 @@ var SelectGroupLabel = styled2(Select2.GroupLabel)`
204
236
  letter-spacing: 0.05em;
205
237
  color: ${({ theme }) => theme.colors.text.subtext};
206
238
  `;
207
- var SelectSeparator = styled2(Select2.Separator)`
239
+ var SelectSeparator = styled3(Select2.Separator)`
208
240
  height: 1px;
209
241
  margin: ${({ theme }) => `${theme.space[200]} ${theme.space[300]}`};
210
242
  background: ${({ theme }) => theme.colors.container.border.base};
211
243
  `;
212
- var SelectPositioner = styled2(Select2.Positioner)`
244
+ var SelectPositioner = styled3(Select2.Positioner)`
213
245
  width: var(--anchor-width);
214
246
  z-index: 7;
215
247
  `;
216
- var SelectPopup = styled2(Select2.Popup)`
248
+ var SelectPopup = styled3(Select2.Popup)`
217
249
  font-family: ${({ theme }) => theme.fontFamily};
218
250
  background: ${({ theme }) => theme.colors.container.background.base};
219
251
  border: 1px solid ${({ theme }) => theme.colors.container.border.base};
220
252
  border-radius: ${({ theme }) => theme.radii[500]};
221
253
  box-shadow: ${({ theme }) => theme.shadows.low};
222
254
  outline: none;
223
- max-height: min(var(--base-ui-available-height, 400px), 400px);
255
+ max-height: min(var(--available-height, 400px), 400px);
224
256
  overflow-y: auto;
225
257
  padding: ${({ theme }) => theme.space[200]};
226
258
 
@@ -255,27 +287,6 @@ var SelectPopup = styled2(Select2.Popup)`
255
287
  }
256
288
  `;
257
289
 
258
- // src/v3/Common/SelectIcons.tsx
259
- import "react";
260
- import styled3 from "styled-components";
261
- import { Icon as Icon2 } from "@sproutsocial/seeds-react-icon";
262
- import { jsx as jsx2 } from "react/jsx-runtime";
263
- var StyledChevron = styled3.div`
264
- display: flex;
265
- align-items: center;
266
- transition: transform 0.15s;
267
- ${({ $isOpen }) => $isOpen && "transform: rotate(-180deg);"}
268
- `;
269
- function ChevronIcon() {
270
- return /* @__PURE__ */ jsx2(Icon2, { name: "chevron-down-outline", fixedWidth: true, "aria-hidden": true });
271
- }
272
- function ClearIcon() {
273
- return /* @__PURE__ */ jsx2(Icon2, { name: "circle-x-outline", fixedWidth: true, "aria-hidden": true, size: "mini" });
274
- }
275
- function CheckIcon2() {
276
- return /* @__PURE__ */ jsx2(Icon2, { name: "check-outline", fixedWidth: true, "aria-hidden": true });
277
- }
278
-
279
290
  // src/v3/SingleSelect.tsx
280
291
  import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
281
292
  var StyledValue = styled4(Select3.Value)`
@@ -290,8 +301,9 @@ var StyledValue = styled4(Select3.Value)`
290
301
  }
291
302
  `;
292
303
  function SingleSelect(props) {
293
- const { id, placeholder, includePlaceholderItem } = props;
304
+ const { id, placeholder, includePlaceholderItem, fullWidth = true } = props;
294
305
  const ariaDescribedBy = props["aria-describedby"];
306
+ const isInvalid = props.isInvalid;
295
307
  const isChildrenMode = "children" in props && props.children != null;
296
308
  const selectedItemId = props.selectedItemId;
297
309
  const defaultSelectedItemId = props.defaultSelectedItemId;
@@ -338,7 +350,7 @@ function SingleSelect(props) {
338
350
  }
339
351
  }
340
352
  }
341
- return /* @__PURE__ */ jsxs2(Field, { children: [
353
+ return /* @__PURE__ */ jsxs2(Field, { $fullWidth: fullWidth, children: [
342
354
  /* @__PURE__ */ jsx3("div", { ref: containerRef, style: { position: "relative" } }),
343
355
  /* @__PURE__ */ jsxs2(
344
356
  Select3.Root,
@@ -349,10 +361,19 @@ function SingleSelect(props) {
349
361
  onValueChange: handleValueChange,
350
362
  id,
351
363
  children: [
352
- /* @__PURE__ */ jsxs2(SelectTrigger, { "aria-describedby": ariaDescribedBy, children: [
353
- /* @__PURE__ */ jsx3(StyledValue, { placeholder, children: renderSelection && selectedItem ? renderSelection(selectedItem) : void 0 }),
354
- /* @__PURE__ */ jsx3(SelectIcon, { children: /* @__PURE__ */ jsx3(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ jsx3(ChevronIcon, {}) }) })
355
- ] }),
364
+ /* @__PURE__ */ jsxs2(
365
+ SelectTrigger,
366
+ {
367
+ "aria-describedby": ariaDescribedBy,
368
+ "aria-invalid": isInvalid || void 0,
369
+ "aria-required": props.required || void 0,
370
+ $isInvalid: isInvalid,
371
+ children: [
372
+ /* @__PURE__ */ jsx3(StyledValue, { placeholder, children: renderSelection && selectedItem ? renderSelection(selectedItem) : void 0 }),
373
+ /* @__PURE__ */ jsx3(SelectIcon, { children: /* @__PURE__ */ jsx3(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ jsx3(ChevronIcon, {}) }) })
374
+ ]
375
+ }
376
+ ),
356
377
  /* @__PURE__ */ jsx3(Select3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx3(SelectPositioner, { sideOffset: 8, alignItemWithTrigger: false, children: /* @__PURE__ */ jsxs2(SelectPopup, { children: [
357
378
  /* @__PURE__ */ jsx3(Select3.ScrollUpArrow, {}),
358
379
  /* @__PURE__ */ jsx3(Select3.List, { children: children ? children : groupBy ? groupItems(data, groupBy).map((group, index, arr) => /* @__PURE__ */ jsxs2(React4.Fragment, { children: [
@@ -420,8 +441,9 @@ var Placeholder = styled5.div`
420
441
  margin: 2px 8px 0px 0px;
421
442
  `;
422
443
  function MultiSelect(props) {
423
- const { id, placeholder = "Select..." } = props;
444
+ const { id, placeholder = "Select...", fullWidth = true } = props;
424
445
  const ariaDescribedBy = props["aria-describedby"];
446
+ const isInvalid = props.isInvalid;
425
447
  const isChildrenMode = "children" in props && props.children != null;
426
448
  const data = isChildrenMode ? [] : props.data;
427
449
  const itemToString = isChildrenMode ? () => "" : props.itemToString;
@@ -466,7 +488,7 @@ function MultiSelect(props) {
466
488
  onSelectedItemIdsChange(ids);
467
489
  }
468
490
  }
469
- return /* @__PURE__ */ jsxs3(Field, { children: [
491
+ return /* @__PURE__ */ jsxs3(Field, { $fullWidth: fullWidth, children: [
470
492
  /* @__PURE__ */ jsx4("div", { ref: containerRef, style: { position: "relative" } }),
471
493
  /* @__PURE__ */ jsxs3(
472
494
  Select4.Root,
@@ -478,23 +500,32 @@ function MultiSelect(props) {
478
500
  disabled: props.disabled,
479
501
  id,
480
502
  children: [
481
- /* @__PURE__ */ jsxs3(SelectTrigger, { "aria-describedby": ariaDescribedBy, children: [
482
- /* @__PURE__ */ jsx4(SelectValue, { children: () => {
483
- if (renderSelection) return renderSelection(selectedItems);
484
- if (selectedItems.length === 0)
485
- return /* @__PURE__ */ jsx4(Placeholder, { children: placeholder });
486
- const visibleItems = maxSelections != null ? selectedItems.slice(0, maxSelections) : selectedItems;
487
- const overflowCount = maxSelections != null && selectedItems.length > maxSelections ? selectedItems.length - maxSelections : 0;
488
- const text = visibleItems.map(
489
- (item) => customRenderSelections ? customRenderSelections(item) : itemToString(item)
490
- ).join(", ");
491
- return /* @__PURE__ */ jsxs3(SelectionText, { children: [
492
- text,
493
- overflowCount > 0 ? `, +${overflowCount}` : ""
494
- ] });
495
- } }),
496
- /* @__PURE__ */ jsx4(SelectIcon, { children: /* @__PURE__ */ jsx4(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ jsx4(ChevronIcon, {}) }) })
497
- ] }),
503
+ /* @__PURE__ */ jsxs3(
504
+ SelectTrigger,
505
+ {
506
+ "aria-describedby": ariaDescribedBy,
507
+ "aria-invalid": isInvalid || void 0,
508
+ "aria-required": props.required || void 0,
509
+ $isInvalid: isInvalid,
510
+ children: [
511
+ /* @__PURE__ */ jsx4(SelectValue, { children: () => {
512
+ if (renderSelection) return renderSelection(selectedItems);
513
+ if (selectedItems.length === 0)
514
+ return /* @__PURE__ */ jsx4(Placeholder, { children: placeholder });
515
+ const visibleItems = maxSelections != null ? selectedItems.slice(0, maxSelections) : selectedItems;
516
+ const overflowCount = maxSelections != null && selectedItems.length > maxSelections ? selectedItems.length - maxSelections : 0;
517
+ const text = visibleItems.map(
518
+ (item) => customRenderSelections ? customRenderSelections(item) : itemToString(item)
519
+ ).join(", ");
520
+ return /* @__PURE__ */ jsxs3(SelectionText, { children: [
521
+ text,
522
+ overflowCount > 0 ? `, +${overflowCount}` : ""
523
+ ] });
524
+ } }),
525
+ /* @__PURE__ */ jsx4(SelectIcon, { children: /* @__PURE__ */ jsx4(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ jsx4(ChevronIcon, {}) }) })
526
+ ]
527
+ }
528
+ ),
498
529
  /* @__PURE__ */ jsx4(Select4.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx4(SelectPositioner, { sideOffset: 8, alignItemWithTrigger: false, children: /* @__PURE__ */ jsxs3(SelectPopup, { children: [
499
530
  /* @__PURE__ */ jsx4(Select4.ScrollUpArrow, {}),
500
531
  /* @__PURE__ */ jsx4(Select4.List, { children: children ? children : groupBy ? groupItems(data, groupBy).map((group, index, arr) => /* @__PURE__ */ jsxs3(React5.Fragment, { children: [
@@ -535,21 +566,41 @@ function MultiSelect(props) {
535
566
  }
536
567
 
537
568
  // src/v3/SingleCombobox.tsx
538
- import * as React8 from "react";
569
+ import * as React9 from "react";
539
570
  import { Combobox as Combobox3 } from "@base-ui/react/combobox";
540
571
  import "@tanstack/react-virtual";
541
572
 
542
- // src/v3/Common/ComboboxItem.tsx
573
+ // src/v3/Common/useSuppressEscapeClear.ts
543
574
  import * as React6 from "react";
575
+ function useSuppressEscapeClear(open) {
576
+ return React6.useCallback(
577
+ (event) => {
578
+ if (event.key === "Escape" && !open) {
579
+ event.stopPropagation();
580
+ }
581
+ },
582
+ [open]
583
+ );
584
+ }
585
+
586
+ // src/v3/Common/ComboboxItem.tsx
587
+ import * as React7 from "react";
544
588
  import Radio2 from "@sproutsocial/seeds-react-radio";
545
589
  import Checkbox3 from "@sproutsocial/seeds-react-checkbox";
546
590
 
547
591
  // src/v3/Common/ComboboxStyles.tsx
548
592
  import { Combobox } from "@base-ui/react/combobox";
549
- import styled6 from "styled-components";
593
+ import styled6, { css as css2 } from "styled-components";
550
594
  import { focusRing as focusRing2 } from "@sproutsocial/seeds-react-mixins";
551
595
  import Checkbox2 from "@sproutsocial/seeds-react-checkbox";
552
596
  import { jsx as jsx5 } from "react/jsx-runtime";
597
+ var invalidStyles2 = css2`
598
+ border-color: ${({ theme }) => theme.colors.form.border.error};
599
+
600
+ ${StyledChevron} {
601
+ color: ${({ theme }) => theme.colors.icon.error};
602
+ }
603
+ `;
553
604
  var ComboboxLabel = styled6.label`
554
605
  font-size: ${({ theme }) => theme.typography[200].fontSize};
555
606
  font-weight: ${({ theme }) => theme.fontWeights.semibold};
@@ -576,6 +627,8 @@ var ComboboxInputGroup = styled6(Combobox.InputGroup)`
576
627
  opacity: 0.4;
577
628
  cursor: not-allowed;
578
629
  }
630
+
631
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
579
632
  `;
580
633
  var ComboboxInput = styled6(Combobox.Input)`
581
634
  flex: 1;
@@ -623,7 +676,7 @@ var ComboboxActionButtons = styled6.div`
623
676
  margin-left: auto;
624
677
  gap: ${({ theme }) => theme.space[100]};
625
678
  `;
626
- var ComboboxClear = styled6(Combobox.Clear)`
679
+ var ComboboxClear = styled6(Combobox.Clear).attrs({ tabIndex: 0 })`
627
680
  display: flex;
628
681
  align-items: center;
629
682
  justify-content: center;
@@ -640,6 +693,10 @@ var ComboboxClear = styled6(Combobox.Clear)`
640
693
  color: ${({ theme }) => theme.colors.text.body};
641
694
  }
642
695
 
696
+ &:focus-visible {
697
+ ${focusRing2}
698
+ }
699
+
643
700
  &[data-empty] {
644
701
  display: none;
645
702
  }
@@ -672,7 +729,7 @@ var ComboboxPopup = styled6(Combobox.Popup)`
672
729
  box-shadow: ${({ theme }) => theme.shadows.medium};
673
730
  outline: none;
674
731
  width: 100%;
675
- max-height: min(var(--base-ui-available-height, 400px), 400px);
732
+ max-height: min(var(--available-height, 400px), 400px);
676
733
  overflow-y: auto;
677
734
  padding: 0;
678
735
 
@@ -839,6 +896,7 @@ var ComboboxToken = styled6(Combobox.Chips)`
839
896
  display: flex;
840
897
  width: 100%;
841
898
  flex-wrap: wrap;
899
+ gap: ${({ theme }) => theme.space[200]};
842
900
  `;
843
901
  var ComboboxTokenInputGroup = styled6(Combobox.InputGroup)`
844
902
  display: flex;
@@ -863,6 +921,8 @@ var ComboboxTokenInputGroup = styled6(Combobox.InputGroup)`
863
921
  opacity: 0.4;
864
922
  cursor: not-allowed;
865
923
  }
924
+
925
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
866
926
  `;
867
927
  var Token = styled6.span`
868
928
  display: inline-flex;
@@ -895,6 +955,10 @@ var TokenRemove = styled6.button`
895
955
  cursor: pointer;
896
956
  padding: 0;
897
957
  line-height: 1;
958
+
959
+ &:focus-visible {
960
+ ${focusRing2}
961
+ }
898
962
  `;
899
963
  var SearchableSelectTrigger = styled6(Combobox.Trigger)`
900
964
  display: flex;
@@ -928,6 +992,8 @@ var SearchableSelectTrigger = styled6(Combobox.Trigger)`
928
992
  opacity: 0.4;
929
993
  cursor: not-allowed;
930
994
  }
995
+
996
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
931
997
  `;
932
998
  var SearchableSelectTriggerIcon = styled6(Combobox.Icon)`
933
999
  display: flex;
@@ -1010,6 +1076,8 @@ var SearchableSelectTokenTrigger = styled6(Combobox.Trigger)`
1010
1076
  opacity: 0.4;
1011
1077
  cursor: not-allowed;
1012
1078
  }
1079
+
1080
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
1013
1081
  `;
1014
1082
 
1015
1083
  // src/v3/Common/ComboboxItem.tsx
@@ -1074,11 +1142,11 @@ function ComboboxItemInner({
1074
1142
  }
1075
1143
  );
1076
1144
  }
1077
- var ComboboxItem2 = React6.forwardRef(ComboboxItemInner);
1145
+ var ComboboxItem2 = React7.forwardRef(ComboboxItemInner);
1078
1146
  var ComboboxItem_default = ComboboxItem2;
1079
1147
 
1080
1148
  // src/v3/Common/VirtualizedComboboxList.tsx
1081
- import * as React7 from "react";
1149
+ import * as React8 from "react";
1082
1150
  import { Combobox as Combobox2 } from "@base-ui/react/combobox";
1083
1151
  import { useVirtualizer } from "@tanstack/react-virtual";
1084
1152
 
@@ -1118,7 +1186,7 @@ function VirtualizedComboboxList({
1118
1186
  renderCreatableItem
1119
1187
  }) {
1120
1188
  const filteredItems = Combobox2.useFilteredItems();
1121
- const scrollElementRef = React7.useRef(null);
1189
+ const scrollElementRef = React8.useRef(null);
1122
1190
  const virtualizer = useVirtualizer({
1123
1191
  enabled: open,
1124
1192
  count: filteredItems.length,
@@ -1130,8 +1198,8 @@ function VirtualizedComboboxList({
1130
1198
  scrollPaddingStart: 4,
1131
1199
  scrollPaddingEnd: 4
1132
1200
  });
1133
- React7.useImperativeHandle(virtualizerRef, () => virtualizer);
1134
- const handleScrollRef = React7.useCallback(
1201
+ React8.useImperativeHandle(virtualizerRef, () => virtualizer);
1202
+ const handleScrollRef = React8.useCallback(
1135
1203
  (el) => {
1136
1204
  scrollElementRef.current = el;
1137
1205
  if (el) requestAnimationFrame(() => virtualizer.measure());
@@ -1275,9 +1343,11 @@ function SingleCombobox(props) {
1275
1343
  id,
1276
1344
  placeholder = "Search...",
1277
1345
  emptyText = "No results found.",
1278
- filter
1346
+ filter,
1347
+ fullWidth = true
1279
1348
  } = props;
1280
1349
  const ariaDescribedBy = props["aria-describedby"];
1350
+ const isInvalid = props.isInvalid;
1281
1351
  const isChildrenMode = "children" in props && props.children != null;
1282
1352
  const data = isChildrenMode ? [] : props.data;
1283
1353
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1291,17 +1361,18 @@ function SingleCombobox(props) {
1291
1361
  const defaultSelectedItemId = props.defaultSelectedItemId;
1292
1362
  const onSelectedItemIdChange = props.onSelectedItemIdChange;
1293
1363
  const { containerRef, portalContainer } = useSeedsPortalContainer();
1294
- const [open, setOpen] = React8.useState(false);
1295
- const virtualizerRef = React8.useRef(null);
1364
+ const [open, setOpen] = React9.useState(false);
1365
+ const virtualizerRef = React9.useRef(null);
1366
+ const onInputKeyDownCapture = useSuppressEscapeClear(open);
1296
1367
  const isControlled = selectedItemId !== void 0;
1297
- const idToItem = React8.useCallback(
1368
+ const idToItem = React9.useCallback(
1298
1369
  (id2) => {
1299
1370
  if (id2 == null) return null;
1300
1371
  return data.find((d) => String(d.id) === String(id2)) ?? null;
1301
1372
  },
1302
1373
  [data]
1303
1374
  );
1304
- const [internalValue, setInternalValue] = React8.useState(
1375
+ const [internalValue, setInternalValue] = React9.useState(
1305
1376
  () => idToItem(defaultSelectedItemId)
1306
1377
  );
1307
1378
  const value = isControlled ? idToItem(selectedItemId) : internalValue;
@@ -1313,11 +1384,11 @@ function SingleCombobox(props) {
1313
1384
  onSelectedItemIdChange(newItem ? newItem.id : null);
1314
1385
  }
1315
1386
  }
1316
- const groups = React8.useMemo(
1387
+ const groups = React9.useMemo(
1317
1388
  () => groupBy ? groupItems(data, groupBy) : null,
1318
1389
  [data, groupBy]
1319
1390
  );
1320
- return /* @__PURE__ */ jsxs6(Field, { children: [
1391
+ return /* @__PURE__ */ jsxs6(Field, { $fullWidth: fullWidth, children: [
1321
1392
  /* @__PURE__ */ jsx8("div", { ref: containerRef, style: { position: "relative" } }),
1322
1393
  /* @__PURE__ */ jsxs6(
1323
1394
  Combobox3.Root,
@@ -1338,29 +1409,38 @@ function SingleCombobox(props) {
1338
1409
  if (!item || !virt) return;
1339
1410
  const isStart = index === 0;
1340
1411
  const isEnd = index === virt.options.count - 1;
1341
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
1412
+ if (reason === "keyboard" && (isStart || isEnd)) {
1342
1413
  queueMicrotask(() => {
1343
1414
  virt.scrollToIndex(index, {
1344
- align: isEnd ? "start" : "end"
1415
+ align: isStart ? "start" : "end"
1345
1416
  });
1346
1417
  });
1347
1418
  }
1348
1419
  } : void 0,
1349
1420
  children: [
1350
- /* @__PURE__ */ jsxs6(ComboboxInputGroup, { children: [
1351
- /* @__PURE__ */ jsx8(
1352
- ComboboxInput,
1353
- {
1354
- placeholder,
1355
- id,
1356
- "aria-describedby": ariaDescribedBy
1357
- }
1358
- ),
1359
- /* @__PURE__ */ jsxs6(ComboboxActionButtons, { children: [
1360
- /* @__PURE__ */ jsx8(ComboboxClear, { "aria-label": "Clear selection", children: /* @__PURE__ */ jsx8(ClearIcon, {}) }),
1361
- /* @__PURE__ */ jsx8(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ jsx8(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ jsx8(ChevronIcon, {}) }) })
1362
- ] })
1363
- ] }),
1421
+ /* @__PURE__ */ jsxs6(
1422
+ ComboboxInputGroup,
1423
+ {
1424
+ $isInvalid: isInvalid,
1425
+ onKeyDownCapture: onInputKeyDownCapture,
1426
+ children: [
1427
+ /* @__PURE__ */ jsx8(
1428
+ ComboboxInput,
1429
+ {
1430
+ placeholder,
1431
+ id,
1432
+ "aria-describedby": ariaDescribedBy,
1433
+ "aria-invalid": isInvalid || void 0,
1434
+ "aria-required": props.required || void 0
1435
+ }
1436
+ ),
1437
+ /* @__PURE__ */ jsxs6(ComboboxActionButtons, { children: [
1438
+ /* @__PURE__ */ jsx8(ComboboxClear, { "aria-label": "Clear selection", children: /* @__PURE__ */ jsx8(ClearIcon, {}) }),
1439
+ /* @__PURE__ */ jsx8(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ jsx8(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ jsx8(ChevronIcon, {}) }) })
1440
+ ] })
1441
+ ]
1442
+ }
1443
+ ),
1364
1444
  /* @__PURE__ */ jsx8(Combobox3.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx8(ComboboxPositioner, { sideOffset: 4, children: /* @__PURE__ */ jsxs6(
1365
1445
  ComboboxPopup,
1366
1446
  {
@@ -1390,7 +1470,7 @@ function SingleCombobox(props) {
1390
1470
  renderItem,
1391
1471
  renderGroupHeading
1392
1472
  }
1393
- ) : children ? children : groups ? (group, index) => /* @__PURE__ */ jsxs6(React8.Fragment, { children: [
1473
+ ) : children ? children : groups ? ((group, index) => /* @__PURE__ */ jsxs6(React9.Fragment, { children: [
1394
1474
  /* @__PURE__ */ jsxs6(ComboboxGroup, { items: group.items, children: [
1395
1475
  /* @__PURE__ */ jsx8(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(group.value) : group.value }),
1396
1476
  /* @__PURE__ */ jsx8(Combobox3.Collection, { children: (item) => /* @__PURE__ */ jsx8(
@@ -1407,7 +1487,7 @@ function SingleCombobox(props) {
1407
1487
  ) })
1408
1488
  ] }),
1409
1489
  index < groups.length - 1 && /* @__PURE__ */ jsx8(ComboboxSeparator, {})
1410
- ] }, group.value) : (item) => /* @__PURE__ */ jsx8(
1490
+ ] }, group.value)) : ((item) => /* @__PURE__ */ jsx8(
1411
1491
  ComboboxItem_default,
1412
1492
  {
1413
1493
  value: item,
@@ -1418,7 +1498,7 @@ function SingleCombobox(props) {
1418
1498
  renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
1419
1499
  },
1420
1500
  item.id
1421
- )
1501
+ ))
1422
1502
  }
1423
1503
  )
1424
1504
  ]
@@ -1431,7 +1511,7 @@ function SingleCombobox(props) {
1431
1511
  }
1432
1512
 
1433
1513
  // src/v3/MultiCombobox.tsx
1434
- import * as React9 from "react";
1514
+ import * as React10 from "react";
1435
1515
  import { Combobox as Combobox4 } from "@base-ui/react/combobox";
1436
1516
  import "@tanstack/react-virtual";
1437
1517
  import Icon3 from "@sproutsocial/seeds-react-icon";
@@ -1455,9 +1535,11 @@ function MultiCombobox(props) {
1455
1535
  loadingText = "Loading...",
1456
1536
  filter,
1457
1537
  inputValue,
1458
- onInputValueChange
1538
+ onInputValueChange,
1539
+ fullWidth = true
1459
1540
  } = props;
1460
1541
  const ariaDescribedBy = props["aria-describedby"];
1542
+ const isInvalid = props.isInvalid;
1461
1543
  const isChildrenMode = "children" in props && props.children != null;
1462
1544
  const data = isChildrenMode ? [] : props.data;
1463
1545
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1481,29 +1563,31 @@ function MultiCombobox(props) {
1481
1563
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
1482
1564
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
1483
1565
  const { containerRef, portalContainer } = useSeedsPortalContainer();
1484
- const [open, setOpen] = React9.useState(false);
1485
- const [internalInputValue, setInternalInputValue] = React9.useState("");
1486
- const skipNextInputChangeRef = React9.useRef(false);
1487
- const virtualizerRef = React9.useRef(null);
1566
+ const [open, setOpen] = React10.useState(false);
1567
+ const [internalInputValue, setInternalInputValue] = React10.useState("");
1568
+ const skipNextInputChangeRef = React10.useRef(false);
1569
+ const virtualizerRef = React10.useRef(null);
1570
+ const inputRef = React10.useRef(null);
1571
+ const onInputKeyDownCapture = useSuppressEscapeClear(open);
1488
1572
  const isControlled = selectedItemIds !== void 0;
1489
- const idsToItems = React9.useCallback(
1573
+ const idsToItems = React10.useCallback(
1490
1574
  (ids) => ids.map((id2) => data.find((d) => d.id === id2)).filter((d) => d != null),
1491
1575
  [data]
1492
1576
  );
1493
- const [internalValue, setInternalValue] = React9.useState(
1577
+ const [internalValue, setInternalValue] = React10.useState(
1494
1578
  () => defaultSelectedItemIds ? idsToItems(defaultSelectedItemIds) : []
1495
1579
  );
1496
1580
  const value = isControlled ? idsToItems(selectedItemIds) : internalValue;
1497
- const visibleData = React9.useMemo(
1581
+ const visibleData = React10.useMemo(
1498
1582
  () => removeSelectedItems ? data.filter((item) => !value.some((v) => v.id === item.id)) : data,
1499
1583
  [data, value, removeSelectedItems]
1500
1584
  );
1501
- const groups = React9.useMemo(
1585
+ const groups = React10.useMemo(
1502
1586
  () => groupBy ? groupItems(visibleData, groupBy) : null,
1503
1587
  [visibleData, groupBy]
1504
1588
  );
1505
1589
  const currentInputValue = inputValue ?? internalInputValue;
1506
- const creatableSentinel = React9.useMemo(() => {
1590
+ const creatableSentinel = React10.useMemo(() => {
1507
1591
  if (!creatableProp) return null;
1508
1592
  const trimmed = currentInputValue.trim();
1509
1593
  if (!trimmed) return null;
@@ -1514,7 +1598,7 @@ function MultiCombobox(props) {
1514
1598
  if (exactExists) return null;
1515
1599
  return makeCreatableSentinel(trimmed);
1516
1600
  }, [creatableProp, currentInputValue, data, itemToString]);
1517
- const flatItems = React9.useMemo(() => {
1601
+ const flatItems = React10.useMemo(() => {
1518
1602
  if (!selectHeadings && !selectAll) return null;
1519
1603
  if (!groups && !selectAll) return null;
1520
1604
  const rows = [];
@@ -1600,6 +1684,7 @@ function MultiCombobox(props) {
1600
1684
  e.preventDefault();
1601
1685
  e.stopPropagation();
1602
1686
  setSelectedItems(value.filter((v) => v.id !== item.id));
1687
+ inputRef.current?.focus();
1603
1688
  }
1604
1689
  function renderSentinelRow(row) {
1605
1690
  if (isSelectAllSentinel2(row)) {
@@ -1670,7 +1755,7 @@ function MultiCombobox(props) {
1670
1755
  const rootItems = creatableSentinel && Array.isArray(baseItems) ? [...baseItems, creatableSentinel] : baseItems;
1671
1756
  const hasSentinels = selectAll || selectHeadings;
1672
1757
  const rootValue = hasSentinels ? [...value] : value;
1673
- return /* @__PURE__ */ jsxs7(Field, { children: [
1758
+ return /* @__PURE__ */ jsxs7(Field, { $fullWidth: fullWidth, children: [
1674
1759
  /* @__PURE__ */ jsx9("div", { ref: containerRef, style: { position: "relative" } }),
1675
1760
  /* @__PURE__ */ jsxs7(
1676
1761
  Combobox4.Root,
@@ -1681,7 +1766,10 @@ function MultiCombobox(props) {
1681
1766
  open,
1682
1767
  disabled: props.disabled,
1683
1768
  onOpenChange: (nextOpen, eventDetails) => {
1684
- if (!nextOpen && eventDetails.reason === "item-press") return;
1769
+ if (!nextOpen && eventDetails.reason === "item-press") {
1770
+ eventDetails.cancel();
1771
+ return;
1772
+ }
1685
1773
  setOpen(nextOpen);
1686
1774
  },
1687
1775
  filter: creatableProp ? (item, query) => {
@@ -1714,10 +1802,10 @@ function MultiCombobox(props) {
1714
1802
  if (!item || !virt) return;
1715
1803
  const isStart = index === 0;
1716
1804
  const isEnd = index === virt.options.count - 1;
1717
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
1805
+ if (reason === "keyboard" && (isStart || isEnd)) {
1718
1806
  queueMicrotask(() => {
1719
1807
  virt.scrollToIndex(index, {
1720
- align: isEnd ? "start" : "end"
1808
+ align: isStart ? "start" : "end"
1721
1809
  });
1722
1810
  });
1723
1811
  }
@@ -1744,42 +1832,52 @@ function MultiCombobox(props) {
1744
1832
  },
1745
1833
  items: rootItems,
1746
1834
  children: [
1747
- /* @__PURE__ */ jsx9(ComboboxTokenInputGroup, { children: /* @__PURE__ */ jsxs7(ComboboxToken, { children: [
1748
- renderSelection ? renderSelection(value) : (() => {
1749
- const visibleTokens = maxTokens != null ? value.slice(0, maxTokens) : value;
1750
- const overflow = maxTokens != null ? value.length - maxTokens : 0;
1751
- return /* @__PURE__ */ jsxs7(Fragment6, { children: [
1752
- visibleTokens.map((item) => /* @__PURE__ */ jsxs7(Token, { children: [
1753
- renderToken ? renderToken(item) : itemToString(item),
1754
- /* @__PURE__ */ jsx9(
1755
- TokenRemove,
1756
- {
1757
- "aria-label": `Remove ${itemToString(item)}`,
1758
- onPointerDown: (e) => e.preventDefault(),
1759
- onClick: (e) => removeItem(item, e),
1760
- children: /* @__PURE__ */ jsx9(Icon3, { name: "x-outline", size: "mini" })
1761
- }
1762
- )
1763
- ] }, item.id)),
1764
- overflow > 0 && /* @__PURE__ */ jsxs7(Token, { children: [
1765
- "+",
1766
- overflow
1767
- ] }, "__overflow")
1768
- ] });
1769
- })(),
1770
- /* @__PURE__ */ jsx9(
1771
- ComboboxTokenInput,
1772
- {
1773
- id,
1774
- placeholder: value.length > 0 ? "" : placeholder,
1775
- "aria-describedby": ariaDescribedBy
1776
- }
1777
- ),
1778
- /* @__PURE__ */ jsxs7(ComboboxActionButtons, { children: [
1779
- /* @__PURE__ */ jsx9(ComboboxClear, { "aria-label": "Clear all", children: /* @__PURE__ */ jsx9(ClearIcon, {}) }),
1780
- /* @__PURE__ */ jsx9(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ jsx9(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ jsx9(ChevronIcon, {}) }) })
1781
- ] })
1782
- ] }) }),
1835
+ /* @__PURE__ */ jsx9(
1836
+ ComboboxTokenInputGroup,
1837
+ {
1838
+ $isInvalid: isInvalid,
1839
+ onKeyDownCapture: onInputKeyDownCapture,
1840
+ children: /* @__PURE__ */ jsxs7(ComboboxToken, { children: [
1841
+ renderSelection ? renderSelection(value) : (() => {
1842
+ const visibleTokens = maxTokens != null ? value.slice(0, maxTokens) : value;
1843
+ const overflow = maxTokens != null ? value.length - maxTokens : 0;
1844
+ return /* @__PURE__ */ jsxs7(Fragment6, { children: [
1845
+ visibleTokens.map((item) => /* @__PURE__ */ jsxs7(Token, { children: [
1846
+ renderToken ? renderToken(item) : itemToString(item),
1847
+ /* @__PURE__ */ jsx9(
1848
+ TokenRemove,
1849
+ {
1850
+ "aria-label": `Remove ${itemToString(item)}`,
1851
+ onPointerDown: (e) => e.preventDefault(),
1852
+ onClick: (e) => removeItem(item, e),
1853
+ children: /* @__PURE__ */ jsx9(Icon3, { name: "x-outline", size: "mini" })
1854
+ }
1855
+ )
1856
+ ] }, item.id)),
1857
+ overflow > 0 && /* @__PURE__ */ jsxs7(Token, { children: [
1858
+ "+",
1859
+ overflow
1860
+ ] }, "__overflow")
1861
+ ] });
1862
+ })(),
1863
+ /* @__PURE__ */ jsx9(
1864
+ ComboboxTokenInput,
1865
+ {
1866
+ ref: inputRef,
1867
+ id,
1868
+ placeholder: value.length > 0 ? "" : placeholder,
1869
+ "aria-describedby": ariaDescribedBy,
1870
+ "aria-invalid": isInvalid || void 0,
1871
+ "aria-required": props.required || void 0
1872
+ }
1873
+ ),
1874
+ /* @__PURE__ */ jsxs7(ComboboxActionButtons, { children: [
1875
+ /* @__PURE__ */ jsx9(ComboboxClear, { "aria-label": "Clear all", children: /* @__PURE__ */ jsx9(ClearIcon, {}) }),
1876
+ /* @__PURE__ */ jsx9(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ jsx9(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ jsx9(ChevronIcon, {}) }) })
1877
+ ] })
1878
+ ] })
1879
+ }
1880
+ ),
1783
1881
  /* @__PURE__ */ jsx9(Combobox4.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx9(ComboboxPositioner, { sideOffset: 4, children: /* @__PURE__ */ jsxs7(
1784
1882
  ComboboxPopup,
1785
1883
  {
@@ -1817,12 +1915,12 @@ function MultiCombobox(props) {
1817
1915
  measureRef
1818
1916
  ) : void 0
1819
1917
  }
1820
- ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
1918
+ ) : children ? children : flatItems ? ((row) => renderSentinelRow(row)) : groups ? ((group, index) => {
1821
1919
  if (isCreatableSentinel(group)) {
1822
1920
  return renderCreatableItem(group);
1823
1921
  }
1824
1922
  const g = group;
1825
- return /* @__PURE__ */ jsxs7(React9.Fragment, { children: [
1923
+ return /* @__PURE__ */ jsxs7(React10.Fragment, { children: [
1826
1924
  /* @__PURE__ */ jsxs7(ComboboxGroup, { items: g.items, children: [
1827
1925
  /* @__PURE__ */ jsx9(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
1828
1926
  /* @__PURE__ */ jsx9(Combobox4.Collection, { children: (item) => /* @__PURE__ */ jsx9(
@@ -1840,7 +1938,7 @@ function MultiCombobox(props) {
1840
1938
  ] }),
1841
1939
  index < groups.length - 1 && /* @__PURE__ */ jsx9(ComboboxSeparator, {})
1842
1940
  ] }, g.value);
1843
- } : (item) => {
1941
+ }) : ((item) => {
1844
1942
  if (isCreatableSentinel(item)) {
1845
1943
  return renderCreatableItem(item);
1846
1944
  }
@@ -1857,7 +1955,7 @@ function MultiCombobox(props) {
1857
1955
  },
1858
1956
  dataItem.id
1859
1957
  );
1860
- }
1958
+ })
1861
1959
  }
1862
1960
  )
1863
1961
  ]
@@ -1870,7 +1968,7 @@ function MultiCombobox(props) {
1870
1968
  }
1871
1969
 
1872
1970
  // src/v3/SingleSearchableSelect.tsx
1873
- import * as React10 from "react";
1971
+ import * as React11 from "react";
1874
1972
  import { Combobox as Combobox5 } from "@base-ui/react/combobox";
1875
1973
  import "@tanstack/react-virtual";
1876
1974
  import { Fragment as Fragment8, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
@@ -1883,9 +1981,11 @@ function SingleSearchableSelect(props) {
1883
1981
  emptyText = "No results found.",
1884
1982
  isLoading = false,
1885
1983
  loadingText = "Loading...",
1886
- filter
1984
+ filter,
1985
+ fullWidth = true
1887
1986
  } = props;
1888
1987
  const ariaDescribedBy = props["aria-describedby"];
1988
+ const isInvalid = props.isInvalid;
1889
1989
  const isChildrenMode = "children" in props && props.children != null;
1890
1990
  const data = isChildrenMode ? [] : props.data;
1891
1991
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1900,17 +2000,17 @@ function SingleSearchableSelect(props) {
1900
2000
  const defaultSelectedItemId = props.defaultSelectedItemId;
1901
2001
  const onSelectedItemIdChange = props.onSelectedItemIdChange;
1902
2002
  const { containerRef, portalContainer } = useSeedsPortalContainer();
1903
- const [open, setOpen] = React10.useState(false);
1904
- const virtualizerRef = React10.useRef(null);
2003
+ const [open, setOpen] = React11.useState(false);
2004
+ const virtualizerRef = React11.useRef(null);
1905
2005
  const isControlled = selectedItemId !== void 0;
1906
- const idToItem = React10.useCallback(
2006
+ const idToItem = React11.useCallback(
1907
2007
  (id2) => {
1908
2008
  if (id2 == null) return null;
1909
2009
  return data.find((d) => String(d.id) === String(id2)) ?? null;
1910
2010
  },
1911
2011
  [data]
1912
2012
  );
1913
- const [internalValue, setInternalValue] = React10.useState(
2013
+ const [internalValue, setInternalValue] = React11.useState(
1914
2014
  () => idToItem(defaultSelectedItemId)
1915
2015
  );
1916
2016
  const value = isControlled ? idToItem(selectedItemId) : internalValue;
@@ -1921,11 +2021,11 @@ function SingleSearchableSelect(props) {
1921
2021
  onSelectedItemIdChange(realItem ? realItem.id : null);
1922
2022
  }
1923
2023
  }
1924
- const groups = React10.useMemo(
2024
+ const groups = React11.useMemo(
1925
2025
  () => groupBy ? groupItems(data, groupBy) : null,
1926
2026
  [data, groupBy]
1927
2027
  );
1928
- return /* @__PURE__ */ jsxs8(Field, { children: [
2028
+ return /* @__PURE__ */ jsxs8(Field, { $fullWidth: fullWidth, children: [
1929
2029
  /* @__PURE__ */ jsx10("div", { ref: containerRef, style: { position: "relative" } }),
1930
2030
  /* @__PURE__ */ jsxs8(
1931
2031
  Combobox5.Root,
@@ -1951,19 +2051,29 @@ function SingleSearchableSelect(props) {
1951
2051
  if (!item || !virt) return;
1952
2052
  const isStart = index === 0;
1953
2053
  const isEnd = index === virt.options.count - 1;
1954
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
2054
+ if (reason === "keyboard" && (isStart || isEnd)) {
1955
2055
  queueMicrotask(() => {
1956
2056
  virt.scrollToIndex(index, {
1957
- align: isEnd ? "start" : "end"
2057
+ align: isStart ? "start" : "end"
1958
2058
  });
1959
2059
  });
1960
2060
  }
1961
2061
  } : void 0,
1962
2062
  children: [
1963
- /* @__PURE__ */ jsxs8(SearchableSelectTrigger, { id, "aria-describedby": ariaDescribedBy, children: [
1964
- /* @__PURE__ */ jsx10(SearchableSelectPlaceholder, { children: /* @__PURE__ */ jsx10(Combobox5.Value, { placeholder, children: value ? renderSelection ? renderSelection(value) : itemToString(value) : placeholder }) }),
1965
- /* @__PURE__ */ jsx10(SearchableSelectTriggerIcon, { children: /* @__PURE__ */ jsx10(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ jsx10(ChevronIcon, {}) }) })
1966
- ] }),
2063
+ /* @__PURE__ */ jsxs8(
2064
+ SearchableSelectTrigger,
2065
+ {
2066
+ id,
2067
+ "aria-describedby": ariaDescribedBy,
2068
+ "aria-invalid": isInvalid || void 0,
2069
+ "aria-required": props.required || void 0,
2070
+ $isInvalid: isInvalid,
2071
+ children: [
2072
+ /* @__PURE__ */ jsx10(SearchableSelectPlaceholder, { children: /* @__PURE__ */ jsx10(Combobox5.Value, { placeholder, children: value ? renderSelection ? renderSelection(value) : itemToString(value) : placeholder }) }),
2073
+ /* @__PURE__ */ jsx10(SearchableSelectTriggerIcon, { children: /* @__PURE__ */ jsx10(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ jsx10(ChevronIcon, {}) }) })
2074
+ ]
2075
+ }
2076
+ ),
1967
2077
  /* @__PURE__ */ jsx10(Combobox5.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx10(ComboboxPositioner, { sideOffset: 4, children: /* @__PURE__ */ jsxs8(
1968
2078
  SearchableSelectPopup,
1969
2079
  {
@@ -2001,7 +2111,7 @@ function SingleSearchableSelect(props) {
2001
2111
  inputType,
2002
2112
  renderItem
2003
2113
  }
2004
- ) : children ? children : groups ? (group, index) => /* @__PURE__ */ jsxs8(React10.Fragment, { children: [
2114
+ ) : children ? children : groups ? ((group, index) => /* @__PURE__ */ jsxs8(React11.Fragment, { children: [
2005
2115
  /* @__PURE__ */ jsxs8(ComboboxGroup, { items: group.items, children: [
2006
2116
  /* @__PURE__ */ jsx10(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(group.value) : group.value }),
2007
2117
  /* @__PURE__ */ jsx10(Combobox5.Collection, { children: (item) => /* @__PURE__ */ jsx10(
@@ -2018,7 +2128,7 @@ function SingleSearchableSelect(props) {
2018
2128
  ) })
2019
2129
  ] }),
2020
2130
  index < groups.length - 1 && /* @__PURE__ */ jsx10(ComboboxSeparator, {})
2021
- ] }, group.value) : /* @__PURE__ */ jsxs8(Fragment8, { children: [
2131
+ ] }, group.value)) : /* @__PURE__ */ jsxs8(Fragment8, { children: [
2022
2132
  includePlaceholderItem && /* @__PURE__ */ jsx10(
2023
2133
  ComboboxItem_default,
2024
2134
  {
@@ -2054,7 +2164,7 @@ function SingleSearchableSelect(props) {
2054
2164
  }
2055
2165
 
2056
2166
  // src/v3/MultiSearchableSelect.tsx
2057
- import * as React11 from "react";
2167
+ import * as React12 from "react";
2058
2168
  import { Combobox as Combobox6 } from "@base-ui/react/combobox";
2059
2169
  import "@tanstack/react-virtual";
2060
2170
  import Icon4 from "@sproutsocial/seeds-react-icon";
@@ -2084,9 +2194,11 @@ function MultiSearchableSelect(props) {
2084
2194
  emptyText = "No results found.",
2085
2195
  isLoading = false,
2086
2196
  loadingText = "Loading...",
2087
- filter
2197
+ filter,
2198
+ fullWidth = true
2088
2199
  } = props;
2089
2200
  const ariaDescribedBy = props["aria-describedby"];
2201
+ const isInvalid = props.isInvalid;
2090
2202
  const isChildrenMode = "children" in props && props.children != null;
2091
2203
  const data = isChildrenMode ? [] : props.data;
2092
2204
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -2108,29 +2220,29 @@ function MultiSearchableSelect(props) {
2108
2220
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
2109
2221
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
2110
2222
  const { containerRef, portalContainer } = useSeedsPortalContainer();
2111
- const [open, setOpen] = React11.useState(false);
2112
- const [internalInputValue, setInternalInputValue] = React11.useState("");
2113
- const skipNextInputChangeRef = React11.useRef(false);
2114
- const virtualizerRef = React11.useRef(null);
2223
+ const [open, setOpen] = React12.useState(false);
2224
+ const [internalInputValue, setInternalInputValue] = React12.useState("");
2225
+ const skipNextInputChangeRef = React12.useRef(false);
2226
+ const virtualizerRef = React12.useRef(null);
2115
2227
  const isControlled = selectedItemIds !== void 0;
2116
- const idsToItems = React11.useCallback(
2228
+ const idsToItems = React12.useCallback(
2117
2229
  (ids) => ids.map((id2) => data.find((d) => d.id === id2)).filter((d) => d != null),
2118
2230
  [data]
2119
2231
  );
2120
- const [internalValue, setInternalValue] = React11.useState(
2232
+ const [internalValue, setInternalValue] = React12.useState(
2121
2233
  () => defaultSelectedItemIds ? idsToItems(defaultSelectedItemIds) : []
2122
2234
  );
2123
2235
  const value = isControlled ? idsToItems(selectedItemIds) : internalValue;
2124
- const visibleData = React11.useMemo(
2236
+ const visibleData = React12.useMemo(
2125
2237
  () => removeSelectedItems ? data.filter((item) => !value.some((v) => v.id === item.id)) : data,
2126
2238
  [data, value, removeSelectedItems]
2127
2239
  );
2128
- const groups = React11.useMemo(
2240
+ const groups = React12.useMemo(
2129
2241
  () => groupBy ? groupItems(visibleData, groupBy) : null,
2130
2242
  [visibleData, groupBy]
2131
2243
  );
2132
2244
  const currentInputValue = internalInputValue;
2133
- const creatableSentinel = React11.useMemo(() => {
2245
+ const creatableSentinel = React12.useMemo(() => {
2134
2246
  if (!creatableProp) return null;
2135
2247
  const trimmed = currentInputValue.trim();
2136
2248
  if (!trimmed) return null;
@@ -2141,7 +2253,7 @@ function MultiSearchableSelect(props) {
2141
2253
  if (exactExists) return null;
2142
2254
  return makeCreatableSentinel(trimmed);
2143
2255
  }, [creatableProp, currentInputValue, data, itemToString]);
2144
- const flatItems = React11.useMemo(() => {
2256
+ const flatItems = React12.useMemo(() => {
2145
2257
  if (!groups || !selectHeadings && !selectAll) return null;
2146
2258
  const rows = [];
2147
2259
  if (selectAll) rows.push(SELECT_ALL_SENTINEL2);
@@ -2285,7 +2397,7 @@ function MultiSearchableSelect(props) {
2285
2397
  const rootItems = creatableSentinel && Array.isArray(baseItems) ? [...baseItems, creatableSentinel] : baseItems;
2286
2398
  const hasSentinels = selectAll || selectHeadings;
2287
2399
  const rootValue = hasSentinels ? [...value] : value;
2288
- return /* @__PURE__ */ jsxs9(Field, { children: [
2400
+ return /* @__PURE__ */ jsxs9(Field, { $fullWidth: fullWidth, children: [
2289
2401
  /* @__PURE__ */ jsx11("div", { ref: containerRef, style: { position: "relative" } }),
2290
2402
  /* @__PURE__ */ jsxs9(
2291
2403
  Combobox6.Root,
@@ -2318,10 +2430,10 @@ function MultiSearchableSelect(props) {
2318
2430
  if (!item || !virt) return;
2319
2431
  const isStart = index === 0;
2320
2432
  const isEnd = index === virt.options.count - 1;
2321
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
2433
+ if (reason === "keyboard" && (isStart || isEnd)) {
2322
2434
  queueMicrotask(() => {
2323
2435
  virt.scrollToIndex(index, {
2324
- align: isEnd ? "start" : "end"
2436
+ align: isStart ? "start" : "end"
2325
2437
  });
2326
2438
  });
2327
2439
  }
@@ -2353,6 +2465,9 @@ function MultiSearchableSelect(props) {
2353
2465
  {
2354
2466
  id,
2355
2467
  "aria-describedby": ariaDescribedBy,
2468
+ "aria-invalid": isInvalid || void 0,
2469
+ "aria-required": props.required || void 0,
2470
+ $isInvalid: isInvalid,
2356
2471
  children: [
2357
2472
  renderSelection ? renderSelection(value) : value.length > 0 ? (() => {
2358
2473
  const visibleItems = maxSelections != null ? value.slice(0, maxSelections) : value;
@@ -2413,12 +2528,12 @@ function MultiSearchableSelect(props) {
2413
2528
  measureRef
2414
2529
  ) : void 0
2415
2530
  }
2416
- ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
2531
+ ) : children ? children : flatItems ? ((row) => renderSentinelRow(row)) : groups ? ((group, index) => {
2417
2532
  if (isCreatableSentinel(group)) {
2418
2533
  return renderCreatableItem(group);
2419
2534
  }
2420
2535
  const g = group;
2421
- return /* @__PURE__ */ jsxs9(React11.Fragment, { children: [
2536
+ return /* @__PURE__ */ jsxs9(React12.Fragment, { children: [
2422
2537
  /* @__PURE__ */ jsxs9(ComboboxGroup, { items: g.items, children: [
2423
2538
  /* @__PURE__ */ jsx11(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
2424
2539
  /* @__PURE__ */ jsx11(Combobox6.Collection, { children: (item) => /* @__PURE__ */ jsx11(
@@ -2436,7 +2551,7 @@ function MultiSearchableSelect(props) {
2436
2551
  ] }),
2437
2552
  index < groups.length - 1 && /* @__PURE__ */ jsx11(ComboboxSeparator, {})
2438
2553
  ] }, g.value);
2439
- } : (item) => {
2554
+ }) : ((item) => {
2440
2555
  if (isCreatableSentinel(item)) {
2441
2556
  return renderCreatableItem(item);
2442
2557
  }
@@ -2453,7 +2568,7 @@ function MultiSearchableSelect(props) {
2453
2568
  },
2454
2569
  dataItem.id
2455
2570
  );
2456
- }
2571
+ })
2457
2572
  }
2458
2573
  )
2459
2574
  ]
@@ -2464,7 +2579,426 @@ function MultiSearchableSelect(props) {
2464
2579
  )
2465
2580
  ] });
2466
2581
  }
2582
+
2583
+ // src/v3/ActionMenu.tsx
2584
+ import * as React13 from "react";
2585
+ import { Menu as Menu2 } from "@base-ui/react/menu";
2586
+ import Radio3 from "@sproutsocial/seeds-react-radio";
2587
+ import Checkbox4 from "@sproutsocial/seeds-react-checkbox";
2588
+ import { Icon as Icon5 } from "@sproutsocial/seeds-react-icon";
2589
+
2590
+ // src/v3/ActionMenuStyles.tsx
2591
+ import { Menu } from "@base-ui/react/menu";
2592
+ import styled8, { css as css3 } from "styled-components";
2593
+ import "@sproutsocial/seeds-react-mixins";
2594
+ var ActionMenuTrigger = styled8(Menu.Trigger)``;
2595
+ var ActionMenuPositioner = styled8(Menu.Positioner)`
2596
+ min-width: var(--anchor-width);
2597
+ z-index: 7;
2598
+ `;
2599
+ var ActionMenuPopup = styled8(Menu.Popup).attrs({
2600
+ "data-base-ui-swipe-ignore": ""
2601
+ })`
2602
+ font-family: ${({ theme }) => theme.fontFamily};
2603
+ background: ${({ theme }) => theme.colors.container.background.base};
2604
+ border: 1px solid ${({ theme }) => theme.colors.container.border.base};
2605
+ border-radius: ${({ theme }) => theme.radii[500]};
2606
+ box-shadow: ${({ theme }) => theme.shadows.low};
2607
+ outline: none;
2608
+ max-height: min(var(--available-height, 400px), 400px);
2609
+ overflow-y: auto;
2610
+ padding: ${({ theme }) => theme.space[300]};
2611
+
2612
+ &[data-open] {
2613
+ animation: action-menu-popup-in 120ms ease-out;
2614
+ }
2615
+
2616
+ &[data-closed] {
2617
+ animation: action-menu-popup-out 100ms ease-in;
2618
+ }
2619
+
2620
+ @keyframes action-menu-popup-in {
2621
+ from {
2622
+ opacity: 0;
2623
+ transform: scale(0.95);
2624
+ }
2625
+ to {
2626
+ opacity: 1;
2627
+ transform: scale(1);
2628
+ }
2629
+ }
2630
+
2631
+ @keyframes action-menu-popup-out {
2632
+ from {
2633
+ opacity: 1;
2634
+ transform: scale(1);
2635
+ }
2636
+ to {
2637
+ opacity: 0;
2638
+ transform: scale(0.95);
2639
+ }
2640
+ }
2641
+ `;
2642
+ var ActionMenuGroup = styled8(Menu.Group)`
2643
+ display: block;
2644
+ `;
2645
+ var ActionMenuGroupLabel = styled8(Menu.GroupLabel)`
2646
+ padding: ${({ theme }) => `${theme.space[300]}`};
2647
+ font-size: ${({ theme }) => theme.typography[100].fontSize};
2648
+ color: ${({ theme }) => theme.colors.text.body};
2649
+ `;
2650
+ var ActionMenuSeparator = styled8(Menu.Separator)`
2651
+ height: 1px;
2652
+ margin: ${({ theme }) => `${theme.space[300]} -${theme.space[300]}`};
2653
+ background: ${({ theme }) => theme.colors.container.border.base};
2654
+ `;
2655
+ var menuItemStyles = css3`
2656
+ box-sizing: border-box;
2657
+ display: block;
2658
+ width: 100%;
2659
+ border-radius: ${({ theme }) => theme.radii[500]};
2660
+ background-color: ${({ theme }) => theme.colors.listItem.background.base};
2661
+ border: 1px solid ${({ theme }) => theme.colors.listItem.background.base};
2662
+ color: ${({ theme }) => theme.colors.text.body};
2663
+ font-family: ${({ theme }) => theme.fontFamily};
2664
+ font-weight: ${({ theme }) => theme.fontWeights.normal};
2665
+ text-align: left;
2666
+ text-decoration: none;
2667
+ padding: ${({ theme }) => theme.space[300]};
2668
+ outline: 0;
2669
+ ${({ theme }) => theme.typography[200]};
2670
+ transition: all ${({ theme }) => theme.duration.fast};
2671
+ cursor: pointer;
2672
+ user-select: none;
2673
+
2674
+ &[data-highlighted] {
2675
+ border-color: ${({ theme }) => theme.colors.listItem.border.base};
2676
+ background-color: ${({ theme }) => theme.colors.listItem.background.hover};
2677
+ color: ${({ theme }) => theme.colors.text.body};
2678
+ text-decoration: none;
2679
+ }
2680
+
2681
+ &[data-disabled] {
2682
+ cursor: not-allowed;
2683
+ opacity: 0.4;
2684
+ }
2685
+ `;
2686
+ var StyledMenuItem = styled8(Menu.Item)`
2687
+ ${menuItemStyles}
2688
+ `;
2689
+ var StyledCheckboxItem = styled8(Menu.CheckboxItem)`
2690
+ ${menuItemStyles}
2691
+ display: flex;
2692
+ align-items: center;
2693
+ gap: ${({ theme }) => theme.space[300]};
2694
+ `;
2695
+ var StyledRadioItem = styled8(Menu.RadioItem)`
2696
+ ${menuItemStyles}
2697
+ display: flex;
2698
+ align-items: center;
2699
+ gap: ${({ theme }) => theme.space[300]};
2700
+ `;
2701
+ var StyledCheckboxItemIndicator = styled8(Menu.CheckboxItemIndicator)`
2702
+ display: flex;
2703
+ align-items: center;
2704
+ width: 16px;
2705
+ color: ${({ theme }) => theme.colors.text.body};
2706
+ `;
2707
+ var StyledRadioItemIndicator = styled8(Menu.RadioItemIndicator)`
2708
+ display: flex;
2709
+ align-items: center;
2710
+ width: 16px;
2711
+ color: ${({ theme }) => theme.colors.text.body};
2712
+ `;
2713
+ var StyledSubmenuTrigger = styled8(Menu.SubmenuTrigger)`
2714
+ ${menuItemStyles}
2715
+ display: flex;
2716
+ align-items: center;
2717
+ gap: ${({ theme }) => theme.space[300]};
2718
+ justify-content: space-between;
2719
+
2720
+ &[data-popup-open] {
2721
+ border-color: ${({ theme }) => theme.colors.listItem.border.base};
2722
+ background-color: ${({ theme }) => theme.colors.listItem.background.hover};
2723
+ }
2724
+ `;
2725
+ var StyledLinkItem = styled8(Menu.LinkItem)`
2726
+ ${menuItemStyles}
2727
+ `;
2728
+
2729
+ // src/v3/ActionMenu.tsx
2730
+ import { Fragment as Fragment11, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
2731
+ function ActionMenu({
2732
+ trigger,
2733
+ children,
2734
+ open,
2735
+ defaultOpen,
2736
+ onOpenChange,
2737
+ disabled
2738
+ }) {
2739
+ const { containerRef, portalContainer } = useSeedsPortalContainer();
2740
+ return /* @__PURE__ */ jsxs10(
2741
+ Menu2.Root,
2742
+ {
2743
+ open,
2744
+ defaultOpen,
2745
+ onOpenChange,
2746
+ children: [
2747
+ /* @__PURE__ */ jsx12("div", { ref: containerRef, style: { position: "relative" } }),
2748
+ /* @__PURE__ */ jsx12(ActionMenuTrigger, { render: trigger, disabled }),
2749
+ /* @__PURE__ */ jsx12(Menu2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx12(ActionMenuPositioner, { sideOffset: 8, children: /* @__PURE__ */ jsx12(ActionMenuPopup, { children }) }) })
2750
+ ]
2751
+ }
2752
+ );
2753
+ }
2754
+ function MenuGroup({
2755
+ children,
2756
+ label,
2757
+ showSeparator = false
2758
+ }) {
2759
+ return /* @__PURE__ */ jsxs10(Fragment11, { children: [
2760
+ /* @__PURE__ */ jsxs10(ActionMenuGroup, { children: [
2761
+ label && /* @__PURE__ */ jsx12(ActionMenuGroupLabel, { children: label }),
2762
+ children
2763
+ ] }),
2764
+ showSeparator && /* @__PURE__ */ jsx12(ActionMenuSeparator, {})
2765
+ ] });
2766
+ }
2767
+ function MenuRadioGroup({
2768
+ children,
2769
+ value,
2770
+ defaultValue,
2771
+ onValueChange
2772
+ }) {
2773
+ return /* @__PURE__ */ jsx12(
2774
+ Menu2.RadioGroup,
2775
+ {
2776
+ value,
2777
+ defaultValue,
2778
+ onValueChange,
2779
+ children
2780
+ }
2781
+ );
2782
+ }
2783
+ function MenuItem(props) {
2784
+ const generatedId = React13.useId();
2785
+ if (props.type === "checkbox") {
2786
+ const {
2787
+ children: children2,
2788
+ checked,
2789
+ defaultChecked,
2790
+ onCheckedChange,
2791
+ disabled: disabled2,
2792
+ closeOnClick: closeOnClick2 = false,
2793
+ id
2794
+ } = props;
2795
+ const itemId = id ?? `checkbox-menu-item-${generatedId}`;
2796
+ return /* @__PURE__ */ jsxs10(
2797
+ StyledCheckboxItem,
2798
+ {
2799
+ checked,
2800
+ defaultChecked,
2801
+ onCheckedChange,
2802
+ disabled: disabled2,
2803
+ closeOnClick: closeOnClick2,
2804
+ children: [
2805
+ /* @__PURE__ */ jsx12(
2806
+ StyledCheckboxItemIndicator,
2807
+ {
2808
+ keepMounted: true,
2809
+ render: (_indicatorProps, state) => /* @__PURE__ */ jsx12(
2810
+ Checkbox4,
2811
+ {
2812
+ checked: state.checked,
2813
+ onChange: () => {
2814
+ },
2815
+ tabIndex: -1,
2816
+ id: itemId,
2817
+ name: "menu-checkbox-item"
2818
+ }
2819
+ )
2820
+ }
2821
+ ),
2822
+ children2
2823
+ ]
2824
+ }
2825
+ );
2826
+ }
2827
+ if (props.type === "radio") {
2828
+ const { children: children2, value, disabled: disabled2, closeOnClick: closeOnClick2 = false } = props;
2829
+ return /* @__PURE__ */ jsxs10(
2830
+ StyledRadioItem,
2831
+ {
2832
+ value,
2833
+ disabled: disabled2,
2834
+ closeOnClick: closeOnClick2,
2835
+ children: [
2836
+ /* @__PURE__ */ jsx12(
2837
+ StyledRadioItemIndicator,
2838
+ {
2839
+ keepMounted: true,
2840
+ render: (_indicatorProps, state) => /* @__PURE__ */ jsx12(
2841
+ Radio3,
2842
+ {
2843
+ checked: state.checked,
2844
+ onChange: () => {
2845
+ },
2846
+ tabIndex: -1,
2847
+ id: `radio-menu-item-${value}`,
2848
+ name: "menu-radio-item"
2849
+ }
2850
+ )
2851
+ }
2852
+ ),
2853
+ children2
2854
+ ]
2855
+ }
2856
+ );
2857
+ }
2858
+ const {
2859
+ children,
2860
+ onClick,
2861
+ disabled,
2862
+ closeOnClick = true,
2863
+ href,
2864
+ target
2865
+ } = props;
2866
+ if (href) {
2867
+ return /* @__PURE__ */ jsx12(StyledLinkItem, { href, target, closeOnClick, children });
2868
+ }
2869
+ return /* @__PURE__ */ jsx12(
2870
+ StyledMenuItem,
2871
+ {
2872
+ onClick,
2873
+ disabled,
2874
+ closeOnClick,
2875
+ children
2876
+ }
2877
+ );
2878
+ }
2879
+ function MenuSub({
2880
+ trigger,
2881
+ children,
2882
+ open,
2883
+ defaultOpen,
2884
+ onOpenChange,
2885
+ closeParentOnEsc = false
2886
+ }) {
2887
+ const { containerRef, portalContainer } = useSeedsPortalContainer();
2888
+ return /* @__PURE__ */ jsxs10(
2889
+ Menu2.SubmenuRoot,
2890
+ {
2891
+ open,
2892
+ defaultOpen,
2893
+ onOpenChange,
2894
+ closeParentOnEsc,
2895
+ children: [
2896
+ /* @__PURE__ */ jsx12("div", { ref: containerRef, style: { position: "relative" } }),
2897
+ trigger,
2898
+ /* @__PURE__ */ jsx12(Menu2.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx12(ActionMenuPositioner, { sideOffset: getOffset, alignOffset: getOffset, children: /* @__PURE__ */ jsx12(ActionMenuPopup, { children }) }) })
2899
+ ]
2900
+ }
2901
+ );
2902
+ }
2903
+ function getOffset({ side }) {
2904
+ return side === "top" || side === "bottom" ? 4 : -8;
2905
+ }
2906
+ function MenuSubTrigger({
2907
+ children,
2908
+ disabled,
2909
+ label,
2910
+ openOnHover = true
2911
+ }) {
2912
+ return /* @__PURE__ */ jsxs10(
2913
+ StyledSubmenuTrigger,
2914
+ {
2915
+ disabled,
2916
+ label,
2917
+ openOnHover,
2918
+ children: [
2919
+ children,
2920
+ /* @__PURE__ */ jsx12(Icon5, { name: "chevron-right-outline", fixedWidth: true, "aria-hidden": true })
2921
+ ]
2922
+ }
2923
+ );
2924
+ }
2925
+
2926
+ // src/v3/MenuButton.tsx
2927
+ import "react";
2928
+ import "@sproutsocial/seeds-react-button";
2929
+ import { Icon as Icon6 } from "@sproutsocial/seeds-react-icon";
2930
+
2931
+ // src/v3/MenuButtonStyles.tsx
2932
+ import styled9 from "styled-components";
2933
+ import { Button } from "@sproutsocial/seeds-react-button";
2934
+ var MenuButtonContainer = styled9.div`
2935
+ display: inline-flex;
2936
+ gap: 1px;
2937
+ `;
2938
+ var MainButton = styled9(Button)`
2939
+ && {
2940
+ border-top-right-radius: 0;
2941
+ border-bottom-right-radius: 0;
2942
+ }
2943
+ `;
2944
+ var TriggerButton = styled9(Button)`
2945
+ && {
2946
+ border-top-left-radius: 0;
2947
+ border-bottom-left-radius: 0;
2948
+ }
2949
+
2950
+ .Icon-svg {
2951
+ transition: transform ${({ theme }) => theme.duration.fast} ease;
2952
+ }
2953
+
2954
+ &[data-popup-open] .Icon-svg {
2955
+ transform: rotate(180deg);
2956
+ }
2957
+ `;
2958
+
2959
+ // src/v3/MenuButton.tsx
2960
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
2961
+ function MenuButton({
2962
+ actionMenu,
2963
+ appearance = "primary",
2964
+ size,
2965
+ disabled,
2966
+ menuButtonAriaLabel,
2967
+ children,
2968
+ ...rest
2969
+ }) {
2970
+ return /* @__PURE__ */ jsxs11(MenuButtonContainer, { children: [
2971
+ /* @__PURE__ */ jsx13(
2972
+ MainButton,
2973
+ {
2974
+ appearance,
2975
+ size,
2976
+ disabled,
2977
+ ...rest,
2978
+ children
2979
+ }
2980
+ ),
2981
+ /* @__PURE__ */ jsx13(
2982
+ ActionMenu,
2983
+ {
2984
+ disabled,
2985
+ trigger: /* @__PURE__ */ jsx13(
2986
+ TriggerButton,
2987
+ {
2988
+ appearance,
2989
+ size,
2990
+ disabled,
2991
+ ariaLabel: menuButtonAriaLabel,
2992
+ children: /* @__PURE__ */ jsx13(Icon6, { name: "chevron-down-outline", fixedWidth: true, "aria-hidden": true })
2993
+ }
2994
+ ),
2995
+ children: actionMenu
2996
+ }
2997
+ )
2998
+ ] });
2999
+ }
2467
3000
  export {
3001
+ ActionMenu,
2468
3002
  ComboboxActionButtons,
2469
3003
  ComboboxClear,
2470
3004
  ComboboxEmpty,
@@ -2487,6 +3021,12 @@ export {
2487
3021
  ComboboxTokenInput,
2488
3022
  ComboboxTokenInputGroup,
2489
3023
  ComboboxTrigger,
3024
+ MenuButton,
3025
+ MenuGroup,
3026
+ MenuItem,
3027
+ MenuRadioGroup,
3028
+ MenuSub,
3029
+ MenuSubTrigger,
2490
3030
  MultiCombobox,
2491
3031
  MultiSearchableSelect,
2492
3032
  MultiSelect,