@sproutsocial/seeds-react-menu 1.0.1 → 1.1.1

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 (42) hide show
  1. package/.turbo/turbo-build.log +85 -9
  2. package/CHANGELOG.md +32 -0
  3. package/dist/esm/index.js +505 -122
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/index.d.mts +45 -16
  6. package/dist/index.d.ts +45 -16
  7. package/dist/index.js +568 -179
  8. package/dist/index.js.map +1 -1
  9. package/package.json +5 -5
  10. package/src/ActionMenu/ActionMenu.tsx +4 -3
  11. package/src/ActionMenu/ActionMenuTypes.ts +5 -4
  12. package/src/ActionMenu/__tests__/ActionMenu.test.tsx +1 -1
  13. package/src/Autocomplete/Autocomplete.stories.tsx +95 -32
  14. package/src/Autocomplete/AutocompleteTypes.ts +5 -2
  15. package/src/Autocomplete/MultiAutocomplete.tsx +3 -2
  16. package/src/Autocomplete/SingleAutocomplete.tsx +3 -3
  17. package/src/Autocomplete/index.ts +1 -0
  18. package/src/ListboxToggleButton.tsx +65 -0
  19. package/src/MenuContent/MenuContentTypes.ts +1 -2
  20. package/src/MenuContent/styles.tsx +2 -9
  21. package/src/MenuGroup/__tests__/MenuGroup.test.tsx +1 -1
  22. package/src/MenuItem/__tests__/MenuItem.test.tsx +1 -3
  23. package/src/MenuRoot/MenuRoot.tsx +95 -15
  24. package/src/MultiSelectMenu/MultiSelectMenu.stories.tsx +0 -1
  25. package/src/MultiSelectMenu/MultiSelectMenu.tsx +3 -2
  26. package/src/MultiSelectMenu/MultiSelectMenuTypes.ts +5 -3
  27. package/src/NestedMenu/NestedMenu.feature +1 -1
  28. package/src/NestedMenu/NestedMenu.stories.tsx +17 -7
  29. package/src/NestedMenu/NestedMenu.tsx +217 -43
  30. package/src/NestedMenu/NestedMenuContext.tsx +16 -0
  31. package/src/NestedMenu/NestedMenuHeader.tsx +19 -6
  32. package/src/NestedMenu/NestedMenuPopout.tsx +55 -0
  33. package/src/NestedMenu/NestedMenuRoot.tsx +27 -0
  34. package/src/NestedMenu/NestedMenuTypes.ts +3 -2
  35. package/src/NestedMenu/__tests__/NestedMenu.test.tsx +210 -19
  36. package/src/SingleSelectMenu/SingleSelectMenu.stories.tsx +0 -1
  37. package/src/SingleSelectMenu/SingleSelectMenu.tsx +3 -2
  38. package/src/SingleSelectMenu/SingleSelectMenuTypes.ts +5 -3
  39. package/src/__tests__/Menu.test.tsx +1 -1
  40. package/src/index.ts +1 -0
  41. package/src/storybookUtilities/menu-storybook-components.tsx +11 -31
  42. package/src/types.ts +5 -1
