@elliemae/ds-global-header 3.70.0-next.7 → 3.70.0-next.71

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 (155) hide show
  1. package/dist/cjs/DSGlobalHeader.js +16 -2
  2. package/dist/cjs/DSGlobalHeader.js.map +2 -2
  3. package/dist/cjs/DSGlobalHeaderContext.js.map +2 -2
  4. package/dist/cjs/config/useGlobalHeader.js +13 -2
  5. package/dist/cjs/config/useGlobalHeader.js.map +2 -2
  6. package/dist/cjs/constants/index.js +11 -5
  7. package/dist/cjs/constants/index.js.map +2 -2
  8. package/dist/cjs/index.js +3 -6
  9. package/dist/cjs/index.js.map +3 -3
  10. package/dist/cjs/package.json +1 -4
  11. package/dist/cjs/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js +33 -1
  12. package/dist/cjs/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js.map +2 -2
  13. package/dist/cjs/parts/Logo/GlobalHeaderLogo.js +16 -2
  14. package/dist/cjs/parts/Logo/GlobalHeaderLogo.js.map +2 -2
  15. package/dist/cjs/parts/Toolbar/GlobalHeaderToolbar.js +54 -16
  16. package/dist/cjs/parts/Toolbar/GlobalHeaderToolbar.js.map +2 -2
  17. package/dist/cjs/{utils/useCallbackAfterRender.js → parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js} +7 -16
  18. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js.map +7 -0
  19. package/dist/cjs/{hooks/useOnClickOutside.js → parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js} +13 -30
  20. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js.map +7 -0
  21. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js +53 -0
  22. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js.map +7 -0
  23. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js +84 -0
  24. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js.map +7 -0
  25. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js +50 -0
  26. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js.map +7 -0
  27. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js +66 -0
  28. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js.map +7 -0
  29. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js +118 -71
  30. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js.map +3 -3
  31. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js +27 -11
  32. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js.map +2 -2
  33. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js +52 -0
  34. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js.map +7 -0
  35. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js +23 -15
  36. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js.map +2 -2
  37. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js +54 -0
  38. package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js.map +7 -0
  39. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js +28 -16
  40. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js.map +2 -2
  41. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js +61 -50
  42. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js.map +2 -2
  43. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js +58 -0
  44. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js.map +7 -0
  45. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js +33 -25
  46. package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js.map +2 -2
  47. package/dist/cjs/parts/Toolbar/outOfTheBox/index.js +12 -4
  48. package/dist/cjs/parts/Toolbar/outOfTheBox/index.js.map +2 -2
  49. package/dist/cjs/parts/Toolbar/styles.js +6 -1
  50. package/dist/cjs/parts/Toolbar/styles.js.map +2 -2
  51. package/dist/cjs/react-desc-prop-types.js.map +2 -2
  52. package/dist/cjs/sharedTypes.js.map +1 -1
  53. package/dist/cjs/typescript-testing/typescript-global-header-toolbar-types.js +52 -0
  54. package/dist/cjs/typescript-testing/typescript-global-header-toolbar-types.js.map +2 -2
  55. package/dist/esm/DSGlobalHeader.js +16 -2
  56. package/dist/esm/DSGlobalHeader.js.map +2 -2
  57. package/dist/esm/DSGlobalHeaderContext.js.map +2 -2
  58. package/dist/esm/config/useGlobalHeader.js +13 -2
  59. package/dist/esm/config/useGlobalHeader.js.map +2 -2
  60. package/dist/esm/constants/index.js +11 -5
  61. package/dist/esm/constants/index.js.map +2 -2
  62. package/dist/esm/index.js +3 -6
  63. package/dist/esm/index.js.map +3 -3
  64. package/dist/esm/package.json +1 -4
  65. package/dist/esm/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js +34 -2
  66. package/dist/esm/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js.map +2 -2
  67. package/dist/esm/parts/Logo/GlobalHeaderLogo.js +16 -2
  68. package/dist/esm/parts/Logo/GlobalHeaderLogo.js.map +2 -2
  69. package/dist/esm/parts/Toolbar/GlobalHeaderToolbar.js +55 -17
  70. package/dist/esm/parts/Toolbar/GlobalHeaderToolbar.js.map +2 -2
  71. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js +8 -0
  72. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js.map +7 -0
  73. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js +13 -0
  74. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js.map +7 -0
  75. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js +23 -0
  76. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js.map +7 -0
  77. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js +54 -0
  78. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js.map +7 -0
  79. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js +20 -0
  80. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js.map +7 -0
  81. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js +36 -0
  82. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js.map +7 -0
  83. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js +119 -72
  84. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js.map +2 -2
  85. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js +28 -12
  86. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js.map +2 -2
  87. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js +22 -0
  88. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js.map +7 -0
  89. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js +24 -16
  90. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js.map +2 -2
  91. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js +24 -0
  92. package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js.map +7 -0
  93. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js +34 -17
  94. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js.map +2 -2
  95. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js +61 -50
  96. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js.map +2 -2
  97. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js +28 -0
  98. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js.map +7 -0
  99. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js +33 -25
  100. package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js.map +2 -2
  101. package/dist/esm/parts/Toolbar/outOfTheBox/index.js +8 -3
  102. package/dist/esm/parts/Toolbar/outOfTheBox/index.js.map +2 -2
  103. package/dist/esm/parts/Toolbar/styles.js +6 -1
  104. package/dist/esm/parts/Toolbar/styles.js.map +2 -2
  105. package/dist/esm/react-desc-prop-types.js.map +2 -2
  106. package/dist/esm/typescript-testing/typescript-global-header-toolbar-types.js +52 -0
  107. package/dist/esm/typescript-testing/typescript-global-header-toolbar-types.js.map +2 -2
  108. package/dist/types/DSGlobalHeaderContext.d.ts +10 -2
  109. package/dist/types/config/useGlobalHeader.d.ts +3 -4
  110. package/dist/types/constants/index.d.ts +4 -3
  111. package/dist/types/index.d.ts +0 -2
  112. package/dist/types/parts/Breadcrumb/PureBreadcrumb.d.ts +1 -1
  113. package/dist/types/parts/Breadcrumb/styles.d.ts +1 -1
  114. package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.d.ts +4 -0
  115. package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.d.ts +2 -0
  116. package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.d.ts +1 -0
  117. package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.d.ts +2 -0
  118. package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.d.ts +23 -0
  119. package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.d.ts +456 -0
  120. package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.d.ts +2 -2
  121. package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.d.ts +2 -2
  122. package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.d.ts +28 -0
  123. package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.d.ts +9 -1
  124. package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.d.ts +26 -0
  125. package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.d.ts +2 -2
  126. package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.d.ts +3 -1
  127. package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.d.ts +26 -0
  128. package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.d.ts +2 -3
  129. package/dist/types/parts/Toolbar/outOfTheBox/index.d.ts +3 -3
  130. package/dist/types/parts/Toolbar/styles.d.ts +1 -0
  131. package/dist/types/react-desc-prop-types.d.ts +63 -72
  132. package/dist/types/sharedTypes.d.ts +16 -6
  133. package/package.json +20 -17
  134. package/dist/cjs/hooks/useOnClickOutside.js.map +0 -7
  135. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js +0 -127
  136. package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js.map +0 -7
  137. package/dist/cjs/utils/useCallbackAfterRender.js.map +0 -7
  138. package/dist/esm/hooks/useOnClickOutside.js +0 -30
  139. package/dist/esm/hooks/useOnClickOutside.js.map +0 -7
  140. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js +0 -97
  141. package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js.map +0 -7
  142. package/dist/esm/utils/useCallbackAfterRender.js +0 -17
  143. package/dist/esm/utils/useCallbackAfterRender.js.map +0 -7
  144. package/dist/types/hooks/useOnClickOutside.d.ts +0 -1
  145. package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.d.ts +0 -6
  146. package/dist/types/tests/GlobalHeader.a11y.test.d.ts +0 -1
  147. package/dist/types/tests/GlobalHeader.callback.test.d.ts +0 -1
  148. package/dist/types/tests/GlobalHeader.getOwnerProps.test.d.ts +0 -1
  149. package/dist/types/tests/GlobalHeader.keyboard.test.d.ts +0 -1
  150. package/dist/types/tests/GlobalHeader.setup.test.d.ts +0 -113
  151. package/dist/types/typescript-testing/typescript-global-header-breadcrumb-types.d.ts +0 -3
  152. package/dist/types/typescript-testing/typescript-global-header-deprecated.d.ts +0 -1
  153. package/dist/types/typescript-testing/typescript-global-header-toolbar-types.d.ts +0 -3
  154. package/dist/types/typescript-testing/typescript-global-header-valid.d.ts +0 -1
  155. package/dist/types/utils/useCallbackAfterRender.d.ts +0 -3
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../scripts/build/transpile/react-shim.js", "../../../../../../src/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { DSAppPicker } from '@elliemae/ds-app-picker';\nimport React from 'react';\nimport { AppPickerCtx } from './AppPickerCTX.js';\nimport { TriggerDefaultComponent } from './TriggerDefaultComponent.js';\n\nexport const AppPickerRenderer = (): JSX.Element => {\n const { contractProps, id } = React.useContext(AppPickerCtx);\n\n /*\n * Our default trigger applies only when the consumer supplied neither trigger API.\n *\n * This one cannot be expressed by spread order, unlike every other default below. DSAppPicker's\n * Trigger gives `TriggerComponent` precedence over `renderTrigger` (Trigger.tsx: \"TriggerComponent\n * wins when both custom APIs are supplied\"), so passing ours unconditionally would silently discard a\n * consumer's `renderTrigger` no matter where `contractProps` is spread \u2014 the spread would forward\n * their prop faithfully and DSAppPicker would then ignore it. Deciding here instead keeps both custom\n * trigger APIs working through the toolbar config.\n */\n const consumerOwnsTheTrigger = Boolean(contractProps.renderTrigger || contractProps.TriggerComponent);\n\n return (\n <DSAppPicker\n // Dimsum IoC direction: our default renders first and the consumer's contract props are spread over\n // it, so anything they put in `componentProps` wins and becomes theirs to own.\n // `getDSAppPickerContractProps` drops keys explicitly set to undefined, so an unset key in the config\n // never erases a default here.\n //\n // Note what is NOT passed: no `isOpen`, no `onKeyDown`, no `onClickOutside`. Passing `isOpen` makes\n // the picker controlled and passing `onKeyDown` switches off its Escape routing and focus return \u2014\n // either way this part would owe a reimplementation of behaviour DSAppPicker already has. See\n // useAppPickerCTX for the full statement.\n //\n // The toolbar is a menubar, so ArrowDown/ArrowUp on a toolbar item open it \u2014 that is this widget's\n // keyboard contract, not an application-level choice, which is why it is opted in here rather than\n // left to each consumer. The picker owns the whole flow: it records the arrow-key activation and\n // seeds focus on the selected app (first for ArrowDown, last for ArrowUp). Spread order still lets a\n // consumer turn it off through `componentProps`.\n openAndFocusOnArrowKeys\n // `TriggerComponent`, not the deprecated `renderTrigger`: DSAppPicker renders this one as JSX so it\n // gets its own fiber and may use hooks, and it is the only trigger API that receives the id the\n // panel's aria-labelledby points at. See TriggerDefaultComponent for the full reasoning.\n {...(consumerOwnsTheTrigger ? {} : { TriggerComponent: TriggerDefaultComponent })}\n /*\n * PUI-18985 \u2014 the item-level `id` names the App Picker, and DSAppPicker derives every id in the\n * widget from it: the root takes it unchanged, the trigger becomes `getIdForAppPickerTrigger(id)`, and the\n * dialog's `aria-labelledby` points at that same trigger id. Handing it over here is what makes\n * those three agree.\n *\n * Before this, `id` rode along in `otherProps` and was spread onto the trigger AFTER the id\n * DSAppPicker had supplied, so the trigger carried the bare item id while the dialog still pointed\n * at the generated one \u2014 a pointer to no element, and a dialog with no accessible name (axe\n * `aria-dialog-name`, serious). useAppPickerCTX now reads `id` out of `otherProps` so only this\n * route exists.\n *\n * Consumers who addressed the trigger by the bare item id migrate to `getIdForAppPickerTrigger`, exported by\n * ds-app-picker; the bare id now selects the picker root. Omitted when unset, so DSAppPicker's own\n * generated instance id is untouched.\n */\n {...(id ? { id } : {})}\n {...contractProps}\n />\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACqBnB;AArBJ,SAAS,mBAAmB;AAC5B,OAAOA,YAAW;AAClB,SAAS,oBAAoB;AAC7B,SAAS,+BAA+B;AAEjC,MAAM,oBAAoB,MAAmB;AAClD,QAAM,EAAE,eAAe,GAAG,IAAIA,OAAM,WAAW,YAAY;AAY3D,QAAM,yBAAyB,QAAQ,cAAc,iBAAiB,cAAc,gBAAgB;AAEpG,SACE;AAAA,IAAC;AAAA;AAAA,MAgBC,yBAAuB;AAAA,MAItB,GAAI,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,wBAAwB;AAAA,MAiB9E,GAAI,KAAK,EAAE,GAAG,IAAI,CAAC;AAAA,MACnB,GAAG;AAAA;AAAA,EACN;AAEJ;",
6
+ "names": ["React"]
7
+ }
@@ -0,0 +1,54 @@
1
+ import * as React from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { MenuPicker } from "@elliemae/ds-icons";
4
+ import { getGlobalAttributes, getXstyledProps } from "@elliemae/ds-props-helpers";
5
+ import { mergeRefs } from "@elliemae/ds-system";
6
+ import React2 from "react";
7
+ import { GLOBAL_HEADER_DATA_TESTID } from "../../../../constants/index.js";
8
+ import { StyledButton } from "../../../styles.js";
9
+ import { AppPickerCtx } from "./AppPickerCTX.js";
10
+ const TriggerDefaultComponent = ({
11
+ innerRef,
12
+ id,
13
+ onClick: appPickerOnClick,
14
+ onKeyDown: appPickerOnKeyDown,
15
+ "aria-haspopup": ariaHasPopup
16
+ }) => {
17
+ const { triggerOnClick, setRef, triggerRef, label, otherProps, getOwnerPropsAwareOfPropsPassedToGlobalHeader } = React2.useContext(AppPickerCtx);
18
+ const handleTriggerRefs = React2.useCallback(
19
+ (buttonRef) => {
20
+ setRef(buttonRef);
21
+ mergeRefs(triggerRef, innerRef)(buttonRef);
22
+ },
23
+ [setRef, triggerRef, innerRef]
24
+ );
25
+ const handleOnClickComposed = React2.useCallback(
26
+ (e) => {
27
+ appPickerOnClick(e);
28
+ triggerOnClick?.(e);
29
+ },
30
+ [appPickerOnClick, triggerOnClick]
31
+ );
32
+ return /* @__PURE__ */ jsx(
33
+ StyledButton,
34
+ {
35
+ id,
36
+ onClick: handleOnClickComposed,
37
+ onKeyDown: appPickerOnKeyDown,
38
+ innerRef: handleTriggerRefs,
39
+ "aria-label": label,
40
+ "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_BUTTON,
41
+ "aria-haspopup": ariaHasPopup,
42
+ ...getGlobalAttributes(otherProps),
43
+ ...getXstyledProps(otherProps),
44
+ type: "button",
45
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
46
+ getOwnerPropsArguments: () => ({}),
47
+ children: /* @__PURE__ */ jsx(MenuPicker, { width: 20.73, height: 20.73 })
48
+ }
49
+ );
50
+ };
51
+ export {
52
+ TriggerDefaultComponent
53
+ };
54
+ //# sourceMappingURL=TriggerDefaultComponent.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../scripts/build/transpile/react-shim.js", "../../../../../../src/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import type { DSAppPickerT } from '@elliemae/ds-app-picker';\nimport { MenuPicker } from '@elliemae/ds-icons';\nimport { getGlobalAttributes, getXstyledProps } from '@elliemae/ds-props-helpers';\nimport { mergeRefs } from '@elliemae/ds-system';\nimport React from 'react';\nimport { GLOBAL_HEADER_DATA_TESTID } from '../../../../constants/index.js';\nimport { StyledButton } from '../../../styles.js';\nimport { AppPickerCtx } from './AppPickerCTX.js';\n\n/*\n * The toolbar's default App Picker trigger, as a real component with its own module.\n *\n * MUST be handed to DSAppPicker as `TriggerComponent`, never `renderTrigger`. Two reasons, both hard:\n *\n * 1. This component uses `useContext`. DSAppPicker renders `TriggerComponent` as JSX so React creates a\n * fiber for it, which is what makes hooks here legal. `renderTrigger` is invoked as a plain function\n * (`renderTrigger({ ref })`) to honour the legacy DSPopover render-prop contract, so any hook inside\n * it registers against DSAppPicker's Trigger fiber instead \u2014 a rules-of-hooks violation React cannot\n * detect at runtime.\n * 2. Only `TriggerComponent` receives `dialogLabelId`, the id the panel's `aria-labelledby` points at.\n * It arrives as `id` and is applied below; drop it and the dialog has no accessible name.\n */\nexport const TriggerDefaultComponent = ({\n innerRef,\n id,\n onClick: appPickerOnClick,\n onKeyDown: appPickerOnKeyDown,\n 'aria-haspopup': ariaHasPopup,\n}: DSAppPickerT.TriggerComponentProps): JSX.Element => {\n const { triggerOnClick, setRef, triggerRef, label, otherProps, getOwnerPropsAwareOfPropsPassedToGlobalHeader } =\n React.useContext(AppPickerCtx);\n\n /*\n * Three refs on one node: the toolbar's arrow-key roving registration, a consumer-supplied `triggerRef`,\n * and DSAppPicker's own \u2014 the last is what its focus return targets after a scoped Escape, so dropping\n * `innerRef` here silently strands focus when the panel closes.\n *\n * No focus logic beyond that. Returning focus to this trigger is DSAppPicker's job and it does it, which\n * is only true while this part supplies no `onKeyDown` to it \u2014 see useAppPickerCTX.\n */\n const handleTriggerRefs = React.useCallback(\n (buttonRef: HTMLButtonElement) => {\n setRef(buttonRef);\n mergeRefs(triggerRef, innerRef)(buttonRef);\n },\n [setRef, triggerRef, innerRef],\n );\n\n /*\n * DSAppPicker's `onClick` does the opening AND records whether the activation came from the keyboard\n * (`e.detail === 0`), which is what lets it land focus on the selected app rather than the panel. It must\n * always run.\n *\n * `triggerOnClick` is the consumer's own click callback and runs alongside it. It does not suppress the\n * open: a consumer who needs to own the transition supplies `componentProps.isOpen`, which makes the\n * picker controlled and renders its internal flip inert.\n */\n const handleOnClickComposed = React.useCallback(\n (e: React.MouseEvent | React.KeyboardEvent) => {\n appPickerOnClick(e);\n triggerOnClick?.(e as React.MouseEvent<HTMLButtonElement>);\n },\n [appPickerOnClick, triggerOnClick],\n );\n\n return (\n <StyledButton\n id={id}\n onClick={handleOnClickComposed}\n onKeyDown={appPickerOnKeyDown}\n innerRef={handleTriggerRefs}\n aria-label={label}\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_BUTTON}\n aria-haspopup={ariaHasPopup}\n // No `aria-expanded`, matching DSAppPicker's own trigger. This one opens a `role=\"dialog\"`, and in\n // the dialog pattern the open state is conveyed by the dialog's presence, not by an attribute on the\n // control. The sibling toolbar items DO carry it correctly \u2014 `ds-popup-menu` opens a `role=\"menu\"`\n // and `ds-search-toggle` expands an inline region, which are the patterns the attribute belongs to.\n // Item-level global attributes land here, AFTER the handlers above, so an `onKeyDown` or `onClick`\n // set directly on the toolbar entry replaces the one this trigger wired. That is the documented\n // item-level override and `WithControlledAppPicker` relies on it \u2014 but note what an `onKeyDown`\n // override costs now: it takes over `openAndFocusOnArrowKeys`, so the arrow keys stop opening the\n // picker unless the consumer opens it themselves.\n //\n // `id` is the one global attribute that cannot reach this spread: useAppPickerCTX reads it out by\n // name and AppPickerRenderer hands it to DSAppPicker, which owns every id in this widget and derives\n // the `id` above from it. Left in here it would take that key back and strand the dialog's\n // `aria-labelledby` \u2014 PUI-18985.\n {...getGlobalAttributes(otherProps)}\n // The part-level xstyled layer, which the contract advertises \u2014 this is the element that serves it.\n {...getXstyledProps(otherProps)}\n type=\"button\"\n // Exposes the dsGlobalheaderMenubarItemButton slot on this trigger. Drop either prop and the slot\n // goes silently inert \u2014 getPartProps returns {} without the lookup table and generates no\n // data-dimsum-slot.\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n // Explicit and empty: no render-time values worth handing to a function-form slot prop. Stated so\n // \"what arguments does this slot get?\" always has a visible answer at the call site.\n getOwnerPropsArguments={() => ({})}\n >\n <MenuPicker width={20.73} height={20.73} />\n </StyledButton>\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACoGjB;AAnGN,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB,uBAAuB;AACrD,SAAS,iBAAiB;AAC1B,OAAOA,YAAW;AAClB,SAAS,iCAAiC;AAC1C,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAetB,MAAM,0BAA0B,CAAC;AAAA,EACtC;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,WAAW;AAAA,EACX,iBAAiB;AACnB,MAAuD;AACrD,QAAM,EAAE,gBAAgB,QAAQ,YAAY,OAAO,YAAY,8CAA8C,IAC3GA,OAAM,WAAW,YAAY;AAU/B,QAAM,oBAAoBA,OAAM;AAAA,IAC9B,CAAC,cAAiC;AAChC,aAAO,SAAS;AAChB,gBAAU,YAAY,QAAQ,EAAE,SAAS;AAAA,IAC3C;AAAA,IACA,CAAC,QAAQ,YAAY,QAAQ;AAAA,EAC/B;AAWA,QAAM,wBAAwBA,OAAM;AAAA,IAClC,CAAC,MAA8C;AAC7C,uBAAiB,CAAC;AAClB,uBAAiB,CAAwC;AAAA,IAC3D;AAAA,IACA,CAAC,kBAAkB,cAAc;AAAA,EACnC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,SAAS;AAAA,MACT,WAAW;AAAA,MACX,UAAU;AAAA,MACV,cAAY;AAAA,MACZ,eAAa,0BAA0B;AAAA,MACvC,iBAAe;AAAA,MAed,GAAG,oBAAoB,UAAU;AAAA,MAEjC,GAAG,gBAAgB,UAAU;AAAA,MAC9B,MAAK;AAAA,MAIL,eAAe;AAAA,MAGf,wBAAwB,OAAO,CAAC;AAAA,MAEhC,8BAAC,cAAW,OAAO,OAAO,QAAQ,OAAO;AAAA;AAAA,EAC3C;AAEJ;",
6
+ "names": ["React"]
7
+ }
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ import { PropTypes, globalAttributesPropTypes, xstyledPropTypes } from "@elliemae/ds-props-helpers";
3
+ const AppPickerPropTypes = {
4
+ ...globalAttributesPropTypes,
5
+ ...xstyledPropTypes,
6
+ label: PropTypes.string.description("Accessible name for the trigger button, and the toolbar label").isRequired,
7
+ componentProps: PropTypes.object.description(
8
+ "The consumer-authored DSAppPicker configuration; forwarded per DSAppPicker own contract via getDSAppPickerContractProps"
9
+ ).isRequired,
10
+ getOwnerPropsAwareOfPropsPassedToGlobalHeader: PropTypes.func.description(
11
+ "Returns the props passed to DSGlobalHeader, so getPartProps can look up this slot consumer-supplied props. Must come from DSGlobalHeader; the function-form hydrator is supplied per slot render site instead"
12
+ ).signature("(() => Partial<DSGlobalHeaderT.DefaultProps> )").isRequired,
13
+ setRef: PropTypes.func.description("Registers the trigger node with the toolbar focus management for arrow-key navigation").signature("(( ref: HTMLElement ) => void )").isRequired
14
+ };
15
+ const AppPickerPropTypesSchema = AppPickerPropTypes;
16
+ export {
17
+ AppPickerPropTypes,
18
+ AppPickerPropTypesSchema
19
+ };
20
+ //# sourceMappingURL=react-desc-prop-types.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../scripts/build/transpile/react-shim.js", "../../../../../../src/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.ts"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import type { DSPropTypesSchema, GlobalAttributesT, ValidationMap, XstyledProps } from '@elliemae/ds-props-helpers';\nimport { PropTypes, globalAttributesPropTypes, xstyledPropTypes } from '@elliemae/ds-props-helpers';\nimport type { DSGlobalHeaderT } from '../../../../react-desc-prop-types.js';\n\n/*\n * Relocated here from DSGlobalHeaderT.AppPickerProps, per the convention every other part in the repo\n * follows. Consumed by useAppPickerCTX / AppPickerCTXRenderer.\n *\n * This namespace describes what DSGlobalHeader passes DOWN to its own out-of-the-box App Picker\n * wrapper. It is NOT the shape an application developer authors \u2014 that is\n * DSGlobalHeaderT.ToolbarAppPickerItem (the toolbar config entry) and, inside it,\n * DSGlobalHeaderT.AppPickerComponentProps. The wrapper is an opinionated pre-configuration that\n * offloads work from the app developer onto Dimsum, so it generates props the developer never sees\n * (`setRef`, `getOwnerPropsAwareOfPropsPassedToGlobalHeader`) and is not meant to know about unless they\n * drop to atomic composition and render DSAppPicker themselves.\n *\n * The three IoC layers an out-of-the-box item is meant to expose are all present here:\n * 1. item-level global attributes, forwarded onto the rendered trigger \u2014 except `id`, which\n * useAppPickerCTX reads out by name and AppPickerRenderer hands to DSAppPicker, because that is\n * the component that owns every id this widget renders (PUI-18985)\n * 2. the slot layer, via `getOwnerPropsAwareOfPropsPassedToGlobalHeader` (parent-owned slots \u2014 see the\n * no-slots note below)\n * 3. `componentProps`, the wrapped component's own contract\n *\n * No slots of its own: every styled element this part renders is declared under the PARENT's name and\n * GLOBAL_HEADER_SLOTS, and those slot values are a published data-dimsum-slot / data-testid surface \u2014\n * re-declaring them here would change them, which the QA stability rule forbids. So, as with\n * ds-data-table-filters' FilterPopover, this file carries no PropsForGlobalOnSlots and no\n * getPropsPerSlotPropTypes. Consumers reach these slots through DSGlobalHeader, where they already do.\n *\n * KNOWN GAP (shared by all four out-of-the-box parts, no decision pending on this file) \u2014 `XstyledProps`\n * is declared below and `xstyledPropTypes` is spread into the schema, but no part forwards xstyled props\n * to any element. Global attributes ARE forwarded, via getGlobalAttributes in TriggerDefaultComponent.\n * The declaration comes from the part-generator template and the FilterPopover precedent; making it true\n * needs a styled target per part, which PopupMenu's bare-<div> root does not currently have.\n */\nexport declare namespace AppPickerT {\n export interface RequiredProps {\n /** Accessible name for the trigger, and the toolbar item's label. */\n label: string;\n /** The consumer-authored configuration object. Forwarded to DSAppPicker by its own contract. */\n componentProps: DSGlobalHeaderT.AppPickerComponentProps;\n /*\n * The slot IoC layer, and the ONLY half of it that may be drilled down.\n *\n * `getPartProps` uses this as the lookup table: it indexes the returned object by the styled\n * element's `data-dimsum-slot` (falling back to `data-testid`) to find the consumer's slot prop.\n * That table can therefore only come from DSGlobalHeader, because only DSGlobalHeader holds the\n * props the consumer passed \u2014 hence the deliberately verbose name. It is also what gates slot\n * generation at all: `styledFunction` sets `didDefinedGetOwnerProps: !!getOwnerProps`, and\n * `getPartProps` short-circuits to `{}` without it.\n *\n * Its former companion `getOwnerPropsArguments` is deliberately NOT here. That one is the hydrator\n * for function-form slot props \u2014 `getPartProps` calls `elementProps(getOwnerPropsArguments())` and\n * uses it for nothing else \u2014 so it must be defined by whichever element is rendering the slot,\n * which is the only place that knows the render-time values worth passing. Bundling the two forced\n * every slot in the package to share one hydrator; see ds-chat-bubble's ChatBubbleArrow and\n * ds-fast-list's List for what per-site hydration is actually for.\n */\n getOwnerPropsAwareOfPropsPassedToGlobalHeader: () => Partial<DSGlobalHeaderT.DefaultProps>;\n /** Focus-management registration, supplied by useGlobalHeaderToolbar for arrow-key navigation. */\n setRef: (ref: HTMLElement) => void;\n }\n\n /*\n * Intentionally empty, and intentionally still declared: `never` is a statement, not an oversight \u2014\n * \"this part has no default props, do not expect them\". Keeping the member present preserves\n * at-a-glance parity with every other part's namespace and makes adding a default a one-line change.\n */\n export interface DefaultProps {}\n\n export interface OptionalProps {}\n\n export interface Props\n extends\n Partial<DefaultProps>,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLButtonElement>,\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n keyof RequiredProps | keyof DefaultProps | keyof XstyledProps\n >,\n XstyledProps,\n RequiredProps {}\n\n export interface InternalProps\n extends\n DefaultProps,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLButtonElement>,\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n keyof RequiredProps | keyof DefaultProps | keyof XstyledProps\n >,\n XstyledProps,\n RequiredProps {}\n}\n\nexport const AppPickerPropTypes: DSPropTypesSchema<AppPickerT.Props> = {\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n label: PropTypes.string.description('Accessible name for the trigger button, and the toolbar label').isRequired,\n componentProps: PropTypes.object.description(\n 'The consumer-authored DSAppPicker configuration; forwarded per DSAppPicker own contract via getDSAppPickerContractProps',\n ).isRequired,\n getOwnerPropsAwareOfPropsPassedToGlobalHeader: PropTypes.func\n .description(\n 'Returns the props passed to DSGlobalHeader, so getPartProps can look up this slot consumer-supplied props. Must come from DSGlobalHeader; the function-form hydrator is supplied per slot render site instead',\n )\n .signature('(() => Partial<DSGlobalHeaderT.DefaultProps> )').isRequired,\n setRef: PropTypes.func\n .description('Registers the trigger node with the toolbar focus management for arrow-key navigation')\n .signature('(( ref: HTMLElement ) => void )').isRequired,\n};\n\nexport const AppPickerPropTypesSchema = AppPickerPropTypes as unknown as ValidationMap<AppPickerT.Props>;\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACCvB,SAAS,WAAW,2BAA2B,wBAAwB;AAiGhE,MAAM,qBAA0D;AAAA,EACrE,GAAG;AAAA,EACH,GAAG;AAAA,EACH,OAAO,UAAU,OAAO,YAAY,+DAA+D,EAAE;AAAA,EACrG,gBAAgB,UAAU,OAAO;AAAA,IAC/B;AAAA,EACF,EAAE;AAAA,EACF,+CAA+C,UAAU,KACtD;AAAA,IACC;AAAA,EACF,EACC,UAAU,gDAAgD,EAAE;AAAA,EAC/D,QAAQ,UAAU,KACf,YAAY,uFAAuF,EACnG,UAAU,iCAAiC,EAAE;AAClD;AAEO,MAAM,2BAA2B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,36 @@
1
+ import * as React from "react";
2
+ import { getDSAppPickerContractProps } from "@elliemae/ds-app-picker";
3
+ import React2 from "react";
4
+ const useAppPickerCTX = (config) => {
5
+ const { label, componentProps, getOwnerPropsAwareOfPropsPassedToGlobalHeader, setRef, id, ...otherProps } = config;
6
+ const { triggerRef, triggerOnClick } = componentProps;
7
+ const contractProps = React2.useMemo(() => getDSAppPickerContractProps(componentProps), [componentProps]);
8
+ return React2.useMemo(
9
+ () => ({
10
+ id,
11
+ label,
12
+ componentProps,
13
+ otherProps,
14
+ getOwnerPropsAwareOfPropsPassedToGlobalHeader,
15
+ setRef,
16
+ contractProps,
17
+ triggerRef,
18
+ triggerOnClick
19
+ }),
20
+ [
21
+ id,
22
+ label,
23
+ componentProps,
24
+ otherProps,
25
+ getOwnerPropsAwareOfPropsPassedToGlobalHeader,
26
+ setRef,
27
+ contractProps,
28
+ triggerRef,
29
+ triggerOnClick
30
+ ]
31
+ );
32
+ };
33
+ export {
34
+ useAppPickerCTX
35
+ };
36
+ //# sourceMappingURL=useAppPickerCTX.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../../../scripts/build/transpile/react-shim.js", "../../../../../../src/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.tsx"],
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { getDSAppPickerContractProps } from '@elliemae/ds-app-picker';\nimport React from 'react';\nimport type { AppPickerT } from './react-desc-prop-types.js';\n\n/*\n * This part owns NO open/close state, and that is deliberate.\n *\n * DSAppPicker owns the whole flow: its trigger click toggles the panel, `openAndFocusOnArrowKeys` gives\n * it ArrowDown/ArrowUp, a scoped Escape closes it and returns focus to the trigger, and a click outside\n * closes it. Lifting `isOpen` into this part would make the picker CONTROLLED, which switches every one\n * of those off \u2014 they would then have to be reimplemented here, against a component that already has\n * them and is tested for them.\n *\n * Two knock-on effects, worth knowing before adding state back:\n * - there is no `aria-expanded` on this item's trigger, so no open state is needed to feed one. The\n * picker opens a `role=\"dialog\"`, and that pattern conveys open state by the dialog's presence. The\n * sibling items keep the attribute because a menu and a disclosure region are what it is for.\n * - supplying `onKeyDown` to DSAppPicker sets `closeOnEscape: !onKeyDown`, i.e. it switches OFF the\n * picker's Escape routing AND its focus return. That is why this part supplies none, and why it needs\n * no focus tracker of its own.\n *\n * A consumer can still drive it: `componentProps.isOpen` reaches DSAppPicker through the contract\n * passthrough and makes it controlled for them, which is the supported way to own the transition.\n */\nexport const useAppPickerCTX = (config: AppPickerT.Props) => {\n /*\n * Read by name: only what this part needs for its own behaviour. `otherProps` is the item-level global\n * attributes, which reach the trigger via getGlobalAttributes. Everything a consumer put in\n * `componentProps` reaches DSAppPicker through `contractProps` instead \u2014 do not cherry-pick from\n * componentProps here, that is what the contract filter is for.\n *\n * `id` is read out by name so it does NOT stay in `otherProps` (PUI-18985). It is a member of\n * GlobalAttributesT, so left in there it would be spread onto the trigger and take the key back from\n * DSAppPicker \u2014 which owns every id this widget puts in the DOM and derives them all from this one\n * value. Naming the App Picker is what the item-level `id` means here; the trigger's own id is\n * `getIdForAppPickerTrigger(id)`, exported by ds-app-picker for exactly this reason.\n */\n const { label, componentProps, getOwnerPropsAwareOfPropsPassedToGlobalHeader, setRef, id, ...otherProps } = config;\n const { triggerRef, triggerOnClick } = componentProps;\n\n // `componentProps` is declared as DSAppPicker's own props plus this part's `triggerOnClick`, so every\n // DSAppPicker prop a consumer puts there is part of the contract \u2014 including all nine slot props.\n // Deriving the forwardable set from DSAppPicker's own contract is what keeps the two from drifting, and\n // it strips the one key in that object that belongs to this part rather than to DSAppPicker:\n // `triggerOnClick`. (`setRef` is a sibling field of `componentProps`, not inside it, so it never\n // reaches the filter.)\n const contractProps = React.useMemo(() => getDSAppPickerContractProps(componentProps), [componentProps]);\n\n return React.useMemo(\n () => ({\n id,\n label,\n componentProps,\n otherProps,\n getOwnerPropsAwareOfPropsPassedToGlobalHeader,\n setRef,\n contractProps,\n triggerRef,\n triggerOnClick,\n }),\n [\n id,\n label,\n componentProps,\n otherProps,\n getOwnerPropsAwareOfPropsPassedToGlobalHeader,\n setRef,\n contractProps,\n triggerRef,\n triggerOnClick,\n ],\n );\n};\n"],
5
+ "mappings": "AAAA,YAAY,WAAW;ACAvB,SAAS,mCAAmC;AAC5C,OAAOA,YAAW;AAuBX,MAAM,kBAAkB,CAAC,WAA6B;AAa3D,QAAM,EAAE,OAAO,gBAAgB,+CAA+C,QAAQ,IAAI,GAAG,WAAW,IAAI;AAC5G,QAAM,EAAE,YAAY,eAAe,IAAI;AAQvC,QAAM,gBAAgBA,OAAM,QAAQ,MAAM,4BAA4B,cAAc,GAAG,CAAC,cAAc,CAAC;AAEvG,SAAOA,OAAM;AAAA,IACX,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": ["React"]
7
+ }
@@ -1,53 +1,101 @@
1
1
  import * as React from "react";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useFloatingContext, PopoverArrow, FloatingWrapper } from "@elliemae/ds-floating-context";
