@sproutsocial/seeds-react-menu 1.13.0 → 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.
package/dist/v3/index.js CHANGED
@@ -53,6 +53,7 @@ __export(v3_exports, {
53
53
  ComboboxTokenInput: () => ComboboxTokenInput,
54
54
  ComboboxTokenInputGroup: () => ComboboxTokenInputGroup,
55
55
  ComboboxTrigger: () => ComboboxTrigger,
56
+ MenuButton: () => MenuButton,
56
57
  MenuGroup: () => MenuGroup,
57
58
  MenuItem: () => MenuItem,
58
59
  MenuRadioGroup: () => MenuRadioGroup,
@@ -213,20 +214,50 @@ function groupItems(data, groupBy) {
213
214
 
214
215
  // src/v3/Common/SelectStyles.tsx
215
216
  var import_select2 = require("@base-ui/react/select");
216
- var import_styled_components2 = __toESM(require("styled-components"));
217
+ var import_styled_components3 = __toESM(require("styled-components"));
217
218
  var import_seeds_react_mixins = require("@sproutsocial/seeds-react-mixins");
218
- var Field = import_styled_components2.default.div`
219
+
220
+ // src/v3/Common/SelectIcons.tsx
221
+ var React3 = require("react");
222
+ var import_styled_components2 = __toESM(require("styled-components"));
223
+ var import_seeds_react_icon2 = require("@sproutsocial/seeds-react-icon");
224
+ var import_jsx_runtime2 = require("react/jsx-runtime");
225
+ var StyledChevron = import_styled_components2.default.div`
226
+ display: flex;
227
+ align-items: center;
228
+ transition: transform 0.15s;
229
+ ${({ $isOpen }) => $isOpen && "transform: rotate(-180deg);"}
230
+ `;
231
+ function ChevronIcon() {
232
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_icon2.Icon, { name: "chevron-down-outline", fixedWidth: true, "aria-hidden": true });
233
+ }
234
+ function ClearIcon() {
235
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_icon2.Icon, { name: "circle-x-outline", fixedWidth: true, "aria-hidden": true, size: "mini" });
236
+ }
237
+ function CheckIcon2() {
238
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_icon2.Icon, { name: "check-outline", fixedWidth: true, "aria-hidden": true });
239
+ }
240
+
241
+ // src/v3/Common/SelectStyles.tsx
242
+ var invalidStyles = import_styled_components3.css`
243
+ border-color: ${({ theme }) => theme.colors.form.border.error};
244
+
245
+ ${StyledChevron} {
246
+ color: ${({ theme }) => theme.colors.icon.error};
247
+ }
248
+ `;
249
+ var Field = import_styled_components3.default.div`
219
250
  display: ${({ $fullWidth }) => $fullWidth === false ? "inline-flex" : "flex"};
220
251
  flex-direction: column;
221
252
  gap: ${({ theme }) => theme.space[200]};
222
253
  ${({ $fullWidth }) => $fullWidth !== false && "width: 100%;"}
223
254
  `;
224
- var SelectLabel = (0, import_styled_components2.default)(import_select2.Select.Label)`
255
+ var SelectLabel = (0, import_styled_components3.default)(import_select2.Select.Label)`
225
256
  font-size: ${({ theme }) => theme.typography[200].fontSize};
226
257
  font-weight: ${({ theme }) => theme.fontWeights.semibold};
227
258
  color: ${({ theme }) => theme.colors.text.body};
228
259
  `;
229
- var SelectTrigger = (0, import_styled_components2.default)(import_select2.Select.Trigger)`
260
+ var SelectTrigger = (0, import_styled_components3.default)(import_select2.Select.Trigger)`
230
261
  display: flex;
231
262
  align-items: center;
232
263
  justify-content: space-between;
@@ -261,21 +292,23 @@ var SelectTrigger = (0, import_styled_components2.default)(import_select2.Select
261
292
  opacity: 0.4;
262
293
  cursor: not-allowed;
263
294
  }
295
+
296
+ ${({ $isInvalid }) => $isInvalid && invalidStyles}
264
297
  `;
265
- var SelectValue = (0, import_styled_components2.default)(import_select2.Select.Value)`
298
+ var SelectValue = (0, import_styled_components3.default)(import_select2.Select.Value)`
266
299
  min-width: 0;
267
300
  overflow: hidden;
268
301
  `;
269
- var SelectIcon = (0, import_styled_components2.default)(import_select2.Select.Icon)`
302
+ var SelectIcon = (0, import_styled_components3.default)(import_select2.Select.Icon)`
270
303
  display: flex;
271
304
  align-items: center;
272
305
  color: ${({ theme }) => theme.colors.icon.base};
273
306
  flex-shrink: 0;
274
307
  `;
275
- var SelectGroup = (0, import_styled_components2.default)(import_select2.Select.Group)`
308
+ var SelectGroup = (0, import_styled_components3.default)(import_select2.Select.Group)`
276
309
  display: block;
277
310
  `;
278
- var SelectGroupLabel = (0, import_styled_components2.default)(import_select2.Select.GroupLabel)`
311
+ var SelectGroupLabel = (0, import_styled_components3.default)(import_select2.Select.GroupLabel)`
279
312
  padding: ${({ theme }) => `${theme.space[300]} ${theme.space[300]} ${theme.space[200]}`};
280
313
  font-size: ${({ theme }) => theme.typography[100].fontSize};
281
314
  font-weight: ${({ theme }) => theme.fontWeights.semibold};
@@ -283,23 +316,23 @@ var SelectGroupLabel = (0, import_styled_components2.default)(import_select2.Sel
283
316
  letter-spacing: 0.05em;
284
317
  color: ${({ theme }) => theme.colors.text.subtext};
285
318
  `;
286
- var SelectSeparator = (0, import_styled_components2.default)(import_select2.Select.Separator)`
319
+ var SelectSeparator = (0, import_styled_components3.default)(import_select2.Select.Separator)`
287
320
  height: 1px;
288
321
  margin: ${({ theme }) => `${theme.space[200]} ${theme.space[300]}`};
289
322
  background: ${({ theme }) => theme.colors.container.border.base};
290
323
  `;
291
- var SelectPositioner = (0, import_styled_components2.default)(import_select2.Select.Positioner)`
324
+ var SelectPositioner = (0, import_styled_components3.default)(import_select2.Select.Positioner)`
292
325
  width: var(--anchor-width);
293
326
  z-index: 7;
294
327
  `;
295
- var SelectPopup = (0, import_styled_components2.default)(import_select2.Select.Popup)`
328
+ var SelectPopup = (0, import_styled_components3.default)(import_select2.Select.Popup)`
296
329
  font-family: ${({ theme }) => theme.fontFamily};
297
330
  background: ${({ theme }) => theme.colors.container.background.base};
298
331
  border: 1px solid ${({ theme }) => theme.colors.container.border.base};
299
332
  border-radius: ${({ theme }) => theme.radii[500]};
300
333
  box-shadow: ${({ theme }) => theme.shadows.low};
301
334
  outline: none;
302
- max-height: min(var(--base-ui-available-height, 400px), 400px);
335
+ max-height: min(var(--available-height, 400px), 400px);
303
336
  overflow-y: auto;
304
337
  padding: ${({ theme }) => theme.space[200]};
305
338
 
@@ -334,27 +367,6 @@ var SelectPopup = (0, import_styled_components2.default)(import_select2.Select.P
334
367
  }
335
368
  `;
336
369
 
337
- // src/v3/Common/SelectIcons.tsx
338
- var React3 = require("react");
339
- var import_styled_components3 = __toESM(require("styled-components"));
340
- var import_seeds_react_icon2 = require("@sproutsocial/seeds-react-icon");
341
- var import_jsx_runtime2 = require("react/jsx-runtime");
342
- var StyledChevron = import_styled_components3.default.div`
343
- display: flex;
344
- align-items: center;
345
- transition: transform 0.15s;
346
- ${({ $isOpen }) => $isOpen && "transform: rotate(-180deg);"}
347
- `;
348
- function ChevronIcon() {
349
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_icon2.Icon, { name: "chevron-down-outline", fixedWidth: true, "aria-hidden": true });
350
- }
351
- function ClearIcon() {
352
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_icon2.Icon, { name: "circle-x-outline", fixedWidth: true, "aria-hidden": true, size: "mini" });
353
- }
354
- function CheckIcon2() {
355
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_icon2.Icon, { name: "check-outline", fixedWidth: true, "aria-hidden": true });
356
- }
357
-
358
370
  // src/v3/SingleSelect.tsx
359
371
  var import_jsx_runtime3 = require("react/jsx-runtime");
360
372
  var StyledValue = (0, import_styled_components4.default)(import_select3.Select.Value)`
@@ -371,6 +383,7 @@ var StyledValue = (0, import_styled_components4.default)(import_select3.Select.V
371
383
  function SingleSelect(props) {
372
384
  const { id, placeholder, includePlaceholderItem, fullWidth = true } = props;
373
385
  const ariaDescribedBy = props["aria-describedby"];
386
+ const isInvalid = props.isInvalid;
374
387
  const isChildrenMode = "children" in props && props.children != null;
375
388
  const selectedItemId = props.selectedItemId;
376
389
  const defaultSelectedItemId = props.defaultSelectedItemId;
@@ -428,10 +441,19 @@ function SingleSelect(props) {
428
441
  onValueChange: handleValueChange,
429
442
  id,
430
443
  children: [
431
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(SelectTrigger, { "aria-describedby": ariaDescribedBy, children: [
432
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StyledValue, { placeholder, children: renderSelection && selectedItem ? renderSelection(selectedItem) : void 0 }),
433
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SelectIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChevronIcon, {}) }) })
434
- ] }),
444
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
445
+ SelectTrigger,
446
+ {
447
+ "aria-describedby": ariaDescribedBy,
448
+ "aria-invalid": isInvalid || void 0,
449
+ "aria-required": props.required || void 0,
450
+ $isInvalid: isInvalid,
451
+ children: [
452
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StyledValue, { placeholder, children: renderSelection && selectedItem ? renderSelection(selectedItem) : void 0 }),
453
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SelectIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChevronIcon, {}) }) })
454
+ ]
455
+ }
456
+ ),
435
457
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_select3.Select.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SelectPositioner, { sideOffset: 8, alignItemWithTrigger: false, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(SelectPopup, { children: [
436
458
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_select3.Select.ScrollUpArrow, {}),
437
459
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_select3.Select.List, { children: children ? children : groupBy ? groupItems(data, groupBy).map((group, index, arr) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(React4.Fragment, { children: [
@@ -501,6 +523,7 @@ var Placeholder = import_styled_components5.default.div`
501
523
  function MultiSelect(props) {
502
524
  const { id, placeholder = "Select...", fullWidth = true } = props;
503
525
  const ariaDescribedBy = props["aria-describedby"];
526
+ const isInvalid = props.isInvalid;
504
527
  const isChildrenMode = "children" in props && props.children != null;
505
528
  const data = isChildrenMode ? [] : props.data;
506
529
  const itemToString = isChildrenMode ? () => "" : props.itemToString;
@@ -557,23 +580,32 @@ function MultiSelect(props) {
557
580
  disabled: props.disabled,
558
581
  id,
559
582
  children: [
560
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(SelectTrigger, { "aria-describedby": ariaDescribedBy, children: [
561
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectValue, { children: () => {
562
- if (renderSelection) return renderSelection(selectedItems);
563
- if (selectedItems.length === 0)
564
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Placeholder, { children: placeholder });
565
- const visibleItems = maxSelections != null ? selectedItems.slice(0, maxSelections) : selectedItems;
566
- const overflowCount = maxSelections != null && selectedItems.length > maxSelections ? selectedItems.length - maxSelections : 0;
567
- const text = visibleItems.map(
568
- (item) => customRenderSelections ? customRenderSelections(item) : itemToString(item)
569
- ).join(", ");
570
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(SelectionText, { children: [
571
- text,
572
- overflowCount > 0 ? `, +${overflowCount}` : ""
573
- ] });
574
- } }),
575
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronIcon, {}) }) })
576
- ] }),
583
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
584
+ SelectTrigger,
585
+ {
586
+ "aria-describedby": ariaDescribedBy,
587
+ "aria-invalid": isInvalid || void 0,
588
+ "aria-required": props.required || void 0,
589
+ $isInvalid: isInvalid,
590
+ children: [
591
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectValue, { children: () => {
592
+ if (renderSelection) return renderSelection(selectedItems);
593
+ if (selectedItems.length === 0)
594
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Placeholder, { children: placeholder });
595
+ const visibleItems = maxSelections != null ? selectedItems.slice(0, maxSelections) : selectedItems;
596
+ const overflowCount = maxSelections != null && selectedItems.length > maxSelections ? selectedItems.length - maxSelections : 0;
597
+ const text = visibleItems.map(
598
+ (item) => customRenderSelections ? customRenderSelections(item) : itemToString(item)
599
+ ).join(", ");
600
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(SelectionText, { children: [
601
+ text,
602
+ overflowCount > 0 ? `, +${overflowCount}` : ""
603
+ ] });
604
+ } }),
605
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronIcon, {}) }) })
606
+ ]
607
+ }
608
+ ),
577
609
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_select4.Select.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SelectPositioner, { sideOffset: 8, alignItemWithTrigger: false, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(SelectPopup, { children: [
578
610
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_select4.Select.ScrollUpArrow, {}),
579
611
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_select4.Select.List, { children: children ? children : groupBy ? groupItems(data, groupBy).map((group, index, arr) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(React5.Fragment, { children: [
@@ -614,12 +646,25 @@ function MultiSelect(props) {
614
646
  }
615
647
 
616
648
  // src/v3/SingleCombobox.tsx
617
- var React8 = __toESM(require("react"));
649
+ var React9 = __toESM(require("react"));
618
650
  var import_combobox3 = require("@base-ui/react/combobox");
619
651
  var import_react_virtual2 = require("@tanstack/react-virtual");
620
652
 
621
- // src/v3/Common/ComboboxItem.tsx
653
+ // src/v3/Common/useSuppressEscapeClear.ts
622
654
  var React6 = __toESM(require("react"));
655
+ function useSuppressEscapeClear(open) {
656
+ return React6.useCallback(
657
+ (event) => {
658
+ if (event.key === "Escape" && !open) {
659
+ event.stopPropagation();
660
+ }
661
+ },
662
+ [open]
663
+ );
664
+ }
665
+
666
+ // src/v3/Common/ComboboxItem.tsx
667
+ var React7 = __toESM(require("react"));
623
668
  var import_seeds_react_radio2 = __toESM(require("@sproutsocial/seeds-react-radio"));
624
669
  var import_seeds_react_checkbox3 = __toESM(require("@sproutsocial/seeds-react-checkbox"));
625
670
 
@@ -629,6 +674,13 @@ var import_styled_components6 = __toESM(require("styled-components"));
629
674
  var import_seeds_react_mixins2 = require("@sproutsocial/seeds-react-mixins");
630
675
  var import_seeds_react_checkbox2 = __toESM(require("@sproutsocial/seeds-react-checkbox"));
631
676
  var import_jsx_runtime5 = require("react/jsx-runtime");
677
+ var invalidStyles2 = import_styled_components6.css`
678
+ border-color: ${({ theme }) => theme.colors.form.border.error};
679
+
680
+ ${StyledChevron} {
681
+ color: ${({ theme }) => theme.colors.icon.error};
682
+ }
683
+ `;
632
684
  var ComboboxLabel = import_styled_components6.default.label`
633
685
  font-size: ${({ theme }) => theme.typography[200].fontSize};
634
686
  font-weight: ${({ theme }) => theme.fontWeights.semibold};
@@ -655,6 +707,8 @@ var ComboboxInputGroup = (0, import_styled_components6.default)(import_combobox.
655
707
  opacity: 0.4;
656
708
  cursor: not-allowed;
657
709
  }
710
+
711
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
658
712
  `;
659
713
  var ComboboxInput = (0, import_styled_components6.default)(import_combobox.Combobox.Input)`
660
714
  flex: 1;
@@ -702,7 +756,7 @@ var ComboboxActionButtons = import_styled_components6.default.div`
702
756
  margin-left: auto;
703
757
  gap: ${({ theme }) => theme.space[100]};
704
758
  `;
705
- var ComboboxClear = (0, import_styled_components6.default)(import_combobox.Combobox.Clear)`
759
+ var ComboboxClear = (0, import_styled_components6.default)(import_combobox.Combobox.Clear).attrs({ tabIndex: 0 })`
706
760
  display: flex;
707
761
  align-items: center;
708
762
  justify-content: center;
@@ -719,6 +773,10 @@ var ComboboxClear = (0, import_styled_components6.default)(import_combobox.Combo
719
773
  color: ${({ theme }) => theme.colors.text.body};
720
774
  }
721
775
 
776
+ &:focus-visible {
777
+ ${import_seeds_react_mixins2.focusRing}
778
+ }
779
+
722
780
  &[data-empty] {
723
781
  display: none;
724
782
  }
@@ -751,7 +809,7 @@ var ComboboxPopup = (0, import_styled_components6.default)(import_combobox.Combo
751
809
  box-shadow: ${({ theme }) => theme.shadows.medium};
752
810
  outline: none;
753
811
  width: 100%;
754
- max-height: min(var(--base-ui-available-height, 400px), 400px);
812
+ max-height: min(var(--available-height, 400px), 400px);
755
813
  overflow-y: auto;
756
814
  padding: 0;
757
815
 
@@ -918,6 +976,7 @@ var ComboboxToken = (0, import_styled_components6.default)(import_combobox.Combo
918
976
  display: flex;
919
977
  width: 100%;
920
978
  flex-wrap: wrap;
979
+ gap: ${({ theme }) => theme.space[200]};
921
980
  `;
922
981
  var ComboboxTokenInputGroup = (0, import_styled_components6.default)(import_combobox.Combobox.InputGroup)`
923
982
  display: flex;
@@ -942,6 +1001,8 @@ var ComboboxTokenInputGroup = (0, import_styled_components6.default)(import_comb
942
1001
  opacity: 0.4;
943
1002
  cursor: not-allowed;
944
1003
  }
1004
+
1005
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
945
1006
  `;
946
1007
  var Token = import_styled_components6.default.span`
947
1008
  display: inline-flex;
@@ -974,6 +1035,10 @@ var TokenRemove = import_styled_components6.default.button`
974
1035
  cursor: pointer;
975
1036
  padding: 0;
976
1037
  line-height: 1;
1038
+
1039
+ &:focus-visible {
1040
+ ${import_seeds_react_mixins2.focusRing}
1041
+ }
977
1042
  `;
978
1043
  var SearchableSelectTrigger = (0, import_styled_components6.default)(import_combobox.Combobox.Trigger)`
979
1044
  display: flex;
@@ -1007,6 +1072,8 @@ var SearchableSelectTrigger = (0, import_styled_components6.default)(import_comb
1007
1072
  opacity: 0.4;
1008
1073
  cursor: not-allowed;
1009
1074
  }
1075
+
1076
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
1010
1077
  `;
1011
1078
  var SearchableSelectTriggerIcon = (0, import_styled_components6.default)(import_combobox.Combobox.Icon)`
1012
1079
  display: flex;
@@ -1089,6 +1156,8 @@ var SearchableSelectTokenTrigger = (0, import_styled_components6.default)(import
1089
1156
  opacity: 0.4;
1090
1157
  cursor: not-allowed;
1091
1158
  }
1159
+
1160
+ ${({ $isInvalid }) => $isInvalid && invalidStyles2}
1092
1161
  `;
1093
1162
 
1094
1163
  // src/v3/Common/ComboboxItem.tsx
@@ -1153,11 +1222,11 @@ function ComboboxItemInner({
1153
1222
  }
1154
1223
  );
1155
1224
  }
1156
- var ComboboxItem2 = React6.forwardRef(ComboboxItemInner);
1225
+ var ComboboxItem2 = React7.forwardRef(ComboboxItemInner);
1157
1226
  var ComboboxItem_default = ComboboxItem2;
1158
1227
 
1159
1228
  // src/v3/Common/VirtualizedComboboxList.tsx
1160
- var React7 = __toESM(require("react"));
1229
+ var React8 = __toESM(require("react"));
1161
1230
  var import_combobox2 = require("@base-ui/react/combobox");
1162
1231
  var import_react_virtual = require("@tanstack/react-virtual");
1163
1232
 
@@ -1197,7 +1266,7 @@ function VirtualizedComboboxList({
1197
1266
  renderCreatableItem
1198
1267
  }) {
1199
1268
  const filteredItems = import_combobox2.Combobox.useFilteredItems();
1200
- const scrollElementRef = React7.useRef(null);
1269
+ const scrollElementRef = React8.useRef(null);
1201
1270
  const virtualizer = (0, import_react_virtual.useVirtualizer)({
1202
1271
  enabled: open,
1203
1272
  count: filteredItems.length,
@@ -1209,8 +1278,8 @@ function VirtualizedComboboxList({
1209
1278
  scrollPaddingStart: 4,
1210
1279
  scrollPaddingEnd: 4
1211
1280
  });
1212
- React7.useImperativeHandle(virtualizerRef, () => virtualizer);
1213
- const handleScrollRef = React7.useCallback(
1281
+ React8.useImperativeHandle(virtualizerRef, () => virtualizer);
1282
+ const handleScrollRef = React8.useCallback(
1214
1283
  (el) => {
1215
1284
  scrollElementRef.current = el;
1216
1285
  if (el) requestAnimationFrame(() => virtualizer.measure());
@@ -1358,6 +1427,7 @@ function SingleCombobox(props) {
1358
1427
  fullWidth = true
1359
1428
  } = props;
1360
1429
  const ariaDescribedBy = props["aria-describedby"];
1430
+ const isInvalid = props.isInvalid;
1361
1431
  const isChildrenMode = "children" in props && props.children != null;
1362
1432
  const data = isChildrenMode ? [] : props.data;
1363
1433
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1371,17 +1441,18 @@ function SingleCombobox(props) {
1371
1441
  const defaultSelectedItemId = props.defaultSelectedItemId;
1372
1442
  const onSelectedItemIdChange = props.onSelectedItemIdChange;
1373
1443
  const { containerRef, portalContainer } = useSeedsPortalContainer();
1374
- const [open, setOpen] = React8.useState(false);
1375
- const virtualizerRef = React8.useRef(null);
1444
+ const [open, setOpen] = React9.useState(false);
1445
+ const virtualizerRef = React9.useRef(null);
1446
+ const onInputKeyDownCapture = useSuppressEscapeClear(open);
1376
1447
  const isControlled = selectedItemId !== void 0;
1377
- const idToItem = React8.useCallback(
1448
+ const idToItem = React9.useCallback(
1378
1449
  (id2) => {
1379
1450
  if (id2 == null) return null;
1380
1451
  return data.find((d) => String(d.id) === String(id2)) ?? null;
1381
1452
  },
1382
1453
  [data]
1383
1454
  );
1384
- const [internalValue, setInternalValue] = React8.useState(
1455
+ const [internalValue, setInternalValue] = React9.useState(
1385
1456
  () => idToItem(defaultSelectedItemId)
1386
1457
  );
1387
1458
  const value = isControlled ? idToItem(selectedItemId) : internalValue;
@@ -1393,7 +1464,7 @@ function SingleCombobox(props) {
1393
1464
  onSelectedItemIdChange(newItem ? newItem.id : null);
1394
1465
  }
1395
1466
  }
1396
- const groups = React8.useMemo(
1467
+ const groups = React9.useMemo(
1397
1468
  () => groupBy ? groupItems(data, groupBy) : null,
1398
1469
  [data, groupBy]
1399
1470
  );
@@ -1418,29 +1489,38 @@ function SingleCombobox(props) {
1418
1489
  if (!item || !virt) return;
1419
1490
  const isStart = index === 0;
1420
1491
  const isEnd = index === virt.options.count - 1;
1421
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
1492
+ if (reason === "keyboard" && (isStart || isEnd)) {
1422
1493
  queueMicrotask(() => {
1423
1494
  virt.scrollToIndex(index, {
1424
- align: isEnd ? "start" : "end"
1495
+ align: isStart ? "start" : "end"
1425
1496
  });
1426
1497
  });
1427
1498
  }
1428
1499
  } : void 0,
1429
1500
  children: [
1430
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ComboboxInputGroup, { children: [
1431
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1432
- ComboboxInput,
1433
- {
1434
- placeholder,
1435
- id,
1436
- "aria-describedby": ariaDescribedBy
1437
- }
1438
- ),
1439
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ComboboxActionButtons, { children: [
1440
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxClear, { "aria-label": "Clear selection", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ClearIcon, {}) }),
1441
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronIcon, {}) }) })
1442
- ] })
1443
- ] }),
1501
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1502
+ ComboboxInputGroup,
1503
+ {
1504
+ $isInvalid: isInvalid,
1505
+ onKeyDownCapture: onInputKeyDownCapture,
1506
+ children: [
1507
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1508
+ ComboboxInput,
1509
+ {
1510
+ placeholder,
1511
+ id,
1512
+ "aria-describedby": ariaDescribedBy,
1513
+ "aria-invalid": isInvalid || void 0,
1514
+ "aria-required": props.required || void 0
1515
+ }
1516
+ ),
1517
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ComboboxActionButtons, { children: [
1518
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxClear, { "aria-label": "Clear selection", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ClearIcon, {}) }),
1519
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChevronIcon, {}) }) })
1520
+ ] })
1521
+ ]
1522
+ }
1523
+ ),
1444
1524
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_combobox3.Combobox.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxPositioner, { sideOffset: 4, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1445
1525
  ComboboxPopup,
1446
1526
  {
@@ -1470,7 +1550,7 @@ function SingleCombobox(props) {
1470
1550
  renderItem,
1471
1551
  renderGroupHeading
1472
1552
  }
1473
- ) : children ? children : groups ? (group, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(React8.Fragment, { children: [
1553
+ ) : children ? children : groups ? ((group, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(React9.Fragment, { children: [
1474
1554
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ComboboxGroup, { items: group.items, children: [
1475
1555
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(group.value) : group.value }),
1476
1556
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_combobox3.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
@@ -1487,7 +1567,7 @@ function SingleCombobox(props) {
1487
1567
  ) })
1488
1568
  ] }),
1489
1569
  index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ComboboxSeparator, {})
1490
- ] }, group.value) : (item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1570
+ ] }, group.value)) : ((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1491
1571
  ComboboxItem_default,
1492
1572
  {
1493
1573
  value: item,
@@ -1498,7 +1578,7 @@ function SingleCombobox(props) {
1498
1578
  renderItem: renderItem ? () => renderItem(item) : () => itemToString(item)
1499
1579
  },
1500
1580
  item.id
1501
- )
1581
+ ))
1502
1582
  }
1503
1583
  )
1504
1584
  ]
@@ -1511,7 +1591,7 @@ function SingleCombobox(props) {
1511
1591
  }
1512
1592
 
1513
1593
  // src/v3/MultiCombobox.tsx
1514
- var React9 = __toESM(require("react"));
1594
+ var React10 = __toESM(require("react"));
1515
1595
  var import_combobox4 = require("@base-ui/react/combobox");
1516
1596
  var import_react_virtual3 = require("@tanstack/react-virtual");
1517
1597
  var import_seeds_react_icon3 = __toESM(require("@sproutsocial/seeds-react-icon"));
@@ -1539,6 +1619,7 @@ function MultiCombobox(props) {
1539
1619
  fullWidth = true
1540
1620
  } = props;
1541
1621
  const ariaDescribedBy = props["aria-describedby"];
1622
+ const isInvalid = props.isInvalid;
1542
1623
  const isChildrenMode = "children" in props && props.children != null;
1543
1624
  const data = isChildrenMode ? [] : props.data;
1544
1625
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1562,29 +1643,31 @@ function MultiCombobox(props) {
1562
1643
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
1563
1644
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
1564
1645
  const { containerRef, portalContainer } = useSeedsPortalContainer();
1565
- const [open, setOpen] = React9.useState(false);
1566
- const [internalInputValue, setInternalInputValue] = React9.useState("");
1567
- const skipNextInputChangeRef = React9.useRef(false);
1568
- const virtualizerRef = React9.useRef(null);
1646
+ const [open, setOpen] = React10.useState(false);
1647
+ const [internalInputValue, setInternalInputValue] = React10.useState("");
1648
+ const skipNextInputChangeRef = React10.useRef(false);
1649
+ const virtualizerRef = React10.useRef(null);
1650
+ const inputRef = React10.useRef(null);
1651
+ const onInputKeyDownCapture = useSuppressEscapeClear(open);
1569
1652
  const isControlled = selectedItemIds !== void 0;
1570
- const idsToItems = React9.useCallback(
1653
+ const idsToItems = React10.useCallback(
1571
1654
  (ids) => ids.map((id2) => data.find((d) => d.id === id2)).filter((d) => d != null),
1572
1655
  [data]
1573
1656
  );
1574
- const [internalValue, setInternalValue] = React9.useState(
1657
+ const [internalValue, setInternalValue] = React10.useState(
1575
1658
  () => defaultSelectedItemIds ? idsToItems(defaultSelectedItemIds) : []
1576
1659
  );
1577
1660
  const value = isControlled ? idsToItems(selectedItemIds) : internalValue;
1578
- const visibleData = React9.useMemo(
1661
+ const visibleData = React10.useMemo(
1579
1662
  () => removeSelectedItems ? data.filter((item) => !value.some((v) => v.id === item.id)) : data,
1580
1663
  [data, value, removeSelectedItems]
1581
1664
  );
1582
- const groups = React9.useMemo(
1665
+ const groups = React10.useMemo(
1583
1666
  () => groupBy ? groupItems(visibleData, groupBy) : null,
1584
1667
  [visibleData, groupBy]
1585
1668
  );
1586
1669
  const currentInputValue = inputValue ?? internalInputValue;
1587
- const creatableSentinel = React9.useMemo(() => {
1670
+ const creatableSentinel = React10.useMemo(() => {
1588
1671
  if (!creatableProp) return null;
1589
1672
  const trimmed = currentInputValue.trim();
1590
1673
  if (!trimmed) return null;
@@ -1595,7 +1678,7 @@ function MultiCombobox(props) {
1595
1678
  if (exactExists) return null;
1596
1679
  return makeCreatableSentinel(trimmed);
1597
1680
  }, [creatableProp, currentInputValue, data, itemToString]);
1598
- const flatItems = React9.useMemo(() => {
1681
+ const flatItems = React10.useMemo(() => {
1599
1682
  if (!selectHeadings && !selectAll) return null;
1600
1683
  if (!groups && !selectAll) return null;
1601
1684
  const rows = [];
@@ -1681,6 +1764,7 @@ function MultiCombobox(props) {
1681
1764
  e.preventDefault();
1682
1765
  e.stopPropagation();
1683
1766
  setSelectedItems(value.filter((v) => v.id !== item.id));
1767
+ inputRef.current?.focus();
1684
1768
  }
1685
1769
  function renderSentinelRow(row) {
1686
1770
  if (isSelectAllSentinel2(row)) {
@@ -1762,7 +1846,10 @@ function MultiCombobox(props) {
1762
1846
  open,
1763
1847
  disabled: props.disabled,
1764
1848
  onOpenChange: (nextOpen, eventDetails) => {
1765
- if (!nextOpen && eventDetails.reason === "item-press") return;
1849
+ if (!nextOpen && eventDetails.reason === "item-press") {
1850
+ eventDetails.cancel();
1851
+ return;
1852
+ }
1766
1853
  setOpen(nextOpen);
1767
1854
  },
1768
1855
  filter: creatableProp ? (item, query) => {
@@ -1795,10 +1882,10 @@ function MultiCombobox(props) {
1795
1882
  if (!item || !virt) return;
1796
1883
  const isStart = index === 0;
1797
1884
  const isEnd = index === virt.options.count - 1;
1798
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
1885
+ if (reason === "keyboard" && (isStart || isEnd)) {
1799
1886
  queueMicrotask(() => {
1800
1887
  virt.scrollToIndex(index, {
1801
- align: isEnd ? "start" : "end"
1888
+ align: isStart ? "start" : "end"
1802
1889
  });
1803
1890
  });
1804
1891
  }
@@ -1825,42 +1912,52 @@ function MultiCombobox(props) {
1825
1912
  },
1826
1913
  items: rootItems,
1827
1914
  children: [
1828
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxTokenInputGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxToken, { children: [
1829
- renderSelection ? renderSelection(value) : (() => {
1830
- const visibleTokens = maxTokens != null ? value.slice(0, maxTokens) : value;
1831
- const overflow = maxTokens != null ? value.length - maxTokens : 0;
1832
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1833
- visibleTokens.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Token, { children: [
1834
- renderToken ? renderToken(item) : itemToString(item),
1835
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1836
- TokenRemove,
1837
- {
1838
- "aria-label": `Remove ${itemToString(item)}`,
1839
- onPointerDown: (e) => e.preventDefault(),
1840
- onClick: (e) => removeItem(item, e),
1841
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_seeds_react_icon3.default, { name: "x-outline", size: "mini" })
1842
- }
1843
- )
1844
- ] }, item.id)),
1845
- overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Token, { children: [
1846
- "+",
1847
- overflow
1848
- ] }, "__overflow")
1849
- ] });
1850
- })(),
1851
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1852
- ComboboxTokenInput,
1853
- {
1854
- id,
1855
- placeholder: value.length > 0 ? "" : placeholder,
1856
- "aria-describedby": ariaDescribedBy
1857
- }
1858
- ),
1859
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxActionButtons, { children: [
1860
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxClear, { "aria-label": "Clear all", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ClearIcon, {}) }),
1861
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChevronIcon, {}) }) })
1862
- ] })
1863
- ] }) }),
1915
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1916
+ ComboboxTokenInputGroup,
1917
+ {
1918
+ $isInvalid: isInvalid,
1919
+ onKeyDownCapture: onInputKeyDownCapture,
1920
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxToken, { children: [
1921
+ renderSelection ? renderSelection(value) : (() => {
1922
+ const visibleTokens = maxTokens != null ? value.slice(0, maxTokens) : value;
1923
+ const overflow = maxTokens != null ? value.length - maxTokens : 0;
1924
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
1925
+ visibleTokens.map((item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Token, { children: [
1926
+ renderToken ? renderToken(item) : itemToString(item),
1927
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1928
+ TokenRemove,
1929
+ {
1930
+ "aria-label": `Remove ${itemToString(item)}`,
1931
+ onPointerDown: (e) => e.preventDefault(),
1932
+ onClick: (e) => removeItem(item, e),
1933
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_seeds_react_icon3.default, { name: "x-outline", size: "mini" })
1934
+ }
1935
+ )
1936
+ ] }, item.id)),
1937
+ overflow > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Token, { children: [
1938
+ "+",
1939
+ overflow
1940
+ ] }, "__overflow")
1941
+ ] });
1942
+ })(),
1943
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1944
+ ComboboxTokenInput,
1945
+ {
1946
+ ref: inputRef,
1947
+ id,
1948
+ placeholder: value.length > 0 ? "" : placeholder,
1949
+ "aria-describedby": ariaDescribedBy,
1950
+ "aria-invalid": isInvalid || void 0,
1951
+ "aria-required": props.required || void 0
1952
+ }
1953
+ ),
1954
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxActionButtons, { children: [
1955
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxClear, { "aria-label": "Clear all", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ClearIcon, {}) }),
1956
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxTrigger, { "aria-label": "Open popup", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StyledChevron, { $isOpen: open, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ChevronIcon, {}) }) })
1957
+ ] })
1958
+ ] })
1959
+ }
1960
+ ),
1864
1961
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_combobox4.Combobox.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxPositioner, { sideOffset: 4, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1865
1962
  ComboboxPopup,
1866
1963
  {
@@ -1898,12 +1995,12 @@ function MultiCombobox(props) {
1898
1995
  measureRef
1899
1996
  ) : void 0
1900
1997
  }
1901
- ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
1998
+ ) : children ? children : flatItems ? ((row) => renderSentinelRow(row)) : groups ? ((group, index) => {
1902
1999
  if (isCreatableSentinel(group)) {
1903
2000
  return renderCreatableItem(group);
1904
2001
  }
1905
2002
  const g = group;
1906
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(React9.Fragment, { children: [
2003
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(React10.Fragment, { children: [
1907
2004
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ComboboxGroup, { items: g.items, children: [
1908
2005
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
1909
2006
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_combobox4.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
@@ -1921,7 +2018,7 @@ function MultiCombobox(props) {
1921
2018
  ] }),
1922
2019
  index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ComboboxSeparator, {})
1923
2020
  ] }, g.value);
1924
- } : (item) => {
2021
+ }) : ((item) => {
1925
2022
  if (isCreatableSentinel(item)) {
1926
2023
  return renderCreatableItem(item);
1927
2024
  }
@@ -1938,7 +2035,7 @@ function MultiCombobox(props) {
1938
2035
  },
1939
2036
  dataItem.id
1940
2037
  );
1941
- }
2038
+ })
1942
2039
  }
1943
2040
  )
1944
2041
  ]
@@ -1951,7 +2048,7 @@ function MultiCombobox(props) {
1951
2048
  }
1952
2049
 
1953
2050
  // src/v3/SingleSearchableSelect.tsx
1954
- var React10 = __toESM(require("react"));
2051
+ var React11 = __toESM(require("react"));
1955
2052
  var import_combobox5 = require("@base-ui/react/combobox");
1956
2053
  var import_react_virtual4 = require("@tanstack/react-virtual");
1957
2054
  var import_jsx_runtime10 = require("react/jsx-runtime");
@@ -1968,6 +2065,7 @@ function SingleSearchableSelect(props) {
1968
2065
  fullWidth = true
1969
2066
  } = props;
1970
2067
  const ariaDescribedBy = props["aria-describedby"];
2068
+ const isInvalid = props.isInvalid;
1971
2069
  const isChildrenMode = "children" in props && props.children != null;
1972
2070
  const data = isChildrenMode ? [] : props.data;
1973
2071
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -1982,17 +2080,17 @@ function SingleSearchableSelect(props) {
1982
2080
  const defaultSelectedItemId = props.defaultSelectedItemId;
1983
2081
  const onSelectedItemIdChange = props.onSelectedItemIdChange;
1984
2082
  const { containerRef, portalContainer } = useSeedsPortalContainer();
1985
- const [open, setOpen] = React10.useState(false);
1986
- const virtualizerRef = React10.useRef(null);
2083
+ const [open, setOpen] = React11.useState(false);
2084
+ const virtualizerRef = React11.useRef(null);
1987
2085
  const isControlled = selectedItemId !== void 0;
1988
- const idToItem = React10.useCallback(
2086
+ const idToItem = React11.useCallback(
1989
2087
  (id2) => {
1990
2088
  if (id2 == null) return null;
1991
2089
  return data.find((d) => String(d.id) === String(id2)) ?? null;
1992
2090
  },
1993
2091
  [data]
1994
2092
  );
1995
- const [internalValue, setInternalValue] = React10.useState(
2093
+ const [internalValue, setInternalValue] = React11.useState(
1996
2094
  () => idToItem(defaultSelectedItemId)
1997
2095
  );
1998
2096
  const value = isControlled ? idToItem(selectedItemId) : internalValue;
@@ -2003,7 +2101,7 @@ function SingleSearchableSelect(props) {
2003
2101
  onSelectedItemIdChange(realItem ? realItem.id : null);
2004
2102
  }
2005
2103
  }
2006
- const groups = React10.useMemo(
2104
+ const groups = React11.useMemo(
2007
2105
  () => groupBy ? groupItems(data, groupBy) : null,
2008
2106
  [data, groupBy]
2009
2107
  );
@@ -2033,19 +2131,29 @@ function SingleSearchableSelect(props) {
2033
2131
  if (!item || !virt) return;
2034
2132
  const isStart = index === 0;
2035
2133
  const isEnd = index === virt.options.count - 1;
2036
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
2134
+ if (reason === "keyboard" && (isStart || isEnd)) {
2037
2135
  queueMicrotask(() => {
2038
2136
  virt.scrollToIndex(index, {
2039
- align: isEnd ? "start" : "end"
2137
+ align: isStart ? "start" : "end"
2040
2138
  });
2041
2139
  });
2042
2140
  }
2043
2141
  } : void 0,
2044
2142
  children: [
2045
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(SearchableSelectTrigger, { id, "aria-describedby": ariaDescribedBy, children: [
2046
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchableSelectPlaceholder, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_combobox5.Combobox.Value, { placeholder, children: value ? renderSelection ? renderSelection(value) : itemToString(value) : placeholder }) }),
2047
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchableSelectTriggerIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChevronIcon, {}) }) })
2048
- ] }),
2143
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2144
+ SearchableSelectTrigger,
2145
+ {
2146
+ id,
2147
+ "aria-describedby": ariaDescribedBy,
2148
+ "aria-invalid": isInvalid || void 0,
2149
+ "aria-required": props.required || void 0,
2150
+ $isInvalid: isInvalid,
2151
+ children: [
2152
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchableSelectPlaceholder, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_combobox5.Combobox.Value, { placeholder, children: value ? renderSelection ? renderSelection(value) : itemToString(value) : placeholder }) }),
2153
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SearchableSelectTriggerIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StyledChevron, { "data-chevron": true, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChevronIcon, {}) }) })
2154
+ ]
2155
+ }
2156
+ ),
2049
2157
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_combobox5.Combobox.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ComboboxPositioner, { sideOffset: 4, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2050
2158
  SearchableSelectPopup,
2051
2159
  {
@@ -2083,7 +2191,7 @@ function SingleSearchableSelect(props) {
2083
2191
  inputType,
2084
2192
  renderItem
2085
2193
  }
2086
- ) : children ? children : groups ? (group, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(React10.Fragment, { children: [
2194
+ ) : children ? children : groups ? ((group, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(React11.Fragment, { children: [
2087
2195
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ComboboxGroup, { items: group.items, children: [
2088
2196
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(group.value) : group.value }),
2089
2197
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_combobox5.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
@@ -2100,7 +2208,7 @@ function SingleSearchableSelect(props) {
2100
2208
  ) })
2101
2209
  ] }),
2102
2210
  index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ComboboxSeparator, {})
2103
- ] }, group.value) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2211
+ ] }, group.value)) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2104
2212
  includePlaceholderItem && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2105
2213
  ComboboxItem_default,
2106
2214
  {
@@ -2136,7 +2244,7 @@ function SingleSearchableSelect(props) {
2136
2244
  }
2137
2245
 
2138
2246
  // src/v3/MultiSearchableSelect.tsx
2139
- var React11 = __toESM(require("react"));
2247
+ var React12 = __toESM(require("react"));
2140
2248
  var import_combobox6 = require("@base-ui/react/combobox");
2141
2249
  var import_react_virtual5 = require("@tanstack/react-virtual");
2142
2250
  var import_seeds_react_icon4 = __toESM(require("@sproutsocial/seeds-react-icon"));
@@ -2170,6 +2278,7 @@ function MultiSearchableSelect(props) {
2170
2278
  fullWidth = true
2171
2279
  } = props;
2172
2280
  const ariaDescribedBy = props["aria-describedby"];
2281
+ const isInvalid = props.isInvalid;
2173
2282
  const isChildrenMode = "children" in props && props.children != null;
2174
2283
  const data = isChildrenMode ? [] : props.data;
2175
2284
  const itemToString = isChildrenMode ? (_item) => "" : props.itemToString;
@@ -2191,29 +2300,29 @@ function MultiSearchableSelect(props) {
2191
2300
  const defaultSelectedItemIds = props.defaultSelectedItemIds;
2192
2301
  const onSelectedItemIdsChange = props.onSelectedItemIdsChange;
2193
2302
  const { containerRef, portalContainer } = useSeedsPortalContainer();
2194
- const [open, setOpen] = React11.useState(false);
2195
- const [internalInputValue, setInternalInputValue] = React11.useState("");
2196
- const skipNextInputChangeRef = React11.useRef(false);
2197
- const virtualizerRef = React11.useRef(null);
2303
+ const [open, setOpen] = React12.useState(false);
2304
+ const [internalInputValue, setInternalInputValue] = React12.useState("");
2305
+ const skipNextInputChangeRef = React12.useRef(false);
2306
+ const virtualizerRef = React12.useRef(null);
2198
2307
  const isControlled = selectedItemIds !== void 0;
2199
- const idsToItems = React11.useCallback(
2308
+ const idsToItems = React12.useCallback(
2200
2309
  (ids) => ids.map((id2) => data.find((d) => d.id === id2)).filter((d) => d != null),
2201
2310
  [data]
2202
2311
  );
2203
- const [internalValue, setInternalValue] = React11.useState(
2312
+ const [internalValue, setInternalValue] = React12.useState(
2204
2313
  () => defaultSelectedItemIds ? idsToItems(defaultSelectedItemIds) : []
2205
2314
  );
2206
2315
  const value = isControlled ? idsToItems(selectedItemIds) : internalValue;
2207
- const visibleData = React11.useMemo(
2316
+ const visibleData = React12.useMemo(
2208
2317
  () => removeSelectedItems ? data.filter((item) => !value.some((v) => v.id === item.id)) : data,
2209
2318
  [data, value, removeSelectedItems]
2210
2319
  );
2211
- const groups = React11.useMemo(
2320
+ const groups = React12.useMemo(
2212
2321
  () => groupBy ? groupItems(visibleData, groupBy) : null,
2213
2322
  [visibleData, groupBy]
2214
2323
  );
2215
2324
  const currentInputValue = internalInputValue;
2216
- const creatableSentinel = React11.useMemo(() => {
2325
+ const creatableSentinel = React12.useMemo(() => {
2217
2326
  if (!creatableProp) return null;
2218
2327
  const trimmed = currentInputValue.trim();
2219
2328
  if (!trimmed) return null;
@@ -2224,7 +2333,7 @@ function MultiSearchableSelect(props) {
2224
2333
  if (exactExists) return null;
2225
2334
  return makeCreatableSentinel(trimmed);
2226
2335
  }, [creatableProp, currentInputValue, data, itemToString]);
2227
- const flatItems = React11.useMemo(() => {
2336
+ const flatItems = React12.useMemo(() => {
2228
2337
  if (!groups || !selectHeadings && !selectAll) return null;
2229
2338
  const rows = [];
2230
2339
  if (selectAll) rows.push(SELECT_ALL_SENTINEL2);
@@ -2401,10 +2510,10 @@ function MultiSearchableSelect(props) {
2401
2510
  if (!item || !virt) return;
2402
2511
  const isStart = index === 0;
2403
2512
  const isEnd = index === virt.options.count - 1;
2404
- if (reason === "none" || reason === "keyboard" && (isStart || isEnd)) {
2513
+ if (reason === "keyboard" && (isStart || isEnd)) {
2405
2514
  queueMicrotask(() => {
2406
2515
  virt.scrollToIndex(index, {
2407
- align: isEnd ? "start" : "end"
2516
+ align: isStart ? "start" : "end"
2408
2517
  });
2409
2518
  });
2410
2519
  }
@@ -2436,6 +2545,9 @@ function MultiSearchableSelect(props) {
2436
2545
  {
2437
2546
  id,
2438
2547
  "aria-describedby": ariaDescribedBy,
2548
+ "aria-invalid": isInvalid || void 0,
2549
+ "aria-required": props.required || void 0,
2550
+ $isInvalid: isInvalid,
2439
2551
  children: [
2440
2552
  renderSelection ? renderSelection(value) : value.length > 0 ? (() => {
2441
2553
  const visibleItems = maxSelections != null ? value.slice(0, maxSelections) : value;
@@ -2496,12 +2608,12 @@ function MultiSearchableSelect(props) {
2496
2608
  measureRef
2497
2609
  ) : void 0
2498
2610
  }
2499
- ) : children ? children : flatItems ? (row) => renderSentinelRow(row) : groups ? (group, index) => {
2611
+ ) : children ? children : flatItems ? ((row) => renderSentinelRow(row)) : groups ? ((group, index) => {
2500
2612
  if (isCreatableSentinel(group)) {
2501
2613
  return renderCreatableItem(group);
2502
2614
  }
2503
2615
  const g = group;
2504
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(React11.Fragment, { children: [
2616
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(React12.Fragment, { children: [
2505
2617
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(ComboboxGroup, { items: g.items, children: [
2506
2618
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComboboxGroupLabel, { children: renderGroupHeading ? renderGroupHeading(g.value) : g.value }),
2507
2619
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_combobox6.Combobox.Collection, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
@@ -2519,7 +2631,7 @@ function MultiSearchableSelect(props) {
2519
2631
  ] }),
2520
2632
  index < groups.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ComboboxSeparator, {})
2521
2633
  ] }, g.value);
2522
- } : (item) => {
2634
+ }) : ((item) => {
2523
2635
  if (isCreatableSentinel(item)) {
2524
2636
  return renderCreatableItem(item);
2525
2637
  }
@@ -2536,7 +2648,7 @@ function MultiSearchableSelect(props) {
2536
2648
  },
2537
2649
  dataItem.id
2538
2650
  );
2539
- }
2651
+ })
2540
2652
  }
2541
2653
  )
2542
2654
  ]
@@ -2549,7 +2661,7 @@ function MultiSearchableSelect(props) {
2549
2661
  }
2550
2662
 
2551
2663
  // src/v3/ActionMenu.tsx
2552
- var React12 = __toESM(require("react"));
2664
+ var React13 = __toESM(require("react"));
2553
2665
  var import_menu2 = require("@base-ui/react/menu");
2554
2666
  var import_seeds_react_radio3 = __toESM(require("@sproutsocial/seeds-react-radio"));
2555
2667
  var import_seeds_react_checkbox4 = __toESM(require("@sproutsocial/seeds-react-checkbox"));
@@ -2564,16 +2676,18 @@ var ActionMenuPositioner = (0, import_styled_components8.default)(import_menu.Me
2564
2676
  min-width: var(--anchor-width);
2565
2677
  z-index: 7;
2566
2678
  `;
2567
- var ActionMenuPopup = (0, import_styled_components8.default)(import_menu.Menu.Popup)`
2679
+ var ActionMenuPopup = (0, import_styled_components8.default)(import_menu.Menu.Popup).attrs({
2680
+ "data-base-ui-swipe-ignore": ""
2681
+ })`
2568
2682
  font-family: ${({ theme }) => theme.fontFamily};
2569
2683
  background: ${({ theme }) => theme.colors.container.background.base};
2570
2684
  border: 1px solid ${({ theme }) => theme.colors.container.border.base};
2571
2685
  border-radius: ${({ theme }) => theme.radii[500]};
2572
2686
  box-shadow: ${({ theme }) => theme.shadows.low};
2573
2687
  outline: none;
2574
- max-height: min(var(--base-ui-available-height, 400px), 400px);
2688
+ max-height: min(var(--available-height, 400px), 400px);
2575
2689
  overflow-y: auto;
2576
- padding: ${({ theme }) => theme.space[200]};
2690
+ padding: ${({ theme }) => theme.space[300]};
2577
2691
 
2578
2692
  &[data-open] {
2579
2693
  animation: action-menu-popup-in 120ms ease-out;
@@ -2609,16 +2723,13 @@ var ActionMenuGroup = (0, import_styled_components8.default)(import_menu.Menu.Gr
2609
2723
  display: block;
2610
2724
  `;
2611
2725
  var ActionMenuGroupLabel = (0, import_styled_components8.default)(import_menu.Menu.GroupLabel)`
2612
- padding: ${({ theme }) => `${theme.space[300]} ${theme.space[300]} ${theme.space[200]}`};
2726
+ padding: ${({ theme }) => `${theme.space[300]}`};
2613
2727
  font-size: ${({ theme }) => theme.typography[100].fontSize};
2614
- font-weight: ${({ theme }) => theme.fontWeights.semibold};
2615
- text-transform: uppercase;
2616
- letter-spacing: 0.05em;
2617
- color: ${({ theme }) => theme.colors.text.subtext};
2728
+ color: ${({ theme }) => theme.colors.text.body};
2618
2729
  `;
2619
2730
  var ActionMenuSeparator = (0, import_styled_components8.default)(import_menu.Menu.Separator)`
2620
2731
  height: 1px;
2621
- margin: ${({ theme }) => `${theme.space[200]} ${theme.space[300]}`};
2732
+ margin: ${({ theme }) => `${theme.space[300]} -${theme.space[300]}`};
2622
2733
  background: ${({ theme }) => theme.colors.container.border.base};
2623
2734
  `;
2624
2735
  var menuItemStyles = import_styled_components8.css`
@@ -2750,7 +2861,7 @@ function MenuRadioGroup({
2750
2861
  );
2751
2862
  }
2752
2863
  function MenuItem(props) {
2753
- const generatedId = React12.useId();
2864
+ const generatedId = React13.useId();
2754
2865
  if (props.type === "checkbox") {
2755
2866
  const {
2756
2867
  children: children2,
@@ -2891,6 +3002,81 @@ function MenuSubTrigger({
2891
3002
  }
2892
3003
  );
2893
3004
  }
3005
+
3006
+ // src/v3/MenuButton.tsx
3007
+ var React14 = require("react");
3008
+ var import_seeds_react_button2 = require("@sproutsocial/seeds-react-button");
3009
+ var import_seeds_react_icon6 = require("@sproutsocial/seeds-react-icon");
3010
+
3011
+ // src/v3/MenuButtonStyles.tsx
3012
+ var import_styled_components9 = __toESM(require("styled-components"));
3013
+ var import_seeds_react_button = require("@sproutsocial/seeds-react-button");
3014
+ var MenuButtonContainer = import_styled_components9.default.div`
3015
+ display: inline-flex;
3016
+ gap: 1px;
3017
+ `;
3018
+ var MainButton = (0, import_styled_components9.default)(import_seeds_react_button.Button)`
3019
+ && {
3020
+ border-top-right-radius: 0;
3021
+ border-bottom-right-radius: 0;
3022
+ }
3023
+ `;
3024
+ var TriggerButton = (0, import_styled_components9.default)(import_seeds_react_button.Button)`
3025
+ && {
3026
+ border-top-left-radius: 0;
3027
+ border-bottom-left-radius: 0;
3028
+ }
3029
+
3030
+ .Icon-svg {
3031
+ transition: transform ${({ theme }) => theme.duration.fast} ease;
3032
+ }
3033
+
3034
+ &[data-popup-open] .Icon-svg {
3035
+ transform: rotate(180deg);
3036
+ }
3037
+ `;
3038
+
3039
+ // src/v3/MenuButton.tsx
3040
+ var import_jsx_runtime13 = require("react/jsx-runtime");
3041
+ function MenuButton({
3042
+ actionMenu,
3043
+ appearance = "primary",
3044
+ size,
3045
+ disabled,
3046
+ menuButtonAriaLabel,
3047
+ children,
3048
+ ...rest
3049
+ }) {
3050
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(MenuButtonContainer, { children: [
3051
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3052
+ MainButton,
3053
+ {
3054
+ appearance,
3055
+ size,
3056
+ disabled,
3057
+ ...rest,
3058
+ children
3059
+ }
3060
+ ),
3061
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3062
+ ActionMenu,
3063
+ {
3064
+ disabled,
3065
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3066
+ TriggerButton,
3067
+ {
3068
+ appearance,
3069
+ size,
3070
+ disabled,
3071
+ ariaLabel: menuButtonAriaLabel,
3072
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_seeds_react_icon6.Icon, { name: "chevron-down-outline", fixedWidth: true, "aria-hidden": true })
3073
+ }
3074
+ ),
3075
+ children: actionMenu
3076
+ }
3077
+ )
3078
+ ] });
3079
+ }
2894
3080
  // Annotate the CommonJS export names for ESM import in node:
2895
3081
  0 && (module.exports = {
2896
3082
  ActionMenu,
@@ -2916,6 +3102,7 @@ function MenuSubTrigger({
2916
3102
  ComboboxTokenInput,
2917
3103
  ComboboxTokenInputGroup,
2918
3104
  ComboboxTrigger,
3105
+ MenuButton,
2919
3106
  MenuGroup,
2920
3107
  MenuItem,
2921
3108
  MenuRadioGroup,