@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.
- package/dist/cjs/DSGlobalHeader.js +16 -2
- package/dist/cjs/DSGlobalHeader.js.map +2 -2
- package/dist/cjs/DSGlobalHeaderContext.js.map +2 -2
- package/dist/cjs/config/useGlobalHeader.js +13 -2
- package/dist/cjs/config/useGlobalHeader.js.map +2 -2
- package/dist/cjs/constants/index.js +11 -5
- package/dist/cjs/constants/index.js.map +2 -2
- package/dist/cjs/index.js +3 -6
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs/package.json +1 -4
- package/dist/cjs/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js +33 -1
- package/dist/cjs/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js.map +2 -2
- package/dist/cjs/parts/Logo/GlobalHeaderLogo.js +16 -2
- package/dist/cjs/parts/Logo/GlobalHeaderLogo.js.map +2 -2
- package/dist/cjs/parts/Toolbar/GlobalHeaderToolbar.js +54 -16
- package/dist/cjs/parts/Toolbar/GlobalHeaderToolbar.js.map +2 -2
- package/dist/cjs/{utils/useCallbackAfterRender.js → parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js} +7 -16
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js.map +7 -0
- package/dist/cjs/{hooks/useOnClickOutside.js → parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js} +13 -30
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js +53 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js +84 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js +50 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js +66 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js +118 -71
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js.map +3 -3
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js +27 -11
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js.map +2 -2
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js +52 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js +23 -15
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js.map +2 -2
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js +54 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js +28 -16
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js.map +2 -2
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js +61 -50
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js.map +2 -2
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js +58 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js.map +7 -0
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js +33 -25
- package/dist/cjs/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js.map +2 -2
- package/dist/cjs/parts/Toolbar/outOfTheBox/index.js +12 -4
- package/dist/cjs/parts/Toolbar/outOfTheBox/index.js.map +2 -2
- package/dist/cjs/parts/Toolbar/styles.js +6 -1
- package/dist/cjs/parts/Toolbar/styles.js.map +2 -2
- package/dist/cjs/react-desc-prop-types.js.map +2 -2
- package/dist/cjs/sharedTypes.js.map +1 -1
- package/dist/cjs/typescript-testing/typescript-global-header-toolbar-types.js +52 -0
- package/dist/cjs/typescript-testing/typescript-global-header-toolbar-types.js.map +2 -2
- package/dist/esm/DSGlobalHeader.js +16 -2
- package/dist/esm/DSGlobalHeader.js.map +2 -2
- package/dist/esm/DSGlobalHeaderContext.js.map +2 -2
- package/dist/esm/config/useGlobalHeader.js +13 -2
- package/dist/esm/config/useGlobalHeader.js.map +2 -2
- package/dist/esm/constants/index.js +11 -5
- package/dist/esm/constants/index.js.map +2 -2
- package/dist/esm/index.js +3 -6
- package/dist/esm/index.js.map +3 -3
- package/dist/esm/package.json +1 -4
- package/dist/esm/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js +34 -2
- package/dist/esm/parts/Breadcrumb/useGlobalHeaderBreadcrumb.js.map +2 -2
- package/dist/esm/parts/Logo/GlobalHeaderLogo.js +16 -2
- package/dist/esm/parts/Logo/GlobalHeaderLogo.js.map +2 -2
- package/dist/esm/parts/Toolbar/GlobalHeaderToolbar.js +55 -17
- package/dist/esm/parts/Toolbar/GlobalHeaderToolbar.js.map +2 -2
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js +8 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js +13 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js +23 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js +54 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js +20 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js +36 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js +119 -72
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.js.map +2 -2
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js +28 -12
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.js.map +2 -2
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js +22 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js +24 -16
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.js.map +2 -2
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js +24 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js +34 -17
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.js.map +2 -2
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js +61 -50
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.js.map +2 -2
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js +28 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.js.map +7 -0
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js +33 -25
- package/dist/esm/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.js.map +2 -2
- package/dist/esm/parts/Toolbar/outOfTheBox/index.js +8 -3
- package/dist/esm/parts/Toolbar/outOfTheBox/index.js.map +2 -2
- package/dist/esm/parts/Toolbar/styles.js +6 -1
- package/dist/esm/parts/Toolbar/styles.js.map +2 -2
- package/dist/esm/react-desc-prop-types.js.map +2 -2
- package/dist/esm/typescript-testing/typescript-global-header-toolbar-types.js +52 -0
- package/dist/esm/typescript-testing/typescript-global-header-toolbar-types.js.map +2 -2
- package/dist/types/DSGlobalHeaderContext.d.ts +10 -2
- package/dist/types/config/useGlobalHeader.d.ts +3 -4
- package/dist/types/constants/index.d.ts +4 -3
- package/dist/types/index.d.ts +0 -2
- package/dist/types/parts/Breadcrumb/PureBreadcrumb.d.ts +1 -1
- package/dist/types/parts/Breadcrumb/styles.d.ts +1 -1
- package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTX.d.ts +4 -0
- package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPickerCTXRenderer.d.ts +2 -0
- package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPickerRenderer.d.ts +1 -0
- package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/TriggerDefaultComponent.d.ts +2 -0
- package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/react-desc-prop-types.d.ts +23 -0
- package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/useAppPickerCTX.d.ts +456 -0
- package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.d.ts +2 -2
- package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.d.ts +2 -2
- package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.d.ts +28 -0
- package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.d.ts +9 -1
- package/dist/types/parts/Toolbar/outOfTheBox/PopupMenu/react-desc-prop-types.d.ts +26 -0
- package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggle.d.ts +2 -2
- package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/SearchToggleSpinButton.d.ts +3 -1
- package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/react-desc-prop-types.d.ts +26 -0
- package/dist/types/parts/Toolbar/outOfTheBox/SearchToggle/useSearchToggle.d.ts +2 -3
- package/dist/types/parts/Toolbar/outOfTheBox/index.d.ts +3 -3
- package/dist/types/parts/Toolbar/styles.d.ts +1 -0
- package/dist/types/react-desc-prop-types.d.ts +63 -72
- package/dist/types/sharedTypes.d.ts +16 -6
- package/package.json +20 -17
- package/dist/cjs/hooks/useOnClickOutside.js.map +0 -7
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js +0 -127
- package/dist/cjs/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js.map +0 -7
- package/dist/cjs/utils/useCallbackAfterRender.js.map +0 -7
- package/dist/esm/hooks/useOnClickOutside.js +0 -30
- package/dist/esm/hooks/useOnClickOutside.js.map +0 -7
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js +0 -97
- package/dist/esm/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.js.map +0 -7
- package/dist/esm/utils/useCallbackAfterRender.js +0 -17
- package/dist/esm/utils/useCallbackAfterRender.js.map +0 -7
- package/dist/types/hooks/useOnClickOutside.d.ts +0 -1
- package/dist/types/parts/Toolbar/outOfTheBox/AppPicker/AppPicker.d.ts +0 -6
- package/dist/types/tests/GlobalHeader.a11y.test.d.ts +0 -1
- package/dist/types/tests/GlobalHeader.callback.test.d.ts +0 -1
- package/dist/types/tests/GlobalHeader.getOwnerProps.test.d.ts +0 -1
- package/dist/types/tests/GlobalHeader.keyboard.test.d.ts +0 -1
- package/dist/types/tests/GlobalHeader.setup.test.d.ts +0 -113
- package/dist/types/typescript-testing/typescript-global-header-breadcrumb-types.d.ts +0 -3
- package/dist/types/typescript-testing/typescript-global-header-deprecated.d.ts +0 -1
- package/dist/types/typescript-testing/typescript-global-header-toolbar-types.d.ts +0 -3
- package/dist/types/typescript-testing/typescript-global-header-valid.d.ts +0 -1
- package/dist/types/utils/useCallbackAfterRender.d.ts +0 -3
|
@@ -38,49 +38,97 @@ var import_ds_props_helpers = require("@elliemae/ds-props-helpers");
|
|
|
38
38
|
var import_react = require("react");
|
|
39
39
|
var import_constants = require("../../../../constants/index.js");
|
|
40
40
|
var import_styles = require("../../../styles.js");
|
|
41
|
+
var import_styles2 = require("../../styles.js");
|
|
41
42
|
var import_PopupMenuContent = require("./menuContent/PopupMenuContent.js");
|
|
42
|
-
var import_useOnClickOutside = require("../../../../hooks/useOnClickOutside.js");
|
|
43
43
|
const PopupMenu = ({
|
|
44
44
|
Icon,
|
|
45
45
|
onClick,
|
|
46
46
|
setRef,
|
|
47
47
|
componentProps,
|
|
48
|
-
|
|
48
|
+
getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
49
49
|
...otherProps
|
|
50
50
|
}) => {
|
|
51
|
-
const { arrowStyles, floatingStyles, isOpen, refs, context, showTooltip, hideTooltip } = (0, import_ds_floating_context.useFloatingContext)({
|
|
52
|
-
externallyControlledIsOpen: componentProps.isOpen,
|
|
53
|
-
placement: "bottom",
|
|
54
|
-
withoutAnimation: true,
|
|
55
|
-
withoutPortal: true
|
|
56
|
-
});
|
|
57
51
|
const {
|
|
58
52
|
onClickOutside = () => null,
|
|
59
53
|
onKeyPress,
|
|
60
54
|
popupOnKeyPress,
|
|
61
55
|
isOpen: userIsOpen,
|
|
62
56
|
options,
|
|
63
|
-
closeOnClick
|
|
57
|
+
closeOnClick,
|
|
58
|
+
onOpen,
|
|
59
|
+
onClose
|
|
64
60
|
} = componentProps;
|
|
65
|
-
const
|
|
61
|
+
const { arrowStyles, floatingStyles, isOpen, refs, context, showTooltip, hideTooltip } = (0, import_ds_floating_context.useFloatingContext)({
|
|
62
|
+
externallyControlledIsOpen: componentProps.isOpen,
|
|
63
|
+
placement: "bottom",
|
|
64
|
+
withoutAnimation: true,
|
|
65
|
+
withoutPortal: true,
|
|
66
|
+
// The hook auto-excludes clicks inside the floating element and the reference, so the
|
|
67
|
+
// outside boundary is now { reference, floating } — no boundary <div> needed.
|
|
68
|
+
// Gated internally on `isOpen`, so it only fires while open.
|
|
69
|
+
onClickOutside: (event) => {
|
|
70
|
+
onClickOutside(event);
|
|
71
|
+
if (userIsOpen === void 0) hideTooltip();
|
|
72
|
+
},
|
|
73
|
+
/*
|
|
74
|
+
* Passive notification, straight through from the floating context. Handed over rather than
|
|
75
|
+
* reimplemented because the hook is the only place that sees every transition: the trigger click and
|
|
76
|
+
* ArrowDown both go through `showTooltip`, and click-outside, Escape inside the menu and a
|
|
77
|
+
* closeOnClick item all go through `hideTooltip` — plus a controlled flip of `isOpen`, which no
|
|
78
|
+
* handler in this file observes at all.
|
|
79
|
+
*
|
|
80
|
+
* Notifying does NOT make the consumer responsible for the transition: this stays uncontrolled unless
|
|
81
|
+
* they also supply `isOpen`.
|
|
82
|
+
*
|
|
83
|
+
* The scoped-Escape caveat in the hook's docs does not apply here. A scoped Escape would route to
|
|
84
|
+
* `onEscape` instead of `onClose`, but that path needs `closeOnEscape`, which defaults to false and is
|
|
85
|
+
* not passed — Escape is handled inside PopupMenuContent and closes via `hideTooltip`, so it surfaces
|
|
86
|
+
* as a normal 'interaction' close. Passing `closeOnEscape` here later would silently punch a hole in
|
|
87
|
+
* `onClose` unless `onEscape` is wired at the same time.
|
|
88
|
+
*/
|
|
89
|
+
/*
|
|
90
|
+
* Escape is the floating context's, not this part's. `closeOnEscape` closes the menu and
|
|
91
|
+
* `returnFocusToReference` puts focus back on the trigger — both were hand-rolled here before, in
|
|
92
|
+
* PopupMenuContent's per-item keydown and in a manual `.focus()`.
|
|
93
|
+
*
|
|
94
|
+
* Gated on being UNCONTROLLED, and that gate is load-bearing rather than tidy: the hook applies
|
|
95
|
+
* `returnFocusToReference` on a scoped Escape whichever side owns the open state. For a controlled
|
|
96
|
+
* consumer the close below is inert, so leaving it on would move focus to the trigger while their
|
|
97
|
+
* menu is still open — focus outside an open menu. A controlled consumer owns the close, so they own
|
|
98
|
+
* the Escape and the refocus with it.
|
|
99
|
+
*/
|
|
100
|
+
closeOnEscape: userIsOpen === void 0,
|
|
101
|
+
returnFocusToReference: true,
|
|
102
|
+
/*
|
|
103
|
+
* A scoped Escape routes HERE and not to `onClose`, so the consumer's close notification has to be
|
|
104
|
+
* re-emitted or it silently stops reporting the most common keyboard close.
|
|
105
|
+
*/
|
|
106
|
+
onEscape: (event) => {
|
|
107
|
+
hideTooltip();
|
|
108
|
+
onClose?.({ reason: "interaction", event, isControlled: userIsOpen !== void 0 });
|
|
109
|
+
},
|
|
110
|
+
onOpen,
|
|
111
|
+
onClose
|
|
112
|
+
});
|
|
113
|
+
const openIntentRef = (0, import_react.useRef)("first");
|
|
66
114
|
const handleOnKeyDown = (0, import_react.useCallback)(
|
|
67
115
|
(e) => {
|
|
68
|
-
if (e.code === "ArrowDown") {
|
|
69
|
-
|
|
116
|
+
if (e.code === "ArrowDown" || e.code === "ArrowUp") {
|
|
117
|
+
e.preventDefault();
|
|
118
|
+
openIntentRef.current = e.code === "ArrowUp" ? "last" : "first";
|
|
119
|
+
if (userIsOpen === void 0) showTooltip();
|
|
70
120
|
}
|
|
71
121
|
if (onKeyPress) onKeyPress(e);
|
|
72
122
|
},
|
|
73
|
-
[onKeyPress, showTooltip]
|
|
123
|
+
[onKeyPress, showTooltip, userIsOpen]
|
|
74
124
|
);
|
|
75
125
|
const handleOnClose = (0, import_react.useCallback)(() => {
|
|
76
|
-
if (userIsOpen === void 0)
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
refs.reference?.focus();
|
|
80
|
-
}, [hideTooltip, refs.reference, userIsOpen]);
|
|
126
|
+
if (userIsOpen === void 0) hideTooltip();
|
|
127
|
+
}, [hideTooltip, userIsOpen]);
|
|
81
128
|
const handleTriggerOnClick = (0, import_react.useCallback)(
|
|
82
129
|
(e) => {
|
|
83
|
-
|
|
130
|
+
openIntentRef.current = "first";
|
|
131
|
+
if (userIsOpen === void 0) showTooltip(e);
|
|
84
132
|
if (onClick) onClick(e);
|
|
85
133
|
},
|
|
86
134
|
[onClick, userIsOpen, showTooltip]
|
|
@@ -88,18 +136,6 @@ const PopupMenu = ({
|
|
|
88
136
|
const handleItemClick = (0, import_react.useCallback)(() => {
|
|
89
137
|
if (closeOnClick && userIsOpen === void 0) handleOnClose();
|
|
90
138
|
}, [closeOnClick, handleOnClose, userIsOpen]);
|
|
91
|
-
const handleOutside = (0, import_react.useCallback)(
|
|
92
|
-
(event) => {
|
|
93
|
-
onClickOutside(event);
|
|
94
|
-
const actuallyOpen = userIsOpen ?? isOpen;
|
|
95
|
-
if (!actuallyOpen) return;
|
|
96
|
-
if (userIsOpen === void 0) {
|
|
97
|
-
handleOnClose();
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
[handleOnClose, isOpen, onClickOutside, userIsOpen]
|
|
101
|
-
);
|
|
102
|
-
(0, import_useOnClickOutside.useOnClickOutside)(userIsOpen ?? isOpen ? boundaryRef.current : null, handleOutside);
|
|
103
139
|
const handleRefs = (0, import_react.useCallback)(
|
|
104
140
|
(ref) => {
|
|
105
141
|
setRef(ref);
|
|
@@ -107,45 +143,56 @@ const PopupMenu = ({
|
|
|
107
143
|
},
|
|
108
144
|
[refs, setRef]
|
|
109
145
|
);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
const noSlotArguments = (0, import_react.useCallback)(() => ({}), []);
|
|
147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
148
|
+
import_styles2.StyledPopupMenuContainer,
|
|
149
|
+
{
|
|
150
|
+
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_POPUPMENU_CONTAINER,
|
|
151
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
152
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
153
|
+
...(0, import_ds_props_helpers.useGetXstyledProps)(otherProps),
|
|
154
|
+
children: [
|
|
155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
156
|
+
import_styles.StyledButton,
|
|
157
|
+
{
|
|
158
|
+
onClick: handleTriggerOnClick,
|
|
159
|
+
onKeyDown: handleOnKeyDown,
|
|
160
|
+
innerRef: handleRefs,
|
|
161
|
+
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_ITEM_BUTTON,
|
|
162
|
+
"aria-haspopup": true,
|
|
163
|
+
"aria-expanded": userIsOpen ?? isOpen,
|
|
164
|
+
...(0, import_ds_props_helpers.useGetGlobalAttributes)(otherProps),
|
|
165
|
+
type: "button",
|
|
166
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
167
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
168
|
+
children: Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: "m" })
|
|
169
|
+
}
|
|
170
|
+
),
|
|
171
|
+
refs.reference ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
172
|
+
import_ds_floating_context.FloatingWrapper,
|
|
173
|
+
{
|
|
174
|
+
innerRef: refs.setFloating,
|
|
175
|
+
isOpen: userIsOpen ?? isOpen,
|
|
176
|
+
floatingStyles,
|
|
177
|
+
context,
|
|
178
|
+
children: [
|
|
179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
180
|
+
import_PopupMenuContent.PopupMenuContent,
|
|
181
|
+
{
|
|
182
|
+
options,
|
|
183
|
+
onItemClick: handleItemClick,
|
|
184
|
+
openIntent: openIntentRef.current,
|
|
185
|
+
setIsOpen: hideTooltip,
|
|
186
|
+
popupOnKeyPress,
|
|
187
|
+
getOwnerPropsAwareOfPropsPassedToGlobalHeader
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ds_floating_context.PopoverArrow, { ...arrowStyles })
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
) : null
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
);
|
|
150
197
|
};
|
|
151
198
|
//# sourceMappingURL=PopupMenu.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/parts/Toolbar/outOfTheBox/PopupMenu/PopupMenu.tsx", "../../../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["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
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["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", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_styles"]
|
|
7
7
|
}
|
|
@@ -43,20 +43,31 @@ const PopupMenuContent = import_react.default.memo(
|
|
|
43
43
|
({
|
|
44
44
|
options,
|
|
45
45
|
onItemClick,
|
|
46
|
-
|
|
46
|
+
openIntent,
|
|
47
47
|
popupOnKeyPress,
|
|
48
48
|
setIsOpen,
|
|
49
|
-
|
|
49
|
+
getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
50
|
+
// The part-level global attribute + xstyled layers, forwarded onto the list root below.
|
|
51
|
+
...restGlobalAndXstyled
|
|
50
52
|
}) => {
|
|
51
53
|
const { instanceUID } = (0, import_react.useContext)(import_DSGlobalHeaderContext.DSGlobalHeaderContext);
|
|
52
|
-
const
|
|
54
|
+
const focusableItemsCount = options.filter((option) => option.type !== "separator").length;
|
|
55
|
+
const { menuRef, setRef, keyboardNavigation } = (0, import_usePopupMenuContent.usePopupMenuContent)({
|
|
56
|
+
setIsOpen,
|
|
57
|
+
openIntent,
|
|
58
|
+
focusableItemsCount
|
|
59
|
+
});
|
|
60
|
+
const noSlotArguments = () => ({});
|
|
53
61
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
54
62
|
import_styles.StyledList,
|
|
55
63
|
{
|
|
56
64
|
innerRef: menuRef,
|
|
57
65
|
role: "menu",
|
|
58
66
|
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_LIST,
|
|
59
|
-
|
|
67
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
68
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
69
|
+
...(0, import_ds_props_helpers.getGlobalAttributes)(restGlobalAndXstyled),
|
|
70
|
+
...(0, import_ds_props_helpers.getXstyledProps)(restGlobalAndXstyled),
|
|
60
71
|
children: options.map((option) => {
|
|
61
72
|
const { type, Icon, label = "", onClick, Content, ...rest } = option;
|
|
62
73
|
const globalAttrs = (0, import_ds_props_helpers.getGlobalAttributes)(rest);
|
|
@@ -66,7 +77,6 @@ const PopupMenuContent = import_react.default.memo(
|
|
|
66
77
|
};
|
|
67
78
|
const handleKeyDown = (e) => {
|
|
68
79
|
keyboardNavigation(e);
|
|
69
|
-
if (e.code === "Escape") onClose();
|
|
70
80
|
if (popupOnKeyPress) popupOnKeyPress(e);
|
|
71
81
|
};
|
|
72
82
|
switch (type) {
|
|
@@ -77,7 +87,8 @@ const PopupMenuContent = import_react.default.memo(
|
|
|
77
87
|
role: "none",
|
|
78
88
|
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_SEPARATOR,
|
|
79
89
|
...globalAttrs,
|
|
80
|
-
|
|
90
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
91
|
+
getOwnerPropsArguments: noSlotArguments
|
|
81
92
|
},
|
|
82
93
|
`${instanceUID}-separator-${label}`
|
|
83
94
|
);
|
|
@@ -87,7 +98,8 @@ const PopupMenuContent = import_react.default.memo(
|
|
|
87
98
|
{
|
|
88
99
|
role: "menuitem",
|
|
89
100
|
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM,
|
|
90
|
-
|
|
101
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
102
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
91
103
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
92
104
|
import_styles.StyledItemButton,
|
|
93
105
|
{
|
|
@@ -97,7 +109,8 @@ const PopupMenuContent = import_react.default.memo(
|
|
|
97
109
|
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON,
|
|
98
110
|
...globalAttrs,
|
|
99
111
|
type: "button",
|
|
100
|
-
|
|
112
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
113
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
101
114
|
children: Content && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Content, {})
|
|
102
115
|
}
|
|
103
116
|
)
|
|
@@ -110,7 +123,8 @@ const PopupMenuContent = import_react.default.memo(
|
|
|
110
123
|
{
|
|
111
124
|
role: "menuitem",
|
|
112
125
|
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM,
|
|
113
|
-
|
|
126
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
127
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
114
128
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
115
129
|
import_styles.StyledItemButton,
|
|
116
130
|
{
|
|
@@ -120,14 +134,16 @@ const PopupMenuContent = import_react.default.memo(
|
|
|
120
134
|
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON,
|
|
121
135
|
...globalAttrs,
|
|
122
136
|
type: "button",
|
|
123
|
-
|
|
137
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
138
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
124
139
|
children: [
|
|
125
140
|
Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, {}),
|
|
126
141
|
label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
127
142
|
import_styles.StyledLabel,
|
|
128
143
|
{
|
|
129
144
|
"data-testid": import_constants.GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON_LABEL,
|
|
130
|
-
|
|
145
|
+
getOwnerProps: getOwnerPropsAwareOfPropsPassedToGlobalHeader,
|
|
146
|
+
getOwnerPropsArguments: noSlotArguments,
|
|
131
147
|
children: label
|
|
132
148
|
}
|
|
133
149
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/PopupMenuContent.tsx", "../../../../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { getGlobalAttributes } from '@elliemae/ds-props-helpers';\nimport React, { useContext } from 'react';\nimport { DSGlobalHeaderContext } from '../../../../../DSGlobalHeaderContext.js';\nimport { GLOBAL_HEADER_DATA_TESTID } from '../../../../../constants/index.js';\nimport
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;
|
|
4
|
+
"sourcesContent": ["import { getGlobalAttributes, getXstyledProps } from '@elliemae/ds-props-helpers';\nimport React, { useContext } from 'react';\nimport { DSGlobalHeaderContext } from '../../../../../DSGlobalHeaderContext.js';\nimport { GLOBAL_HEADER_DATA_TESTID } from '../../../../../constants/index.js';\nimport { StyledItemButton, StyledItemContainer, StyledLabel, StyledList, StyledSeparator } from './styles.js';\nimport type { PopupMenuContentT } from './react-desc-prop-types.js';\nimport { usePopupMenuContent } from './usePopupMenuContent.js';\n\nexport const PopupMenuContent = React.memo(\n ({\n options,\n onItemClick,\n openIntent,\n popupOnKeyPress,\n setIsOpen,\n getOwnerPropsAwareOfPropsPassedToGlobalHeader,\n // The part-level global attribute + xstyled layers, forwarded onto the list root below.\n ...restGlobalAndXstyled\n }: PopupMenuContentT.Props): JSX.Element => {\n const { instanceUID } = useContext(DSGlobalHeaderContext);\n\n // Separators are rendered as `role=\"none\"` and carry no ref, so they are excluded from the count the\n // seeding compares against.\n const focusableItemsCount = options.filter((option) => option.type !== 'separator').length;\n\n const { menuRef, setRef, keyboardNavigation } = usePopupMenuContent({\n setIsOpen,\n openIntent,\n focusableItemsCount,\n });\n\n /*\n * Explicit and empty at every slot render site below. `getOwnerPropsArguments` hydrates function-form\n * slot props and nothing else, so \"no arguments\" is worth stating rather than leaving to inference.\n *\n * The per-option sites (item container, item button, label, separator) are where a real payload would\n * go \u2014 ds-fast-list hands its rows `{ index: getId(index) }` for exactly this. What a per-option payload\n * should contain is a consumer-facing contract decision, so adding one is a deliberate API change, not\n * a fill-in-the-blank.\n */\n const noSlotArguments = () => ({});\n\n return (\n <StyledList\n innerRef={menuRef}\n role=\"menu\"\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_LIST}\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n {...getGlobalAttributes(restGlobalAndXstyled)}\n {...getXstyledProps(restGlobalAndXstyled)}\n >\n {options.map((option) => {\n const { type, Icon, label = '', onClick, Content, ...rest } = option;\n\n const globalAttrs = getGlobalAttributes(rest);\n\n const handleClick = (e: React.MouseEvent) => {\n onItemClick();\n if (onClick) onClick(e);\n };\n\n /*\n * No Escape branch here on purpose. Escape is the floating context's, via `closeOnEscape` +\n * `returnFocusToReference` \u2014 it closes the menu AND returns focus to the trigger, which this\n * part used to hand-roll. Re-adding a local Escape would close it twice and fight that focus\n * return.\n */\n const handleKeyDown = (e: React.KeyboardEvent) => {\n keyboardNavigation(e);\n if (popupOnKeyPress) popupOnKeyPress(e);\n };\n\n switch (type) {\n case 'separator':\n return (\n <StyledSeparator\n key={`${instanceUID}-separator-${label}`}\n role=\"none\"\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_SEPARATOR}\n {...globalAttrs}\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n />\n );\n case 'custom':\n return (\n <StyledItemContainer\n key={`${instanceUID}-popup-${label}`}\n role=\"menuitem\"\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM}\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n >\n <StyledItemButton\n innerRef={setRef}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON}\n {...globalAttrs}\n type=\"button\"\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n >\n {Content && <Content />}\n </StyledItemButton>\n </StyledItemContainer>\n );\n default:\n return (\n <StyledItemContainer\n key={`${instanceUID}-popup-${label}`}\n role=\"menuitem\"\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM}\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n >\n <StyledItemButton\n innerRef={setRef}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON}\n {...globalAttrs}\n type=\"button\"\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n >\n {Icon && <Icon />}\n {label && (\n <StyledLabel\n data-testid={GLOBAL_HEADER_DATA_TESTID.MENUBAR_POPUP_MENU_ITEM_BUTTON_LABEL}\n getOwnerProps={getOwnerPropsAwareOfPropsPassedToGlobalHeader}\n getOwnerPropsArguments={noSlotArguments}\n >\n {label}\n </StyledLabel>\n )}\n </StyledItemButton>\n </StyledItemContainer>\n );\n }\n })}\n </StyledList>\n );\n },\n);\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["React"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var react_desc_prop_types_exports = {};
|
|
30
|
+
__export(react_desc_prop_types_exports, {
|
|
31
|
+
PopupMenuContentPropTypes: () => PopupMenuContentPropTypes,
|
|
32
|
+
PopupMenuContentPropTypesSchema: () => PopupMenuContentPropTypesSchema
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(react_desc_prop_types_exports);
|
|
35
|
+
var React = __toESM(require("react"));
|
|
36
|
+
var import_ds_props_helpers = require("@elliemae/ds-props-helpers");
|
|
37
|
+
const PopupMenuContentPropTypes = {
|
|
38
|
+
...import_ds_props_helpers.globalAttributesPropTypes,
|
|
39
|
+
...import_ds_props_helpers.xstyledPropTypes,
|
|
40
|
+
options: import_ds_props_helpers.PropTypes.array.description(
|
|
41
|
+
"Consumer-authored menu entries. Format: [{ type?, Icon?, label?, onClick?, Content?, ...globalAttributes }]"
|
|
42
|
+
).isRequired,
|
|
43
|
+
onItemClick: import_ds_props_helpers.PropTypes.func.description("Invoked after a menu item click so the wrapper can apply its closeOnClick policy").signature("(() => void )").isRequired,
|
|
44
|
+
openIntent: import_ds_props_helpers.PropTypes.string.description('Which end of the menu this open lands on: "first" or "last"').isRequired,
|
|
45
|
+
setIsOpen: import_ds_props_helpers.PropTypes.func.description("The floating context's hide function").signature("(() => void )").isRequired,
|
|
46
|
+
getOwnerPropsAwareOfPropsPassedToGlobalHeader: import_ds_props_helpers.PropTypes.func.description(
|
|
47
|
+
"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"
|
|
48
|
+
).signature("(() => Partial<DSGlobalHeaderT.DefaultProps> )").isRequired,
|
|
49
|
+
popupOnKeyPress: import_ds_props_helpers.PropTypes.func.description("Consumer key handler, invoked on menu items alongside the internal keyboard navigation").signature("(( event: React.KeyboardEvent ) => void )")
|
|
50
|
+
};
|
|
51
|
+
const PopupMenuContentPropTypesSchema = PopupMenuContentPropTypes;
|
|
52
|
+
//# sourceMappingURL=react-desc-prop-types.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/react-desc-prop-types.ts", "../../../../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
+
"sourcesContent": ["import type { DSPropTypesSchema, GlobalAttributesT, ValidationMap, XstyledProps } from '@elliemae/ds-props-helpers';\nimport { PropTypes, globalAttributesPropTypes, xstyledPropTypes } from '@elliemae/ds-props-helpers';\nimport type React from 'react';\nimport type { DSGlobalHeaderT } from '../../../../../react-desc-prop-types.js';\n\n/*\n * Relocated here from DSGlobalHeaderT.PopupMenuContentProps, per the convention every other part in the\n * repo follows. Consumed by PopupMenuContent.tsx.\n *\n * This is the innermost of the three Popup* contracts and the one least likely to be a consumer's\n * business: it is what the PopupMenu wrapper hands to its own menu-content renderer. Every prop except\n * `options` is machinery the wrapper generated. `options` is the one consumer-authored value on it,\n * and it arrives already unwrapped from DSGlobalHeaderT.PopupMenuComponentProps \u2014 which is exactly why\n * having both `PopupMenuComponentProps` and `PopupMenuContentProps` visible side by side in the public\n * namespace was misleading: they look like a pair a developer chooses between, and they are not.\n *\n * IoC layers: the slot layer via `getOwnerPropsAwareOfPropsPassedToGlobalHeader` (fully wired \u2014 this part\n * passes it to the list, items, item buttons, labels and separators, each with its own explicit empty\n * hydrator), per-entry global attributes via `options` items, and the part-level global attribute /\n * xstyled layer below.\n *\n * KNOWN GAP \u2014 the part-level global attribute + xstyled layer is the one thing in this file that was an\n * addition rather than a transcription: the old DSGlobalHeaderT.PopupMenuContentProps did not extend\n * GlobalAttributesT at all, which made this the only out-of-the-box part missing that layer and left its\n * PropTypes unable to spread globalAttributesPropTypes coherently. Nothing forwards either to the root\n * list yet, so for this part both remain a statement of the intended contract rather than of behaviour.\n * Per-entry attributes on `options` items DO reach the DOM and are covered by the pillar tests.\n *\n * No slots of its own \u2014 see the AppPicker sibling file for why.\n */\nexport declare namespace PopupMenuContentT {\n export interface RequiredProps {\n /** The consumer-authored menu entries, unwrapped from componentProps by the PopupMenu wrapper. */\n options: DSGlobalHeaderT.PopupMenuContentItem[];\n /** Wrapper callback: applies the item's closeOnClick policy after a menu item is clicked. */\n onItemClick: () => void;\n /** Wrapper callback: closes the menu and returns focus to the trigger. */\n /** Which end of the menu this open lands on \u2014 see usePopupMenuContent. */\n openIntent: 'first' | 'last';\n /** Wrapper callback: the floating context's hide function. */\n setIsOpen: () => void;\n /*\n * The slot lookup table, and the only half of the slot IoC layer that may be drilled down \u2014 the\n * function-form hydrator is supplied per slot render site instead. See the AppPicker sibling for the\n * full reasoning and the getPartProps mechanics behind the name.\n */\n getOwnerPropsAwareOfPropsPassedToGlobalHeader: () => Partial<DSGlobalHeaderT.DefaultProps>;\n }\n\n /*\n * Intentionally empty, and intentionally still declared \u2014 \"this part has no default props, do not\n * expect them\". See the AppPicker sibling for the full reasoning.\n */\n export interface DefaultProps {}\n\n export interface OptionalProps {\n /*\n * Optional, matching the runtime: PopupMenuContent guards it (`if (popupOnKeyPress)`) and consumers\n * routinely omit it. It was declared required, which was simply wrong \u2014 the type claimed a guarantee\n * the code never relied on, and every consumer omitting it was type-lying to satisfy the compiler.\n */\n popupOnKeyPress?: (event: React.KeyboardEvent) => void;\n }\n\n export interface Props\n extends\n Partial<DefaultProps>,\n OptionalProps,\n Omit<\n GlobalAttributesT<HTMLUListElement>,\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<HTMLUListElement>,\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 PopupMenuContentPropTypes: DSPropTypesSchema<PopupMenuContentT.Props> = {\n ...globalAttributesPropTypes,\n ...xstyledPropTypes,\n options: PropTypes.array.description(\n 'Consumer-authored menu entries. Format: [{ type?, Icon?, label?, onClick?, Content?, ...globalAttributes }]',\n ).isRequired,\n onItemClick: PropTypes.func\n .description('Invoked after a menu item click so the wrapper can apply its closeOnClick policy')\n .signature('(() => void )').isRequired,\n openIntent: PropTypes.string.description('Which end of the menu this open lands on: \"first\" or \"last\"').isRequired,\n setIsOpen: PropTypes.func.description(\"The floating context's hide function\").signature('(() => void )').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 popupOnKeyPress: PropTypes.func\n .description('Consumer key handler, invoked on menu items alongside the internal keyboard navigation')\n .signature('(( event: React.KeyboardEvent ) => void )'),\n};\n\nexport const PopupMenuContentPropTypesSchema =\n PopupMenuContentPropTypes as unknown as ValidationMap<PopupMenuContentT.Props>;\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADCvB,8BAAuE;AAwFhE,MAAM,4BAAwE;AAAA,EACnF,GAAG;AAAA,EACH,GAAG;AAAA,EACH,SAAS,kCAAU,MAAM;AAAA,IACvB;AAAA,EACF,EAAE;AAAA,EACF,aAAa,kCAAU,KACpB,YAAY,kFAAkF,EAC9F,UAAU,eAAe,EAAE;AAAA,EAC9B,YAAY,kCAAU,OAAO,YAAY,6DAA6D,EAAE;AAAA,EACxG,WAAW,kCAAU,KAAK,YAAY,sCAAsC,EAAE,UAAU,eAAe,EAAE;AAAA,EACzG,+CAA+C,kCAAU,KACtD;AAAA,IACC;AAAA,EACF,EACC,UAAU,gDAAgD,EAAE;AAAA,EAC/D,iBAAiB,kCAAU,KACxB,YAAY,wFAAwF,EACpG,UAAU,2CAA2C;AAC1D;AAEO,MAAM,kCACX;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -33,24 +33,32 @@ __export(usePopupMenuContent_exports, {
|
|
|
33
33
|
module.exports = __toCommonJS(usePopupMenuContent_exports);
|
|
34
34
|
var React = __toESM(require("react"));
|
|
35
35
|
var import_react = require("react");
|
|
36
|
-
const usePopupMenuContent = ({ setIsOpen }) => {
|
|
36
|
+
const usePopupMenuContent = ({ setIsOpen, openIntent, focusableItemsCount }) => {
|
|
37
37
|
const menuRef = (0, import_react.useRef)(null);
|
|
38
38
|
const allMenuItemsRef = (0, import_react.useRef)([]);
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
const hasSeededFocusRef = (0, import_react.useRef)(false);
|
|
40
|
+
const setRef = (0, import_react.useCallback)(
|
|
41
|
+
(ref) => {
|
|
42
|
+
if (ref && !allMenuItemsRef.current.includes(ref)) {
|
|
43
|
+
allMenuItemsRef.current.push(ref);
|
|
44
|
+
}
|
|
45
|
+
allMenuItemsRef.current.forEach((item, index) => {
|
|
46
|
+
if (index === 0) {
|
|
47
|
+
item?.setAttribute?.("tabindex", "0");
|
|
48
|
+
} else {
|
|
49
|
+
item?.setAttribute?.("tabindex", "-1");
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (!ref || hasSeededFocusRef.current) return;
|
|
53
|
+
const hasReachedSeedTarget = openIntent === "last" ? allMenuItemsRef.current.length === focusableItemsCount : allMenuItemsRef.current[0] === ref;
|
|
54
|
+
if (hasReachedSeedTarget) {
|
|
55
|
+
hasSeededFocusRef.current = true;
|
|
56
|
+
const target = openIntent === "last" ? allMenuItemsRef.current[focusableItemsCount - 1] : ref;
|
|
57
|
+
target?.focus();
|
|
48
58
|
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
setTimeout(() => allMenuItemsRef.current?.[0]?.focus(), 0);
|
|
53
|
-
}, []);
|
|
59
|
+
},
|
|
60
|
+
[openIntent, focusableItemsCount]
|
|
61
|
+
);
|
|
54
62
|
const keyboardNavigation = (0, import_react.useCallback)(
|
|
55
63
|
(e) => {
|
|
56
64
|
if (e.code === "Tab") {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/parts/Toolbar/outOfTheBox/PopupMenu/menuContent/usePopupMenuContent.tsx", "../../../../../../../../../../scripts/build/transpile/react-shim.js"],
|
|
4
|
-
"sourcesContent": ["import { useRef, useCallback
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,
|
|
4
|
+
"sourcesContent": ["import { useRef, useCallback } from 'react';\n\ninterface UsePopupMenuContentT {\n setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;\n /**\n * Which end of the menu this open should land on. Mirrors DSAppPicker's open-intent mechanism, scoped\n * to this part: the trigger records WHICH key opened the menu and the seeding below reads it \u2014 ArrowUp\n * lands on the last item, everything else on the first.\n */\n openIntent: 'first' | 'last';\n /** How many focusable items the menu mounts. Separators are not focusable and are excluded. */\n focusableItemsCount: number;\n}\n\nexport const usePopupMenuContent = ({ setIsOpen, openIntent, focusableItemsCount }: UsePopupMenuContentT) => {\n const menuRef = useRef<HTMLUListElement>(null);\n const allMenuItemsRef = useRef<HTMLButtonElement[]>([]);\n // Seeded once per mount of the menu content. A ref rather than state because nothing renders from it.\n const hasSeededFocusRef = useRef(false);\n\n const setRef = useCallback(\n (ref: HTMLButtonElement) => {\n if (ref && !allMenuItemsRef.current.includes(ref)) {\n allMenuItemsRef.current.push(ref);\n }\n\n allMenuItemsRef.current.forEach((item, index) => {\n if (index === 0) {\n item?.setAttribute?.('tabindex', '0');\n } else {\n item?.setAttribute?.('tabindex', '-1');\n }\n });\n\n /*\n * Initial focus, seeded from this ref callback \u2014 the correct place for it, because the callback is\n * guaranteed to run once the node exists. Do not move this into an effect or wrap it in a timer; per\n * antipattern_focus_management.md there is nothing left to wait for, and both reintroduce a race this\n * has no need for.\n *\n * `first` can seed the moment item 0 attaches. `last` cannot: the ref callbacks fire one per item and\n * nothing else here knows when the set is complete, which is why the count is passed in rather than\n * inferred. Comparing against it keeps the decision inside the callback instead of deferring it.\n *\n * Seeds once per mount of the menu content, which is why the guard ref exists.\n */\n if (!ref || hasSeededFocusRef.current) return;\n\n const hasReachedSeedTarget =\n openIntent === 'last'\n ? allMenuItemsRef.current.length === focusableItemsCount\n : allMenuItemsRef.current[0] === ref;\n\n if (hasReachedSeedTarget) {\n hasSeededFocusRef.current = true;\n const target = openIntent === 'last' ? allMenuItemsRef.current[focusableItemsCount - 1] : ref;\n target?.focus();\n }\n },\n [openIntent, focusableItemsCount],\n );\n\n const keyboardNavigation = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.code === 'Tab') {\n setIsOpen(false);\n } else {\n const currentIndex = allMenuItemsRef.current.indexOf(e.target as HTMLButtonElement);\n const allRefsLength = allMenuItemsRef.current.length;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (currentIndex < allRefsLength - 1) {\n allMenuItemsRef.current[currentIndex + 1]?.focus?.();\n } else {\n allMenuItemsRef.current[0]?.focus?.();\n }\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (currentIndex === 0) {\n allMenuItemsRef.current[allRefsLength - 1]?.focus?.();\n } else {\n allMenuItemsRef.current[currentIndex - 1]?.focus?.();\n }\n }\n }\n },\n [setIsOpen],\n );\n\n return {\n menuRef,\n setRef,\n keyboardNavigation,\n };\n};\n", "import * as React from 'react';\nexport { React };\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;ACAA,YAAuB;ADAvB,mBAAoC;AAc7B,MAAM,sBAAsB,CAAC,EAAE,WAAW,YAAY,oBAAoB,MAA4B;AAC3G,QAAM,cAAU,qBAAyB,IAAI;AAC7C,QAAM,sBAAkB,qBAA4B,CAAC,CAAC;AAEtD,QAAM,wBAAoB,qBAAO,KAAK;AAEtC,QAAM,aAAS;AAAA,IACb,CAAC,QAA2B;AAC1B,UAAI,OAAO,CAAC,gBAAgB,QAAQ,SAAS,GAAG,GAAG;AACjD,wBAAgB,QAAQ,KAAK,GAAG;AAAA,MAClC;AAEA,sBAAgB,QAAQ,QAAQ,CAAC,MAAM,UAAU;AAC/C,YAAI,UAAU,GAAG;AACf,gBAAM,eAAe,YAAY,GAAG;AAAA,QACtC,OAAO;AACL,gBAAM,eAAe,YAAY,IAAI;AAAA,QACvC;AAAA,MACF,CAAC;AAcD,UAAI,CAAC,OAAO,kBAAkB,QAAS;AAEvC,YAAM,uBACJ,eAAe,SACX,gBAAgB,QAAQ,WAAW,sBACnC,gBAAgB,QAAQ,CAAC,MAAM;AAErC,UAAI,sBAAsB;AACxB,0BAAkB,UAAU;AAC5B,cAAM,SAAS,eAAe,SAAS,gBAAgB,QAAQ,sBAAsB,CAAC,IAAI;AAC1F,gBAAQ,MAAM;AAAA,MAChB;AAAA,IACF;AAAA,IACA,CAAC,YAAY,mBAAmB;AAAA,EAClC;AAEA,QAAM,yBAAqB;AAAA,IACzB,CAAC,MAA2B;AAC1B,UAAI,EAAE,SAAS,OAAO;AACpB,kBAAU,KAAK;AAAA,MACjB,OAAO;AACL,cAAM,eAAe,gBAAgB,QAAQ,QAAQ,EAAE,MAA2B;AAClF,cAAM,gBAAgB,gBAAgB,QAAQ;AAC9C,YAAI,EAAE,QAAQ,aAAa;AACzB,YAAE,eAAe;AACjB,cAAI,eAAe,gBAAgB,GAAG;AACpC,4BAAgB,QAAQ,eAAe,CAAC,GAAG,QAAQ;AAAA,UACrD,OAAO;AACL,4BAAgB,QAAQ,CAAC,GAAG,QAAQ;AAAA,UACtC;AAAA,QACF;AACA,YAAI,EAAE,QAAQ,WAAW;AACvB,YAAE,eAAe;AACjB,cAAI,iBAAiB,GAAG;AACtB,4BAAgB,QAAQ,gBAAgB,CAAC,GAAG,QAAQ;AAAA,UACtD,OAAO;AACL,4BAAgB,QAAQ,eAAe,CAAC,GAAG,QAAQ;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|