4
- import { useGetGlobalAttributes } from "@elliemae/ds-props-helpers";
4
+ import { useGetGlobalAttributes, useGetXstyledProps } from "@elliemae/ds-props-helpers";
5
5
  import { useCallback, useRef } from "react";
6
6
  import { GLOBAL_HEADER_DATA_TESTID } from "../../../../constants/index.js";
7
7
  import { StyledButton } from "../../../styles.js";
8
+ import { StyledPopupMenuContainer } from "../../styles.js";
8
9
  import { PopupMenuContent } from "./menuContent/PopupMenuContent.js";
9
- import { useOnClickOutside } from "../../../../hooks/useOnClickOutside.js";
10
10
  const PopupMenu = ({
11
11
  Icon,
12
12
  onClick,
13
13
  setRef,
14
14
  componentProps,
15
- ownerProps,
15
+ getOwnerPropsAwareOfPropsPassedToGlobalHeader,
16
16
  ...otherProps
17
17
  }) => {
18
- const { arrowStyles, floatingStyles, isOpen, refs, context, showTooltip, hideTooltip } = useFloatingContext({
19
- externallyControlledIsOpen: componentProps.isOpen,
20
- placement: "bottom",
21
- withoutAnimation: true,
22
- withoutPortal: true
23
- });
24
18
  const {
25
19
  onClickOutside = () => null,
26
20
  onKeyPress,
27
21
  popupOnKeyPress,
28
22
  isOpen: userIsOpen,
29
23
  options,
30
- closeOnClick
24
+ closeOnClick,
25
+ onOpen,
26
+ onClose
31
27
  } = componentProps;
32
- const boundaryRef = useRef(null);
28
+ const { arrowStyles, floatingStyles, isOpen, refs, context, showTooltip, hideTooltip } = useFloatingContext({
29
+ externallyControlledIsOpen: componentProps.isOpen,
30
+ placement: "bottom",
31
+ withoutAnimation: true,
32
+ withoutPortal: true,
33
+ // The hook auto-excludes clicks inside the floating element and the reference, so the
34
+ // outside boundary is now { reference, floating } — no boundary <div> needed.
35
+ // Gated internally on `isOpen`, so it only fires while open.
36
+ onClickOutside: (event) => {
37
+ onClickOutside(event);
38
+ if (userIsOpen === void 0) hideTooltip();
39
+ },
40
+ /*
41
+ * Passive notification, straight through from the floating context. Handed over rather than
42
+ * reimplemented because the hook is the only place that sees every transition: the trigger click and
43
+ * ArrowDown both go through `showTooltip`, and click-outside, Escape inside the menu and a
44
+ * closeOnClick item all go through `hideTooltip` — plus a controlled flip of `isOpen`, which no
45
+ * handler in this file observes at all.
46
+ *
47
+ * Notifying does NOT make the consumer responsible for the transition: this stays uncontrolled unless
48
+ * they also supply `isOpen`.
49
+ *
50
+ * The scoped-Escape caveat in the hook's docs does not apply here. A scoped Escape would route to
51
+ * `onEscape` instead of `onClose`, but that path needs `closeOnEscape`, which defaults to false and is
52
+ * not passed — Escape is handled inside PopupMenuContent and closes via `hideTooltip`, so it surfaces
53
+ * as a normal 'interaction' close. Passing `closeOnEscape` here later would silently punch a hole in
54
+ * `onClose` unless `onEscape` is wired at the same time.
55
+ */
56
+ /*
57
+ * Escape is the floating context's, not this part's. `closeOnEscape` closes the menu and
58
+ * `returnFocusToReference` puts focus back on the trigger — both were hand-rolled here before, in
59
+ * PopupMenuContent's per-item keydown and in a manual `.focus()`.
60
+ *
61
+ * Gated on being UNCONTROLLED, and that gate is load-bearing rather than tidy: the hook applies
62
+ * `returnFocusToReference` on a scoped Escape whichever side owns the open state. For a controlled
63
+ * consumer the close below is inert, so leaving it on would move focus to the trigger while their
64
+ * menu is still open — focus outside an open menu. A controlled consumer owns the close, so they own
65
+ * the Escape and the refocus with it.
66
+ */
67
+ closeOnEscape: userIsOpen === void 0,
68
+ returnFocusToReference: true,
69
+ /*
70
+ * A scoped Escape routes HERE and not to `onClose`, so the consumer's close notification has to be
71
+ * re-emitted or it silently stops reporting the most common keyboard close.
72
+ */
73
+ onEscape: (event) => {
74
+ hideTooltip();
75
+ onClose?.({ reason: "interaction", event, isControlled: userIsOpen !== void 0 });
76
+ },
77
+ onOpen,
78
+ onClose
79
+ });
80
+ const openIntentRef = useRef("first");
33
81
  const handleOnKeyDown = useCallback(
34
82
  (e) => {
35
- if (e.code === "ArrowDown") {
36
- showTooltip();
83
+ if (e.code === "ArrowDown" || e.code === "ArrowUp") {
84
+ e.preventDefault();
85
+ openIntentRef.current = e.code === "ArrowUp" ? "last" : "first";
86
+ if (userIsOpen === void 0) showTooltip();
37
87
  }
38
88
  if (onKeyPress) onKeyPress(e);
39
89
  },
40
- [onKeyPress, showTooltip]
90
+ [onKeyPress, showTooltip, userIsOpen]
41
91
  );
42
92
  const handleOnClose = useCallback(() => {
43
- if (userIsOpen === void 0) {
44
- hideTooltip();
45
- }
46
- refs.reference?.focus();
47
- }, [hideTooltip, refs.reference, userIsOpen]);
93
+ if (userIsOpen === void 0) hideTooltip();
94
+ }, [hideTooltip, userIsOpen]);
48
95
  const handleTriggerOnClick = useCallback(
49
96
  (e) => {
50
- if (userIsOpen === void 0) showTooltip();
97
+ openIntentRef.current = "first";
98
+ if (userIsOpen === void 0) showTooltip(e);
51
99
  if (onClick) onClick(e);
52
100
  },
53
101
  [onClick, userIsOpen, showTooltip]
@@ -55,18 +103,6 @@ const PopupMenu = ({
55
103
  const handleItemClick = useCallback(() => {
56
104
  if (closeOnClick && userIsOpen === void 0) handleOnClose();
57
105
  }, [closeOnClick, handleOnClose, userIsOpen]);
58
- const handleOutside = useCallback(
59
- (event) => {
60
- onClickOutside(event);
61
- const actuallyOpen = userIsOpen ?? isOpen;
62
- if (!actuallyOpen) return;
63
- if (userIsOpen === void 0) {
64
- handleOnClose();
65
- }
66
- },
67
- [handleOnClose, isOpen, onClickOutside, userIsOpen]
68
- );
69
- useOnClickOutside(userIsOpen ?? isOpen ? boundaryRef.current : null, handleOutside);
70
106
  const handleRefs = useCallback(
71
107
  (ref) => {
72
108
  setRef(ref);
@@ -74,46 +110,57 @@ const PopupMenu = ({
74
110
  },
75
111
  [refs, setRef]
76
112
  );
77
- return /* @__PURE__ */ jsxs("div", { ref: boundaryRef, children: [
78
- /* @__PURE__ */ jsx(
79
- StyledButton,
80
- {
81
- onClick: handleTriggerOnClick,
82
- onKeyDown: handleOnKeyDown,
83
- innerRef: handleRefs,
84
- "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_BUTTON,
85
- "aria-haspopup": true,
86
- "aria-expanded": userIsOpen ?? isOpen,
87
- ...useGetGlobalAttributes(otherProps),
88
- type: "button",
89
- ...ownerProps,
90
- children: Icon && /* @__PURE__ */ jsx(Icon, { size: "m" })
91
- }
92
- ),
93
- refs.reference ? /* @__PURE__ */ jsxs(
94
- FloatingWrapper,
95
- {
96
- innerRef: refs.setFloating,
97
- isOpen: userIsOpen ?? isOpen,
98
- floatingStyles,
99
- context,
100
- children: [
101
- /* @__PURE__ */ jsx(
102
- PopupMenuContent,
103
- {
104
- options,
105
- onItemClick: handleItemClick,
106
- onClose: handleOnClose,
107
- setIsOpen: hideTooltip,
108
- popupOnKeyPress,
109
- ownerProps
110
- }
111
- ),
112
- /* @__PURE__ */ jsx(PopoverArrow, { ...arrowStyles })
113
- ]
114
- }
115
- ) : null
116
- ] });
113
+ const noSlotArguments = useCallback(() => ({}), []);
114
+ return /* @__PURE__ */ jsxs(
115
+ StyledPopupMenuContainer,
116
+ {
117
+ "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_POPUPMENU_CONTAINER,
118
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
119
+ getOwnerPropsArguments: noSlotArguments,
120
+ ...useGetXstyledProps(otherProps),
121
+ children: [
122
+ /* @__PURE__ */ jsx(
123
+ StyledButton,
124
+ {
125
+ onClick: handleTriggerOnClick,
126
+ onKeyDown: handleOnKeyDown,
127
+ innerRef: handleRefs,
128
+ "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_BUTTON,
129
+ "aria-haspopup": true,
130
+ "aria-expanded": userIsOpen ?? isOpen,
131
+ ...useGetGlobalAttributes(otherProps),
132
+ type: "button",
133
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
134
+ getOwnerPropsArguments: noSlotArguments,
135
+ children: Icon && /* @__PURE__ */ jsx(Icon, { size: "m" })
136
+ }
137
+ ),
138
+ refs.reference ? /* @__PURE__ */ jsxs(
139
+ FloatingWrapper,
140
+ {
141
+ innerRef: refs.setFloating,
142
+ isOpen: userIsOpen ?? isOpen,
143
+ floatingStyles,
144
+ context,
145
+ children: [
146
+ /* @__PURE__ */ jsx(
147
+ PopupMenuContent,
148
+ {
149
+ options,
150
+ onItemClick: handleItemClick,
151
+ openIntent: openIntentRef.current,
152
+ setIsOpen: hideTooltip,
153
+ popupOnKeyPress,
154
+ getOwnerPropsAwareOfPropsPassedToGlobalHeader
155
+ }
156
+ ),
157
+ /* @__PURE__ */ jsx(PopoverArrow, { ...arrowStyles })
158
+ ]
159
+ }
160
+ ) : null
161
+ ]
162
+ }
163
+ );
117
164
  };
118
165
  export {
119
166
  PopupMenu
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../../scripts/build/transpile/react-shim.js", "../../../../../../src/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.tsx"],
4
- "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useFloatingContext, PopoverArrow, FloatingWrapper } from '@elliemae/ds-floating-context';\nimport { useGetGlobalAttributes } from '@elliemae/ds-props-helpers';\nimport React, { useCallback, useRef } from 'react';\nimport { GLOBAL_HEADER_DATA_TESTID } from '../../../../constants/index.js';\nimport type { DSGlobalHeaderT } from '../../../../react-desc-prop-types.js';\nimport { StyledButton } from '../../../styles.js';\nimport { PopupMenuContent } from './menuContent/PopupMenuContent.js';\nimport { useOnClickOutside } from '../../../../hooks/useOnClickOutside.js';\nexport const PopupMenu = ({\n Icon,\n onClick,\n setRef,\n componentProps,\n ownerProps,\n ...otherProps\n}: DSGlobalHeaderT.PopupProps): JSX.Element => {\n const { arrowStyles, floatingStyles, isOpen, refs, context, showTooltip, hideTooltip } = useFloatingContext({\n externallyControlledIsOpen: componentProps.isOpen,\n placement: 'bottom',\n withoutAnimation: true,\n withoutPortal: true,\n });\n\n const {\n onClickOutside = () => null,\n onKeyPress,\n popupOnKeyPress,\n isOpen: userIsOpen,\n options,\n closeOnClick,\n } = componentProps;\n\n /**\n * We want \"outside\" to mean: outside BOTH the trigger and the floating panel.\n * So wrap them in a single DOM node and use that as the boundary.\n */\n const boundaryRef = useRef<HTMLDivElement | null>(null);\n\n const handleOnKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.code === 'ArrowDown') {\n showTooltip();\n }\n if (onKeyPress) onKeyPress(e);\n },\n [onKeyPress, showTooltip],\n );\n\n const handleOnClose = useCallback(() => {\n if (userIsOpen === undefined) {\n hideTooltip();\n }\n (refs.reference as HTMLElement)?.focus();\n }, [hideTooltip, refs.reference, userIsOpen]);\n\n const handleTriggerOnClick = useCallback(\n (e: React.MouseEvent) => {\n if (userIsOpen === undefined) showTooltip();\n if (onClick) onClick(e);\n },\n [onClick, userIsOpen, showTooltip],\n );\n\n const handleItemClick = useCallback(() => {\n if (closeOnClick && userIsOpen === undefined) handleOnClose();\n }, [closeOnClick, handleOnClose, userIsOpen]);\n\n // Close on outside click, but:\n // - always notify consumer via onClickOutside\n // - only actually close when uncontrolled (userIsOpen === undefined)\n // - only run while open\n const handleOutside = useCallback(\n (event: Event) => {\n onClickOutside(event as MouseEvent | TouchEvent);\n\n const actuallyOpen = userIsOpen ?? isOpen;\n if (!actuallyOpen) return;\n\n if (userIsOpen === undefined) {\n handleOnClose();\n }\n },\n [handleOnClose, isOpen, onClickOutside, userIsOpen],\n );\n\n // If you only want to listen when open, pass `null` when closed\n useOnClickOutside((userIsOpen ?? isOpen) ? boundaryRef.current : null, handleOutside);\n\n const handleRefs = useCallback(\n (ref: HTMLButtonElement) => {\n setRef(ref);\n refs.setReference(ref);\n },\n [refs, setRef],\n );\n return (\n <div ref={boundaryRef}>\n <StyledButton\n onClick={handleTriggerOnClick}\n onKeyDown={handleOnKeyDown}\n innerRef={handleRefs}\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_BUTTON}\n aria-haspopup\n aria-expanded={userIsOpen ?? isOpen}\n {...useGetGlobalAttributes(otherProps)}\n type=\"button\"\n {...ownerProps}\n >\n {Icon && <Icon size=\"m\" />}\n </StyledButton>\n\n {refs.reference ? (\n <FloatingWrapper\n innerRef={refs.setFloating}\n isOpen={userIsOpen ?? isOpen}\n floatingStyles={floatingStyles}\n context={context}\n >\n <PopupMenuContent\n options={options}\n onItemClick={handleItemClick}\n onClose={handleOnClose}\n setIsOpen={hideTooltip}\n popupOnKeyPress={popupOnKeyPress}\n ownerProps={ownerProps}\n />\n <PopoverArrow {...arrowStyles} />\n </FloatingWrapper>\n ) : null}\n </div>\n );\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import * as React from 'react';\nexport { React };\n", "import { useFloatingContext, PopoverArrow, FloatingWrapper } from '@elliemae/ds-floating-context';\nimport { useGetGlobalAttributes, useGetXstyledProps } from '@elliemae/ds-props-helpers';\nimport React, { useCallback, useRef } from 'react';\nimport { GLOBAL_HEADER_DATA_TESTID } from '../../../../constants/index.js';\nimport { StyledButton } from '../../../styles.js';\nimport { StyledPopupMenuContainer } from '../../styles.js';\nimport { PopupMenuContent } from './menuContent/PopupMenuContent.js';\nimport type { PopupMenuT } from './react-desc-prop-types.js';\n\nexport const PopupMenu = ({\n Icon,\n onClick,\n setRef,\n componentProps,\n getOwnerPropsAwareOfPropsPassedToGlobalHeader,\n ...otherProps\n}: PopupMenuT.Props): JSX.Element => {\n const {\n onClickOutside = () => null,\n onKeyPress,\n popupOnKeyPress,\n isOpen: userIsOpen,\n options,\n closeOnClick,\n onOpen,\n onClose,\n } = componentProps;\n\n // We need to declare the floating context before we can reference its hideTooltip in\n // handleOutside; but handleOutside is passed into the same hook call. We resolve this by\n // pulling hideTooltip / refs.reference via the latest-ref pattern of the hook itself \u2014\n // see comments on `onClickOutside` below.\n const { arrowStyles, floatingStyles, isOpen, refs, context, showTooltip, hideTooltip } = useFloatingContext({\n externallyControlledIsOpen: componentProps.isOpen,\n placement: 'bottom',\n withoutAnimation: true,\n withoutPortal: true,\n // The hook auto-excludes clicks inside the floating element and the reference, so the\n // outside boundary is now { reference, floating } \u2014 no boundary <div> needed.\n // Gated internally on `isOpen`, so it only fires while open.\n onClickOutside: (event) => {\n onClickOutside(event);\n // Closes but does NOT move focus. The user clicked somewhere else and the browser has already put\n // focus where they aimed; pulling it back to the trigger would undo that. Returning focus is a\n // scoped-Escape affordance only \u2014 the same line DSAppPicker and the floating context both draw.\n if (userIsOpen === undefined) hideTooltip();\n },\n /*\n * Passive notification, straight through from the floating context. Handed over rather than\n * reimplemented because the hook is the only place that sees every transition: the trigger click and\n * ArrowDown both go through `showTooltip`, and click-outside, Escape inside the menu and a\n * closeOnClick item all go through `hideTooltip` \u2014 plus a controlled flip of `isOpen`, which no\n * handler in this file observes at all.\n *\n * Notifying does NOT make the consumer responsible for the transition: this stays uncontrolled unless\n * they also supply `isOpen`.\n *\n * The scoped-Escape caveat in the hook's docs does not apply here. A scoped Escape would route to\n * `onEscape` instead of `onClose`, but that path needs `closeOnEscape`, which defaults to false and is\n * not passed \u2014 Escape is handled inside PopupMenuContent and closes via `hideTooltip`, so it surfaces\n * as a normal 'interaction' close. Passing `closeOnEscape` here later would silently punch a hole in\n * `onClose` unless `onEscape` is wired at the same time.\n */\n /*\n * Escape is the floating context's, not this part's. `closeOnEscape` closes the menu and\n * `returnFocusToReference` puts focus back on the trigger \u2014 both were hand-rolled here before, in\n * PopupMenuContent's per-item keydown and in a manual `.focus()`.\n *\n * Gated on being UNCONTROLLED, and that gate is load-bearing rather than tidy: the hook applies\n * `returnFocusToReference` on a scoped Escape whichever side owns the open state. For a controlled\n * consumer the close below is inert, so leaving it on would move focus to the trigger while their\n * menu is still open \u2014 focus outside an open menu. A controlled consumer owns the close, so they own\n * the Escape and the refocus with it.\n */\n closeOnEscape: userIsOpen === undefined,\n returnFocusToReference: true,\n /*\n * A scoped Escape routes HERE and not to `onClose`, so the consumer's close notification has to be\n * re-emitted or it silently stops reporting the most common keyboard close.\n */\n onEscape: (event) => {\n hideTooltip();\n onClose?.({ reason: 'interaction', event, isControlled: userIsOpen !== undefined });\n },\n onOpen,\n onClose,\n });\n\n /*\n * WHICH end of the menu the pending open lands on. Same mechanism as DSAppPicker's `openIntentRef`,\n * scoped to this part: the trigger is the only place that knows which key was pressed, and the seeding\n * happens later, in PopupMenuContent's ref callback. A ref rather than state because nothing renders\n * from it and it must not cause a render of its own between the key and the open.\n */\n const openIntentRef = useRef<'first' | 'last'>('first');\n\n /*\n * ArrowDown opens onto the first item, ArrowUp onto the last \u2014 the menubar convention, and the same\n * split DSAppPicker makes.\n *\n * Enter and Space are absent on purpose: this is a native <button>, so the browser turns them into a\n * click that arrives at handleTriggerOnClick. Handling them here too would open twice.\n *\n * `preventDefault` stops the page scrolling on a key being used to open a widget.\n */\n const handleOnKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.code === 'ArrowDown' || e.code === 'ArrowUp') {\n e.preventDefault();\n openIntentRef.current = e.code === 'ArrowUp' ? 'last' : 'first';\n if (userIsOpen === undefined) showTooltip();\n }\n if (onKeyPress) onKeyPress(e);\n },\n [onKeyPress, showTooltip, userIsOpen],\n );\n\n /*\n * Closes after an item click. No `.focus()` here: returning focus to the trigger is the floating\n * context's job on a scoped Escape, and an item click is not one \u2014 the clicked item is usually\n * navigating away, so yanking focus back to the trigger would fight the user.\n */\n const handleOnClose = useCallback(() => {\n if (userIsOpen === undefined) hideTooltip();\n }, [hideTooltip, userIsOpen]);\n\n const handleTriggerOnClick = useCallback(\n (e: React.MouseEvent) => {\n // Click, Enter and Space all land on the first item; only ArrowUp asks for the other end.\n openIntentRef.current = 'first';\n if (userIsOpen === undefined) showTooltip(e);\n if (onClick) onClick(e);\n },\n [onClick, userIsOpen, showTooltip],\n );\n\n const handleItemClick = useCallback(() => {\n if (closeOnClick && userIsOpen === undefined) handleOnClose();\n }, [closeOnClick, handleOnClose, userIsOpen]);\n\n const handleRefs = useCallback(\n (ref: HTMLButtonElement) => {\n setRef(ref);\n refs.setReference(ref);\n },\n [refs, setRef],\n );\n\n // Explicit and empty, shared by this part's slot render sites: `getOwnerPropsArguments` hydrates\n // function-form slot props and nothing else, and none of these elements have render-time values worth\n // passing. Stated rather than omitted so the answer is always visible at the call site.\n const noSlotArguments = useCallback(() => ({}), []);\n return (\n <StyledPopupMenuContainer\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_POPUPMENU_CONTAINER}\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n // Explicit and empty: this root has no render-time values to hand a function-form slot prop.\n getOwnerPropsArguments={noSlotArguments}\n // The part-level xstyled layer. This root is the only element in the part that can receive it, so it\n // must stay a styled component \u2014 a plain <div> here silently drops every xstyled prop the contract\n // advertises.\n {...useGetXstyledProps(otherProps)}\n >\n <StyledButton\n onClick={handleTriggerOnClick}\n onKeyDown={handleOnKeyDown}\n innerRef={handleRefs}\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_BUTTON}\n aria-haspopup\n aria-expanded={userIsOpen ?? isOpen}\n {...useGetGlobalAttributes(otherProps)}\n type=\"button\"\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n >\n {Icon && <Icon size=\"m\" />}\n </StyledButton>\n\n {refs.reference ? (\n <FloatingWrapper\n innerRef={refs.setFloating}\n isOpen={userIsOpen ?? isOpen}\n floatingStyles={floatingStyles}\n context={context}\n >\n <PopupMenuContent\n options={options}\n onItemClick={handleItemClick}\n openIntent={openIntentRef.current}\n setIsOpen={hideTooltip}\n popupOnKeyPress={popupOnKeyPress}\n getOwnerPropsAwareOfPropsPassedToGlobalHeader={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n />\n <PopoverArrow {...arrowStyles} />\n </FloatingWrapper>\n ) : null}\n </StyledPopupMenuContainer>\n );\n};\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { getGlobalAttributes } from "@elliemae/ds-props-helpers";
3
+ import { getGlobalAttributes, getXstyledProps } from "@elliemae/ds-props-helpers";
4
4
  import React2, { useContext } from "react";
5
5
  import { DSGlobalHeaderContext } from "../../../../../DSGlobalHeaderContext.js";
6
6
  import { GLOBAL_HEADER_DATA_TESTID } from "../../../../../constants/index.js";
@@ -10,20 +10,31 @@ const PopupMenuContent = React2.memo(
10
10
  ({
11
11
  options,
12
12
  onItemClick,
13
- onClose,
13
+ openIntent,
14
14
  popupOnKeyPress,
15
15
  setIsOpen,
16
- ownerProps
16
+ getOwnerPropsAwareOfPropsPassedToGlobalHeader,
17
+ // The part-level global attribute + xstyled layers, forwarded onto the list root below.
18
+ ...restGlobalAndXstyled
17
19
  }) => {
18
20
  const { instanceUID } = useContext(DSGlobalHeaderContext);
19
- const { menuRef, setRef, keyboardNavigation } = usePopupMenuContent({ setIsOpen });
21
+ const focusableItemsCount = options.filter((option) => option.type !== "separator").length;
22
+ const { menuRef, setRef, keyboardNavigation } = usePopupMenuContent({
23
+ setIsOpen,
24
+ openIntent,
25
+ focusableItemsCount
26
+ });
27
+ const noSlotArguments = () => ({});
20
28
  return /* @__PURE__ */ jsx(
21
29
  StyledList,
22
30
  {
23
31
  innerRef: menuRef,
24
32
  role: "menu",
25
33
  "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_LIST,
26
- ...ownerProps,
34
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
35
+ getOwnerPropsArguments: noSlotArguments,
36
+ ...getGlobalAttributes(restGlobalAndXstyled),
37
+ ...getXstyledProps(restGlobalAndXstyled),
27
38
  children: options.map((option) => {
28
39
  const { type, Icon, label = "", onClick, Content, ...rest } = option;
29
40
  const globalAttrs = getGlobalAttributes(rest);
@@ -33,7 +44,6 @@ const PopupMenuContent = React2.memo(
33
44
  };
34
45
  const handleKeyDown = (e) => {
35
46
  keyboardNavigation(e);
36
- if (e.code === "Escape") onClose();
37
47
  if (popupOnKeyPress) popupOnKeyPress(e);
38
48
  };
39
49
  switch (type) {
@@ -44,7 +54,8 @@ const PopupMenuContent = React2.memo(
44
54
  role: "none",
45
55
  "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_SEPARATOR,
46
56
  ...globalAttrs,
47
- ...ownerProps
57
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
58
+ getOwnerPropsArguments: noSlotArguments
48
59
  },
49
60
  `${instanceUID}-separator-${label}`
50
61
  );
@@ -54,7 +65,8 @@ const PopupMenuContent = React2.memo(
54
65
  {
55
66
  role: "menuitem",
56
67
  "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM,
57
- ...ownerProps,
68
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
69
+ getOwnerPropsArguments: noSlotArguments,
58
70
  children: /* @__PURE__ */ jsx(
59
71
  StyledItemButton,
60
72
  {
@@ -64,7 +76,8 @@ const PopupMenuContent = React2.memo(
64
76
  "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON,
65
77
  ...globalAttrs,
66
78
  type: "button",
67
- ...ownerProps,
79
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
80
+ getOwnerPropsArguments: noSlotArguments,
68
81
  children: Content && /* @__PURE__ */ jsx(Content, {})
69
82
  }
70
83
  )
@@ -77,7 +90,8 @@ const PopupMenuContent = React2.memo(
77
90
  {
78
91
  role: "menuitem",
79
92
  "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM,
80
- ...ownerProps,
93
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
94
+ getOwnerPropsArguments: noSlotArguments,
81
95
  children: /* @__PURE__ */ jsxs(
82
96
  StyledItemButton,
83
97
  {
@@ -87,14 +101,16 @@ const PopupMenuContent = React2.memo(
87
101
  "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON,
88
102
  ...globalAttrs,
89
103
  type: "button",
90
- ...ownerProps,
104
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
105
+ getOwnerPropsArguments: noSlotArguments,
91
106
  children: [
92
107
  Icon && /* @__PURE__ */ jsx(Icon, {}),
93
108
  label && /* @__PURE__ */ jsx(
94
109
  StyledLabel,
95
110
  {
96
111
  "data-testid": GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON_LABEL,
97
- ...ownerProps,
112
+ getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
113
+ getOwnerPropsArguments: noSlotArguments,
98
114
  children: label
99
115
  }
100
116
  )