@atlaskit/dropdown-menu
Version:
A dropdown menu displays a list of actions or options to a user.
102 lines (100 loc) • 4.12 kB
JavaScript
/* menu-wrapper.tsx generated by @compiled/babel-plugin v0.36.1 */
import "./menu-wrapper.compiled.css";
import * as React from 'react';
import { ax, ix } from "@compiled/react/runtime";
import { useContext, useEffect, useLayoutEffect } from 'react';
import MenuGroup from '@atlaskit/menu/menu-group';
import { Box } from '@atlaskit/primitives/compiled';
import Spinner from '@atlaskit/spinner';
import isCheckboxItem from '../utils/is-checkbox-item';
import isRadioItem from '../utils/is-radio-item';
import { FocusManagerContext } from './focus-manager';
var styles = {
spinnerContainer: "_1e0c1txw _1ul91lit _1bah1h6o _ca0qv47k _u5f3v47k _n3tdv47k _19bvv47k"
};
var LoadingIndicator = function LoadingIndicator(_ref) {
var _ref$statusLabel = _ref.statusLabel,
statusLabel = _ref$statusLabel === void 0 ? 'Loading' : _ref$statusLabel,
testId = _ref.testId;
return /*#__PURE__*/React.createElement(Box, {
xcss: styles.spinnerContainer,
role: "menuitem"
}, /*#__PURE__*/React.createElement(Spinner, {
size: "small",
label: statusLabel,
testId: testId
}));
};
/**
*
* MenuWrapper wraps all the menu items.
* It handles the logic to close the menu when a MenuItem is clicked, but leaves it open
* if a CheckboxItem or RadioItem is clicked.
* It also sets focus to the first menu item when opened.
*/
var MenuWrapper = function MenuWrapper(_ref2) {
var children = _ref2.children,
isLoading = _ref2.isLoading,
maxHeight = _ref2.maxHeight,
maxWidth = _ref2.maxWidth,
onClose = _ref2.onClose,
onUpdate = _ref2.onUpdate,
statusLabel = _ref2.statusLabel,
setInitialFocusRef = _ref2.setInitialFocusRef,
shouldRenderToParent = _ref2.shouldRenderToParent,
spacing = _ref2.spacing,
testId = _ref2.testId,
isTriggeredUsingKeyboard = _ref2.isTriggeredUsingKeyboard,
autoFocus = _ref2.autoFocus;
var _useContext = useContext(FocusManagerContext),
menuItemRefs = _useContext.menuItemRefs;
var closeOnMenuItemClick = function closeOnMenuItemClick(e) {
var isTargetMenuItemOrDescendant = menuItemRefs.some(function (menuItemRef) {
var menuItem = menuItemRef.current;
if (!menuItem) {
return false;
}
var isCheckboxOrRadio = isCheckboxItem(menuItem) || isRadioItem(menuItem);
return menuItem.contains(e.target) && !isCheckboxOrRadio;
});
// Close menu if the click is triggered from a MenuItem or
// its descendant. Don't close the menu if the click is triggered
// from a MenuItemRadio or MenuItemCheckbox so that the user can
// select multiple items.
if (isTargetMenuItemOrDescendant && onClose) {
onClose(e);
}
};
// Using useEffect here causes a flicker.
// useLayoutEffect ensures that the update and render happen in the same
// rAF tick.
useLayoutEffect(function () {
onUpdate();
}, [isLoading, onUpdate]);
useEffect(function () {
var _menuItemRefs$map$fin;
var firstFocusableRef = (_menuItemRefs$map$fin = menuItemRefs.map(function (_ref3) {
var current = _ref3.current;
return current;
}).find(function (el) {
return !!el && !el.hasAttribute('disabled');
})) !== null && _menuItemRefs$map$fin !== void 0 ? _menuItemRefs$map$fin : null;
if (shouldRenderToParent && (isTriggeredUsingKeyboard || autoFocus)) {
firstFocusableRef === null || firstFocusableRef === void 0 || firstFocusableRef.focus();
}
setInitialFocusRef === null || setInitialFocusRef === void 0 || setInitialFocusRef(firstFocusableRef);
}, [menuItemRefs, setInitialFocusRef, autoFocus, shouldRenderToParent, isTriggeredUsingKeyboard]);
return /*#__PURE__*/React.createElement(MenuGroup, {
isLoading: isLoading,
maxHeight: maxHeight,
maxWidth: maxWidth,
onClick: closeOnMenuItemClick,
role: "menu",
spacing: spacing,
testId: testId && "".concat(testId, "--menu-group")
}, isLoading ? /*#__PURE__*/React.createElement(LoadingIndicator, {
statusLabel: statusLabel,
testId: testId && "".concat(testId, "--loading-indicator")
}) : children);
};
export default MenuWrapper;