package/dist/esm/index.js CHANGED
@@ -2118,10 +2118,10 @@ var MenuHeader = ({
2118
2118
 
2119
2119
  // src/MenuContent/styles.tsx
2120
2120
  import styled3 from "styled-components";
2121
- import { motion } from "motion/react";
2122
- var StyledMenuContent = styled3(motion.ul)`
2121
+ var StyledMenuContent = styled3.ul`
2123
2122
  margin: 0;
2124
2123
  padding: 0;
2124
+ outline: none;
2125
2125
  `;
2126
2126
 
2127
2127
  // src/hooks/useMenuChildren.tsx
@@ -2546,12 +2546,78 @@ MenuGroup.__MENU_PRIMITIVE_TYPE = "MenuGroup";
2546
2546
  import { useCallback as useCallback2, useEffect } from "react";
2547
2547
  import styled7 from "styled-components";
2548
2548
  import { Popout } from "@sproutsocial/seeds-react-popout";
2549
+
2550
+ // ../../seeds-design-tokens/seeds-motion/dist/seeds-motion-unitless.esm.js
2551
+ var MOTION_DURATION_FAST = 0.15;
2552
+
2553
+ // src/MenuRoot/MenuRoot.tsx
2549
2554
  import { jsx as jsx10 } from "react/jsx-runtime";
2550
2555
  var CustomPopoutContent = styled7(Popout.Content)`
2551
2556
  padding: 0;
2552
2557
  margin-left: 0;
2553
2558
  margin-right: 0;
2554
2559
  `;
2560
+ var menuAnimationConfig = {
2561
+ initial: {
2562
+ scale: 0,
2563
+ opacity: 0,
2564
+ originX: 0,
2565
+ originY: 0
2566
+ },
2567
+ animate: {
2568
+ opacity: 1,
2569
+ scale: 1,
2570
+ originX: 0,
2571
+ originY: 0,
2572
+ transition: {
2573
+ type: "tween",
2574
+ duration: MOTION_DURATION_FAST,
2575
+ ease: "circOut"
2576
+ }
2577
+ },
2578
+ exit: {
2579
+ opacity: 0,
2580
+ scale: 1,
2581
+ transition: {
2582
+ type: "tween",
2583
+ duration: MOTION_DURATION_FAST,
2584
+ ease: "circIn"
2585
+ }
2586
+ }
2587
+ };
2588
+ var MenuPopout = ({
2589
+ content,
2590
+ width: width2 = "300px",
2591
+ isOpen,
2592
+ openMenu,
2593
+ closeMenu,
2594
+ focusLockProps,
2595
+ ...popoutProps
2596
+ }) => {
2597
+ const setIsOpen = useCallback2(
2598
+ (newIsOpen) => {
2599
+ newIsOpen ? openMenu?.() : closeMenu?.();
2600
+ },
2601
+ [openMenu, closeMenu]
2602
+ );
2603
+ return /* @__PURE__ */ jsx10(
2604
+ Popout,
2605
+ {
2606
+ isOpen: !!isOpen,
2607
+ setIsOpen,
2608
+ content: (props) => /* @__PURE__ */ jsx10(CustomPopoutContent, { width: popoutProps.fullWidth ? "initial" : width2, children: typeof content === "function" ? content(props) : content }),
2609
+ focusLockProps: {
2610
+ // correct jerking motion when scrolling while the Popout is open
2611
+ // returnFocus: false,
2612
+ crossFrame: false,
2613
+ ...focusLockProps
2614
+ },
2615
+ disableWrapperAria: true,
2616
+ animationConfig: menuAnimationConfig,
2617
+ ...popoutProps
2618
+ }
2619
+ );
2620
+ };
2555
2621
  var MenuRoot = ({
2556
2622
  children,
2557
2623
  menuToggleElement,
@@ -2581,25 +2647,26 @@ var MenuRoot = ({
2581
2647
  }, [hiddenItemsCount, items?.length, isOpen, inputValue]);
2582
2648
  const menuContext = useMenu(contextProps);
2583
2649
  return /* @__PURE__ */ jsx10(
2584
- Popout,
2650
+ MenuPopout,
2585
2651
  {
2586
- menuPopout: true,
2587
2652
  placement,
2588
2653
  isOpen: !!isOpen,
2589
- setIsOpen,
2590
- content: /* @__PURE__ */ jsx10(MenuContentProvider, { menuContext, children: /* @__PURE__ */ jsx10(CustomPopoutContent, { width: width2, children }) }),
2591
- focusLockProps: {
2592
- // correct jerking motion when scrolling while the Popout is open
2593
- // returnFocus: false,
2594
- crossFrame: false,
2595
- ...focusLockProps
2596
- },
2597
- disableWrapperAria: true,
2654
+ openMenu,
2655
+ closeMenu,
2656
+ content: /* @__PURE__ */ jsx10(MenuContentProvider, { menuContext, children }),
2598
2657
  ...popoutProps,
2599
2658
  children: (toggleProps) => /* @__PURE__ */ jsx10(MenuToggleProvider, { menuContext: { ...menuContext, ...toggleProps }, children: menuToggleElement })
2600
2659
  }
2601
2660
  );
2602
2661
  };
2662
+ var MenuRootNoPopout = ({
2663
+ children,
2664
+ menuToggleElement,
2665
+ ...contextProps
2666
+ }) => {
2667
+ const menuContext = useMenu(contextProps);
2668
+ return /* @__PURE__ */ jsx10(MenuContentProvider, { menuContext, children });
2669
+ };
2603
2670
 
2604
2671
  // src/MenuLabel.tsx
2605
2672
  import "react";
@@ -3079,6 +3146,43 @@ var SubmenuItem = ({
3079
3146
  };
3080
3147
  SubmenuItem.__MENU_PRIMITIVE_TYPE = "MenuItem";
3081
3148
 
3149
+ // src/ListboxToggleButton.tsx
3150
+ import styled9, { css as css6 } from "styled-components";
3151
+ import { Icon as Icon3 } from "@sproutsocial/seeds-react-icon";
3152
+ import { jsx as jsx17, jsxs as jsxs5 } from "react/jsx-runtime";
3153
+ var StyledListboxToggleButton = styled9(
3154
+ MenuToggleButton
3155
+ )`
3156
+ ${(props) => props.invalid && css6`
3157
+ border-color: ${(props2) => props2.theme.colors.form.border.error};
3158
+ `}
3159
+ `;
3160
+ var StyledChevron = styled9.div`
3161
+ margin-left: ${({ theme: theme2 }) => theme2.space[300]};
3162
+ ${({ $isOpen }) => $isOpen && `
3163
+ transform: rotate(-180deg);
3164
+ `}
3165
+ transition: transform 0.15s;
3166
+
3167
+ ${({ invalid }) => invalid && css6`
3168
+ color: ${(props) => props.theme.colors.icon.error};
3169
+ `}
3170
+ `;
3171
+ var StyledInnerButton = styled9.div`
3172
+ display: flex;
3173
+ justify-content: space-between;
3174
+ `;
3175
+ var ListboxToggleButton = ({
3176
+ children,
3177
+ ...buttonProps
3178
+ }) => {
3179
+ const { isOpen } = useMenuToggleContext();
3180
+ return /* @__PURE__ */ jsx17(StyledListboxToggleButton, { appearance: "secondary", ...buttonProps, children: /* @__PURE__ */ jsxs5(StyledInnerButton, { children: [
3181
+ children,
3182
+ /* @__PURE__ */ jsx17(StyledChevron, { $isOpen: isOpen, invalid: buttonProps.invalid, children: /* @__PURE__ */ jsx17(Icon3, { name: "chevron-down-outline", fixedWidth: true, "aria-hidden": true }) })
3183
+ ] }) });
3184
+ };
3185
+
3082
3186
  // src/ActionMenu/ActionMenu.tsx
3083
3187
  import React16, { useEffect as useEffect2 } from "react";
3084
3188
  import {
@@ -3246,7 +3350,7 @@ var useDownshiftDefaults = ({
3246
3350
  };
3247
3351
 
3248
3352
  // src/ActionMenu/ActionMenu.tsx
3249
- import { jsx as jsx17 } from "react/jsx-runtime";
3353
+ import { jsx as jsx18 } from "react/jsx-runtime";
3250
3354
  var handleStateChange = (changes, currentSelectedItem) => {
3251
3355
  if (!(changes.type === useSelect2.stateChangeTypes.ToggleButtonKeyDownEnter || changes.type === useSelect2.stateChangeTypes.ToggleButtonKeyDownSpaceButton)) {
3252
3356
  return;
@@ -3283,6 +3387,7 @@ var ActionMenu = ({
3283
3387
  menuItems,
3284
3388
  MenuItemComponent,
3285
3389
  stateReducer: externalStateReducer,
3390
+ MenuRootComponent = MenuRoot,
3286
3391
  ...useSelectProps
3287
3392
  }) => {
3288
3393
  const { allMenuItems, menuItemsMap, children } = useMenuChildren({
@@ -3308,8 +3413,8 @@ var ActionMenu = ({
3308
3413
  useEffect2(() => {
3309
3414
  setCurrentSelectedItem(useSelectReturnProps.selectedItem);
3310
3415
  }, [useSelectReturnProps.selectedItem]);
3311
- return /* @__PURE__ */ jsx17(
3312
- MenuRoot,
3416
+ return /* @__PURE__ */ jsx18(
3417
+ MenuRootComponent,
3313
3418
  {
3314
3419
  ...{
3315
3420
  isListbox: false,
@@ -3329,12 +3434,13 @@ var ActionMenu = ({
3329
3434
  // src/SingleSelectMenu/SingleSelectMenu.tsx
3330
3435
  import "react";
3331
3436
  import { useSelect as useSelect3 } from "downshift";
3332
- import { jsx as jsx18 } from "react/jsx-runtime";
3437
+ import { jsx as jsx19 } from "react/jsx-runtime";
3333
3438
  var SingleSelectMenu = ({
3334
3439
  children: childrenProp,
3335
3440
  stateReducer: externalStateReducer,
3336
3441
  menuItems,
3337
3442
  MenuItemComponent,
3443
+ MenuRootComponent = MenuRoot,
3338
3444
  ...useSelectProps
3339
3445
  }) => {
3340
3446
  const { allMenuItems, menuItemsMap, children } = useMenuChildren({
@@ -3355,8 +3461,8 @@ var SingleSelectMenu = ({
3355
3461
  ),
3356
3462
  ...useSelectProps
3357
3463
  });
3358
- return /* @__PURE__ */ jsx18(
3359
- MenuRoot,
3464
+ return /* @__PURE__ */ jsx19(
3465
+ MenuRootComponent,
3360
3466
  {
3361
3467
  ...{
3362
3468
  isListbox: true,
@@ -3376,13 +3482,14 @@ var SingleSelectMenu = ({
3376
3482
  // src/MultiSelectMenu/MultiSelectMenu.tsx
3377
3483
  import "react";
3378
3484
  import { useSelect as useSelect4, useMultipleSelection } from "downshift";
3379
- import { jsx as jsx19 } from "react/jsx-runtime";
3485
+ import { jsx as jsx20 } from "react/jsx-runtime";
3380
3486
  var MultiSelectMenu = ({
3381
3487
  children: childrenProp,
3382
3488
  menuItems,
3383
3489
  MenuItemComponent,
3384
3490
  onSelectedItemChange: externalOnSelectedItemChange,
3385
3491
  stateReducer: externalStateReducer,
3492
+ MenuRootComponent = MenuRoot,
3386
3493
  getA11yMultiStatusMessage,
3387
3494
  onMultiSelectStateChange,
3388
3495
  multiSelectStateReducer,
@@ -3448,8 +3555,8 @@ var MultiSelectMenu = ({
3448
3555
  },
3449
3556
  ...useSelectProps
3450
3557
  });
3451
- return /* @__PURE__ */ jsx19(
3452
- MenuRoot,
3558
+ return /* @__PURE__ */ jsx20(
3559
+ MenuRootComponent,
3453
3560
  {
3454
3561
  ...{
3455
3562
  isListbox: true,
@@ -3481,11 +3588,12 @@ import "react";
3481
3588
  // src/Autocomplete/SingleAutocomplete.tsx
3482
3589
  import "react";
3483
3590
  import { useCombobox as useCombobox2 } from "downshift";
3484
- import { jsx as jsx20 } from "react/jsx-runtime";
3591
+ import { jsx as jsx21 } from "react/jsx-runtime";
3485
3592
  var SingleAutocomplete = ({
3486
3593
  children: childrenProp,
3487
3594
  stateReducer: externalStateReducer,
3488
3595
  menuItems,
3596
+ MenuRootComponent = MenuRoot,
3489
3597
  MenuItemComponent,
3490
3598
  itemToString: itemToString2 = itemToString,
3491
3599
  getIsItemVisible,
@@ -3514,8 +3622,8 @@ var SingleAutocomplete = ({
3514
3622
  ),
3515
3623
  ...useComboboxProps
3516
3624
  });
3517
- return /* @__PURE__ */ jsx20(
3518
- MenuRoot,
3625
+ return /* @__PURE__ */ jsx21(
3626
+ MenuRootComponent,
3519
3627
  {
3520
3628
  ...{
3521
3629
  isListbox: true,
@@ -3538,12 +3646,13 @@ var SingleAutocomplete = ({
3538
3646
  // src/Autocomplete/MultiAutocomplete.tsx
3539
3647
  import React20 from "react";
3540
3648
  import { useCombobox as useCombobox3, useMultipleSelection as useMultipleSelection2 } from "downshift";
3541
- import { jsx as jsx21 } from "react/jsx-runtime";
3649
+ import { jsx as jsx22 } from "react/jsx-runtime";
3542
3650
  var MultiAutocomplete = ({
3543
3651
  children: childrenProp,
3544
3652
  stateReducer: externalStateReducer,
3545
3653
  menuItems,
3546
3654
  MenuItemComponent,
3655
+ MenuRootComponent = MenuRoot,
3547
3656
  itemToString: itemToString2 = itemToString,
3548
3657
  itemToKey: itemToKey3 = itemToKey,
3549
3658
  getIsItemVisible = getDefaultGetIsItemVisible(itemToString2),
@@ -3642,8 +3751,8 @@ var MultiAutocomplete = ({
3642
3751
  },
3643
3752
  ...useComboboxProps
3644
3753
  });
3645
- return /* @__PURE__ */ jsx21(
3646
- MenuRoot,
3754
+ return /* @__PURE__ */ jsx22(
3755
+ MenuRootComponent,
3647
3756
  {
3648
3757
  ...{
3649
3758
  isListbox: true,
@@ -3671,21 +3780,21 @@ var MultiAutocomplete = ({
3671
3780
  };
3672
3781
 
3673
3782
  // src/Autocomplete/Autocomplete.tsx
3674
- import { jsx as jsx22 } from "react/jsx-runtime";
3783
+ import { jsx as jsx23 } from "react/jsx-runtime";
3675
3784
  var Autocomplete = ({
3676
3785
  multiSelect,
3677
3786
  ...rest
3678
3787
  }) => {
3679
3788
  if (multiSelect) {
3680
- return /* @__PURE__ */ jsx22(MultiAutocomplete, { ...rest });
3789
+ return /* @__PURE__ */ jsx23(MultiAutocomplete, { ...rest });
3681
3790
  }
3682
- return /* @__PURE__ */ jsx22(SingleAutocomplete, { ...rest });
3791
+ return /* @__PURE__ */ jsx23(SingleAutocomplete, { ...rest });
3683
3792
  };
3684
3793
 
3685
3794
  // src/Autocomplete/AutocompleteInput.tsx
3686
3795
  import "react";
3687
3796
  import { Input as Input2 } from "@sproutsocial/seeds-react-input";
3688
- import { jsx as jsx23 } from "react/jsx-runtime";
3797
+ import { jsx as jsx24 } from "react/jsx-runtime";
3689
3798
  var AutocompleteInput = ({
3690
3799
  onKeyDown,
3691
3800
  onChange,
@@ -3696,7 +3805,7 @@ var AutocompleteInput = ({
3696
3805
  ...rest
3697
3806
  }) => {
3698
3807
  const { getInputComponentProps, inputValue, ref, ariaProps } = useMenuToggleContext();
3699
- return /* @__PURE__ */ jsx23(
3808
+ return /* @__PURE__ */ jsx24(
3700
3809
  Input2,
3701
3810
  {
3702
3811
  id: "autocomplete_input",
@@ -3720,59 +3829,54 @@ var AutocompleteInput = ({
3720
3829
  );
3721
3830
  };
3722
3831
 
3723
- // src/NestedMenu/NestedMenu.tsx
3724
- import { useState } from "react";
3725
-
3726
- // src/NestedMenu/NestedMenuContext.tsx
3727
- import { createContext as createContext2, useContext as useContext4 } from "react";
3728
- import { jsx as jsx24 } from "react/jsx-runtime";
3729
- var defaultNestedMenuContext = {
3730
- selectedMenuPath: [],
3731
- setSelectedMenuId: () => {
3732
- },
3733
- setSelectedMenuPath: () => {
3734
- },
3735
- goBack: () => {
3736
- }
3737
- };
3738
- var NestedMenuContext = createContext2(
3739
- defaultNestedMenuContext
3740
- );
3741
- var NestedMenuProvider = ({
3742
- children,
3743
- ...nestedMenuProps
3744
- }) => {
3745
- return /* @__PURE__ */ jsx24(NestedMenuContext.Provider, { value: nestedMenuProps, children });
3746
- };
3747
- var useNestedMenuContext = () => {
3748
- const nestedMenuContextValue = useContext4(NestedMenuContext);
3749
- if (nestedMenuContextValue === null) {
3750
- throw new Error(
3751
- "useNestedMenuContext must be used within a <NestedMenuContext.Provider />"
3752
- );
3753
- }
3754
- return nestedMenuContextValue;
3755
- };
3756
-
3757
- // src/NestedMenu/NestedMenuHeader.tsx
3758
- import { Button as Button2 } from "@sproutsocial/seeds-react-button";
3759
- import { Icon as Icon3 } from "@sproutsocial/seeds-react-icon";
3832
+ // src/Autocomplete/AutocompleteTokenInput.tsx
3833
+ import "react";
3760
3834
  import { jsx as jsx25 } from "react/jsx-runtime";
3761
- var NestedMenuHeader = ({
3762
- backArrowLabel,
3763
- ...props
3835
+ var AutocompleteTokenInput = ({
3836
+ onKeyDown,
3837
+ onChange,
3838
+ onInput,
3839
+ onBlur,
3840
+ onClick,
3841
+ inputProps,
3842
+ getTokenProps,
3843
+ ...rest
3764
3844
  }) => {
3765
- const { goBack, selectedMenuPath } = useNestedMenuContext();
3766
- const showBackArrow = selectedMenuPath.length > 1;
3845
+ const {
3846
+ getInputComponentProps,
3847
+ getDropdownProps,
3848
+ inputValue,
3849
+ isOpen,
3850
+ ref,
3851
+ ariaProps
3852
+ } = useMenuToggleContext();
3767
3853
  return /* @__PURE__ */ jsx25(
3768
- MenuHeader,
3854
+ MenuTokenInput,
3769
3855
  {
3770
- leftAction: showBackArrow ? /* @__PURE__ */ jsx25(Button2, { onClick: goBack, ariaLabel: backArrowLabel, children: /* @__PURE__ */ jsx25(Icon3, { name: "arrow-left" }) }) : void 0,
3771
- ...props
3856
+ id: "autocomplete_input",
3857
+ name: "autocomplete_input",
3858
+ ...getInputComponentProps({
3859
+ ...getDropdownProps?.({ ref, preventKeyAction: isOpen }) || { ref },
3860
+ onKeyDown,
3861
+ onChange,
3862
+ onInput,
3863
+ onBlur,
3864
+ onClick,
3865
+ value: inputValue,
3866
+ refKey: "innerRef",
3867
+ inputProps,
3868
+ ...ariaProps
3869
+ }),
3870
+ ...rest
3772
3871
  }
3773
3872
  );
3774
3873
  };
3775
3874
 
3875
+ // src/NestedMenu/NestedMenu.tsx
3876
+ import { useId, useEffect as useEffect4, useState } from "react";
3877
+ import { AnimatePresence as AnimatePresence2, motion as motion3 } from "motion/react";
3878
+ import { useSelect as useSelect6 } from "downshift";
3879
+
3776
3880
  // src/reducers/nestedMenuStateReducer.tsx
3777
3881
  import { useCombobox as useCombobox4, useSelect as useSelect5 } from "downshift";
3778
3882
  var nestedMenuStateReducer = (_state, actionAndChanges) => {
@@ -3797,6 +3901,44 @@ var nestedMenuStateReducer = (_state, actionAndChanges) => {
3797
3901
  }
3798
3902
  };
3799
3903
 
3904
+ // src/NestedMenu/NestedMenuContext.tsx
3905
+ import { createContext as createContext2, useContext as useContext5 } from "react";
3906
+ import { jsx as jsx26 } from "react/jsx-runtime";
3907
+ var defaultNestedMenuContext = {
3908
+ selectedMenuPath: [],
3909
+ setSelectedMenuId: () => {
3910
+ },
3911
+ setSelectedMenuPath: () => {
3912
+ },
3913
+ resetSelectedMenuPath: () => {
3914
+ },
3915
+ goBack: () => {
3916
+ },
3917
+ rootMenuContextProps: {},
3918
+ activeMenuContext: defaultMenuContext,
3919
+ setActiveMenuContext: () => {
3920
+ },
3921
+ animationSpeed: MOTION_DURATION_FAST
3922
+ };
3923
+ var NestedMenuContext = createContext2(
3924
+ defaultNestedMenuContext
3925
+ );
3926
+ var NestedMenuProvider = ({
3927
+ children,
3928
+ ...nestedMenuProps
3929
+ }) => {
3930
+ return /* @__PURE__ */ jsx26(NestedMenuContext.Provider, { value: nestedMenuProps, children });
3931
+ };
3932
+ var useNestedMenuContext = () => {
3933
+ const nestedMenuContextValue = useContext5(NestedMenuContext);
3934
+ if (nestedMenuContextValue === null) {
3935
+ throw new Error(
3936
+ "useNestedMenuContext must be used within a <NestedMenuContext.Provider />"
3937
+ );
3938
+ }
3939
+ return nestedMenuContextValue;
3940
+ };
3941
+
3800
3942
  // src/NestedMenu/NestedMenuContent.tsx
3801
3943
  import { useEffect as useEffect3, useRef } from "react";
3802
3944
  import { mergeRefs as mergeRefs2 } from "@sproutsocial/seeds-react-utilities";
@@ -3804,7 +3946,7 @@ import { mergeRefs as mergeRefs2 } from "@sproutsocial/seeds-react-utilities";
3804
3946
  // src/NestedMenu/NestedMenuItem.tsx
3805
3947
  import { Icon as Icon4 } from "@sproutsocial/seeds-react-icon";
3806
3948
  import { Box as Box4 } from "@sproutsocial/seeds-react-box";
3807
- import { jsx as jsx26, jsxs as jsxs5 } from "react/jsx-runtime";
3949
+ import { jsx as jsx27, jsxs as jsxs6 } from "react/jsx-runtime";
3808
3950
  var NestedMenuItem = ({
3809
3951
  children,
3810
3952
  childMenuId,
@@ -3818,15 +3960,15 @@ var NestedMenuItem = ({
3818
3960
  setSelectedMenuId?.(childMenuId);
3819
3961
  }
3820
3962
  } : {};
3821
- return /* @__PURE__ */ jsx26(MenuItem, { ...onClickProps, ...rest, children: /* @__PURE__ */ jsxs5(Box4, { display: "flex", justifyContent: "space-between", children: [
3963
+ return /* @__PURE__ */ jsx27(MenuItem, { ...onClickProps, ...rest, children: /* @__PURE__ */ jsxs6(Box4, { display: "flex", justifyContent: "space-between", children: [
3822
3964
  children,
3823
- childMenuId && /* @__PURE__ */ jsx26(MenuItemActionRight, { children: /* @__PURE__ */ jsx26(Icon4, { name: "arrow-right-outline" }) })
3965
+ childMenuId && /* @__PURE__ */ jsx27(MenuItemActionRight, { children: /* @__PURE__ */ jsx27(Icon4, { name: "arrow-right-outline" }) })
3824
3966
  ] }) });
3825
3967
  };
3826
3968
  NestedMenuItem.__MENU_PRIMITIVE_TYPE = "MenuItem";
3827
3969
 
3828
3970
  // src/NestedMenu/NestedMenuContent.tsx
3829
- import { jsx as jsx27 } from "react/jsx-runtime";
3971
+ import { jsx as jsx28 } from "react/jsx-runtime";
3830
3972
  var NestedMenuContent = ({
3831
3973
  innerRef: innerRefProp = null,
3832
3974
  onKeyDown: onKeyDownProp,
@@ -3863,7 +4005,7 @@ var NestedMenuContent = ({
3863
4005
  break;
3864
4006
  }
3865
4007
  };
3866
- return /* @__PURE__ */ jsx27(
4008
+ return /* @__PURE__ */ jsx28(
3867
4009
  MenuContent,
3868
4010
  {
3869
4011
  onKeyDown,
@@ -3875,82 +4017,317 @@ var NestedMenuContent = ({
3875
4017
  };
3876
4018
  NestedMenuContent.__MENU_PRIMITIVE_TYPE = "MenuContent";
3877
4019
 
4020
+ // src/NestedMenu/NestedMenuHeader.tsx
4021
+ import { Button as Button2 } from "@sproutsocial/seeds-react-button";
4022
+ import { Icon as Icon5 } from "@sproutsocial/seeds-react-icon";
4023
+ import { AnimatePresence, motion } from "motion/react";
4024
+ import { jsx as jsx29 } from "react/jsx-runtime";
4025
+ var NestedMenuHeader = ({
4026
+ backArrowLabel,
4027
+ ...props
4028
+ }) => {
4029
+ const { goBack, selectedMenuPath, animationSpeed } = useNestedMenuContext();
4030
+ const showBackArrow = selectedMenuPath.length > 1;
4031
+ return /* @__PURE__ */ jsx29(
4032
+ MenuHeader,
4033
+ {
4034
+ leftAction: /* @__PURE__ */ jsx29(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx29(
4035
+ motion.div,
4036
+ {
4037
+ initial: { opacity: 0 },
4038
+ animate: { opacity: 1 },
4039
+ exit: {
4040
+ opacity: 0,
4041
+ transition: { duration: animationSpeed }
4042
+ },
4043
+ children: showBackArrow ? /* @__PURE__ */ jsx29(Button2, { onClick: goBack, ariaLabel: backArrowLabel, children: /* @__PURE__ */ jsx29(Icon5, { name: "arrow-left" }) }) : void 0
4044
+ },
4045
+ `${selectedMenuPath}-header--button`
4046
+ ) }),
4047
+ ...props
4048
+ }
4049
+ );
4050
+ };
4051
+
4052
+ // src/NestedMenu/NestedMenuRoot.tsx
4053
+ import React24 from "react";
4054
+ import { jsx as jsx30 } from "react/jsx-runtime";
4055
+ var NestedMenuRoot = ({
4056
+ children,
4057
+ menuToggleElement,
4058
+ ...contextProps
4059
+ }) => {
4060
+ const menuContext = useMenu(contextProps);
4061
+ const { setActiveMenuContext, selectedMenuPath } = useNestedMenuContext();
4062
+ React24.useEffect(() => {
4063
+ setActiveMenuContext(menuContext);
4064
+ }, [
4065
+ selectedMenuPath[selectedMenuPath.length - 1],
4066
+ menuContext.selectedItem,
4067
+ menuContext.selectedItems?.length
4068
+ ]);
4069
+ return /* @__PURE__ */ jsx30(MenuContentProvider, { menuContext, children });
4070
+ };
4071
+
4072
+ // src/NestedMenu/NestedMenuPopout.tsx
4073
+ import { motion as motion2 } from "motion/react";
4074
+ import styled10 from "styled-components";
4075
+ import { jsx as jsx31 } from "react/jsx-runtime";
4076
+ var StyledDiv = styled10(motion2.div)`
4077
+ overflow: hidden;
4078
+ `;
4079
+ var NestedMenuPopout = ({
4080
+ content,
4081
+ menuToggleElement,
4082
+ width: width2,
4083
+ ...popoutProps
4084
+ }) => {
4085
+ const { activeMenuContext, rootMenuContextProps, resetSelectedMenuPath } = useNestedMenuContext();
4086
+ return /* @__PURE__ */ jsx31(
4087
+ MenuPopout,
4088
+ {
4089
+ ...popoutProps,
4090
+ onClose: () => setTimeout(() => resetSelectedMenuPath?.(), 100),
4091
+ isOpen: !!rootMenuContextProps.isOpen,
4092
+ openMenu: rootMenuContextProps.openMenu,
4093
+ closeMenu: rootMenuContextProps.closeMenu,
4094
+ width: width2,
4095
+ content: (props) => /* @__PURE__ */ jsx31(StyledDiv, { layout: "position", children: typeof content === "function" ? content(props) : content }),
4096
+ children: (toggleProps) => /* @__PURE__ */ jsx31(
4097
+ MenuToggleProvider,
4098
+ {
4099
+ menuContext: {
4100
+ ...activeMenuContext,
4101
+ ...rootMenuContextProps,
4102
+ ...toggleProps
4103
+ },
4104
+ children: menuToggleElement
4105
+ }
4106
+ )
4107
+ }
4108
+ );
4109
+ };
4110
+
3878
4111
  // src/NestedMenu/NestedMenu.tsx
3879
- import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs6 } from "react/jsx-runtime";
4112
+ import { jsx as jsx32, jsxs as jsxs7 } from "react/jsx-runtime";
3880
4113
  var NestedMenu = ({
3881
4114
  initialMenuId,
3882
4115
  menus,
3883
4116
  onBackButtonClick,
3884
4117
  backArrowLabel,
3885
- menuToggleElement
4118
+ menuToggleElement,
4119
+ popoutProps = {},
4120
+ width: width2 = "300px",
4121
+ stateReducer: rootExternalStateReducer,
4122
+ id: externalNestedMenuId,
4123
+ ...useSelectProps
3886
4124
  }) => {
4125
+ const { defaultDownshiftProps, ...restDefaults } = useDownshiftDefaults({
4126
+ isCombobox: false
4127
+ });
4128
+ const uniqueId = useId();
4129
+ const nestedMenuId = externalNestedMenuId ?? `nested-menu-${uniqueId}`;
4130
+ const [hasLoadedOnce, setHasLoadedOnce] = useState(false);
4131
+ const useSelectReturnProps = useSelect6({
4132
+ ...defaultDownshiftProps.select,
4133
+ id: nestedMenuId,
4134
+ items: [],
4135
+ stateReducer: reduceReducers(
4136
+ defaultDownshiftProps.select.stateReducer,
4137
+ rootExternalStateReducer
4138
+ ),
4139
+ ...useSelectProps
4140
+ });
4141
+ const rootMenuContextProps = {
4142
+ ...useSelectProps,
4143
+ ...useSelectReturnProps,
4144
+ ...restDefaults
4145
+ };
4146
+ useEffect4(() => {
4147
+ if (!useSelectReturnProps.isOpen) {
4148
+ setHasLoadedOnce(false);
4149
+ } else {
4150
+ !hasLoadedOnce && setHasLoadedOnce(true);
4151
+ }
4152
+ }, [useSelectReturnProps.isOpen]);
4153
+ const onNestedIsOpenChange = ({
4154
+ isOpen: newIsOpen
4155
+ }) => {
4156
+ !newIsOpen && useSelectReturnProps.closeMenu?.();
4157
+ };
4158
+ const nestedMenuPropsFromRoot = {
4159
+ // The selected menu needs to receive this id so that the toggle element can be properly associated with it.
4160
+ id: nestedMenuId,
4161
+ onIsOpenChange: onNestedIsOpenChange
4162
+ };
3887
4163
  const [selectedMenuPath, setSelectedMenuPath] = useState([initialMenuId]);
3888
- const selectedMenuId = selectedMenuPath[selectedMenuPath.length - 1];
4164
+ const [activeMenuContext, setActiveMenuContext] = useState(defaultMenuContext);
4165
+ const [currentMenuId, setCurrentMenuId] = useState(initialMenuId);
4166
+ const [isAdding, setIsAdding] = useState(false);
3889
4167
  const setSelectedMenuId = (id) => {
4168
+ setIsAdding(true);
3890
4169
  setSelectedMenuPath((currentPath) => [...currentPath, id]);
3891
4170
  };
4171
+ useEffect4(() => {
4172
+ if (selectedMenuPath.length > 0) {
4173
+ const newMenuId = selectedMenuPath[selectedMenuPath.length - 1];
4174
+ setCurrentMenuId(newMenuId);
4175
+ }
4176
+ }, [selectedMenuPath.join("-")]);
4177
+ const resetSelectedMenuPath = () => {
4178
+ setSelectedMenuPath([initialMenuId]);
4179
+ setCurrentMenuId(initialMenuId);
4180
+ };
3892
4181
  const goBack = () => {
4182
+ setIsAdding(false);
3893
4183
  setSelectedMenuPath((currentPath) => currentPath.slice(0, -1));
3894
- onBackButtonClick?.(selectedMenuId);
4184
+ onBackButtonClick?.(currentMenuId);
3895
4185
  };
3896
4186
  const {
3897
4187
  MenuComponent,
3898
4188
  menuProps,
3899
4189
  MenuHeaderComponent = NestedMenuHeader,
3900
4190
  menuHeaderProps = {}
3901
- } = menus[selectedMenuId] || {};
4191
+ } = menus[currentMenuId] || {};
3902
4192
  const {
3903
4193
  children,
3904
4194
  menuItems,
3905
4195
  MenuItemComponent,
3906
4196
  stateReducer: externalStateReducer,
3907
- onStateChange: externalOnStateChange,
3908
- ...props
4197
+ ...restMenuProps
3909
4198
  } = menuProps || {};
3910
4199
  const stateReducer = reduceReducers(
3911
4200
  nestedMenuStateReducer,
3912
4201
  externalStateReducer
3913
4202
  );
3914
- const onStateChange = (changes) => {
3915
- externalOnStateChange?.(changes);
3916
- if (changes.isOpen === false) {
3917
- setTimeout(() => {
3918
- setSelectedMenuPath([initialMenuId]);
3919
- }, 100);
3920
- }
4203
+ const animationSpeed = MOTION_DURATION_FAST;
4204
+ const contentVariants = {
4205
+ arrive: (custom = { hasLoadedOnce: false, isAdding: false }) => ({
4206
+ opacity: 0,
4207
+ // Start from left if is first render of root, else use default
4208
+ x: !custom?.hasLoadedOnce ? "200%" : custom?.isAdding ? "200%" : "-200%"
4209
+ }),
4210
+ enter: (custom = { hasLoadedOnce: false }) => ({
4211
+ opacity: 1,
4212
+ x: 0,
4213
+ transition: {
4214
+ type: "tween",
4215
+ duration: animationSpeed,
4216
+ ease: "circOut",
4217
+ delay: !custom.hasLoadedOnce ? animationSpeed : 0
4218
+ }
4219
+ }),
4220
+ leave: (custom = { hasLoadedOnce: false, isAdding: false }) => ({
4221
+ opacity: 0,
4222
+ x: custom?.isAdding ? "-200%" : "200%",
4223
+ transition: {
4224
+ type: "tween",
4225
+ duration: animationSpeed,
4226
+ ease: "circIn"
4227
+ }
4228
+ })
4229
+ };
4230
+ const menuVariants = {
4231
+ arrive: (custom = { hasLoadedOnce: false, isAdding: false }) => ({
4232
+ opacity: 0,
4233
+ // Start from left if is first render of root, else use default
4234
+ x: !custom?.hasLoadedOnce ? "200%" : custom?.isAdding ? "200%" : "-200%"
4235
+ }),
4236
+ enter: (custom = { hasLoadedOnce: false }) => ({
4237
+ opacity: 1,
4238
+ x: 0,
4239
+ transition: {
4240
+ type: "tween",
4241
+ duration: animationSpeed,
4242
+ ease: "circOut",
4243
+ delay: !custom.hasLoadedOnce ? animationSpeed : 0
4244
+ }
4245
+ }),
4246
+ leave: (custom = { hasLoadedOnce: false, isAdding: false }) => ({
4247
+ opacity: 0,
4248
+ x: custom?.isAdding ? "-200%" : "200%",
4249
+ transition: {
4250
+ type: "tween",
4251
+ duration: animationSpeed,
4252
+ ease: "circIn"
4253
+ }
4254
+ })
3921
4255
  };
3922
4256
  const nestedMenuProps = {
4257
+ ...nestedMenuPropsFromRoot,
3923
4258
  menuToggleElement,
3924
4259
  stateReducer,
3925
- onStateChange,
3926
- initialIsOpen: selectedMenuPath.length > 1,
3927
- children: /* @__PURE__ */ jsxs6(Fragment4, { children: [
3928
- MenuHeaderComponent && /* @__PURE__ */ jsx28(
3929
- MenuHeaderComponent,
3930
- {
3931
- backArrowLabel,
3932
- ...menuHeaderProps
3933
- }
3934
- ),
3935
- children && children,
3936
- menuItems && !children && /* @__PURE__ */ jsx28(
3937
- NestedMenuContent,
4260
+ MenuRootComponent: NestedMenuRoot,
4261
+ // This ensures that onNestedIsOpenChange will be triggered if the selected menu attempts to close itself.
4262
+ initialIsOpen: true,
4263
+ children: (
4264
+ // Handles the smooth animating of the content
4265
+ /* @__PURE__ */ jsx32(AnimatePresence2, { mode: "wait", children: /* @__PURE__ */ jsxs7(
4266
+ motion3.div,
3938
4267
  {
3939
- menuItems,
3940
- MenuItemComponent: MenuItemComponent ?? NestedMenuItem
3941
- }
3942
- )
3943
- ] }),
3944
- ...props
4268
+ variants: contentVariants,
4269
+ initial: "arrive",
4270
+ animate: "enter",
4271
+ exit: "leave",
4272
+ custom: { isAdding, hasLoadedOnce },
4273
+ children: [
4274
+ MenuHeaderComponent && /* @__PURE__ */ jsx32(
4275
+ MenuHeaderComponent,
4276
+ {
4277
+ backArrowLabel,
4278
+ ...menuHeaderProps
4279
+ }
4280
+ ),
4281
+ children && children,
4282
+ menuItems && !children && /* @__PURE__ */ jsx32(
4283
+ NestedMenuContent,
4284
+ {
4285
+ menuItems,
4286
+ MenuItemComponent: MenuItemComponent ?? NestedMenuItem
4287
+ }
4288
+ )
4289
+ ]
4290
+ },
4291
+ currentMenuId
4292
+ ) })
4293
+ ),
4294
+ ...restMenuProps
3945
4295
  };
3946
- return /* @__PURE__ */ jsx28(
4296
+ return /* @__PURE__ */ jsx32(
3947
4297
  NestedMenuProvider,
3948
4298
  {
3949
- selectedMenuPath,
3950
- setSelectedMenuPath,
3951
- setSelectedMenuId,
3952
- goBack,
3953
- children: MenuComponent && /* @__PURE__ */ jsx28(MenuComponent, { ...nestedMenuProps })
4299
+ ...{
4300
+ selectedMenuPath,
4301
+ setSelectedMenuPath,
4302
+ setSelectedMenuId,
4303
+ resetSelectedMenuPath,
4304
+ goBack,
4305
+ rootMenuContextProps,
4306
+ activeMenuContext,
4307
+ setActiveMenuContext,
4308
+ animationSpeed
4309
+ },
4310
+ children: /* @__PURE__ */ jsx32(
4311
+ NestedMenuPopout,
4312
+ {
4313
+ content: MenuComponent && // Handles the rerender of the component
4314
+ /* @__PURE__ */ jsx32(AnimatePresence2, { mode: "wait", children: /* @__PURE__ */ jsx32(
4315
+ motion3.div,
4316
+ {
4317
+ variants: menuVariants,
4318
+ initial: "arrive",
4319
+ animate: "enter",
4320
+ exit: "leave",
4321
+ custom: { isAdding, hasLoadedOnce },
4322
+ children: /* @__PURE__ */ jsx32(MenuComponent, { ...nestedMenuProps })
4323
+ },
4324
+ `${currentMenuId}-content`
4325
+ ) }),
4326
+ menuToggleElement,
4327
+ width: width2,
4328
+ ...popoutProps
4329
+ }
4330
+ )
3954
4331
  }
3955
4332
  );
3956
4333
  };
@@ -3958,7 +4335,10 @@ export {
3958
4335
  ActionMenu,
3959
4336
  Autocomplete,
3960
4337
  AutocompleteInput,
4338
+ AutocompleteTokenInput,
4339
+ CustomPopoutContent,
3961
4340
  INPUT_TYPES,
4341
+ ListboxToggleButton,
3962
4342
  MenuContent,
3963
4343
  MenuContentContext,
3964
4344
  MenuContentProvider,
@@ -3973,7 +4353,9 @@ export {
3973
4353
  MenuItemRow,
3974
4354
  MenuItemText,
3975
4355
  MenuLabel,
4356
+ MenuPopout,
3976
4357
  MenuRoot,
4358
+ MenuRootNoPopout,
3977
4359
  MenuSearchInput,
3978
4360
  MenuSearchTokenInput,
3979
4361
  MenuToggleButton,
@@ -3988,6 +4370,7 @@ export {
3988
4370
  NestedMenuItem,
3989
4371
  NestedMenuProvider,
3990
4372
  SingleSelectMenu,
4373
+ StyledListboxToggleButton,
3991
4374
  StyledMenuGroup,
3992
4375
  StyledMenuGroupUl,
3993
4376
  StyledMenuItem,