UNPKG

@atlaskit/dropdown-menu

Version:

A dropdown menu displays a list of actions or options to a user.

101 lines (99 loc) 3.52 kB
/* 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'; const styles = { spinnerContainer: "_1e0c1txw _1ul91lit _1bah1h6o _ca0qv47k _u5f3v47k _n3tdv47k _19bvv47k" }; const LoadingIndicator = ({ statusLabel = 'Loading', testId }) => /*#__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. */ const MenuWrapper = ({ children, isLoading, maxHeight, maxWidth, onClose, onUpdate, statusLabel, setInitialFocusRef, shouldRenderToParent, spacing, testId, isTriggeredUsingKeyboard, autoFocus }) => { const { menuItemRefs } = useContext(FocusManagerContext); const closeOnMenuItemClick = e => { const isTargetMenuItemOrDescendant = menuItemRefs.some(menuItemRef => { const { current: menuItem } = menuItemRef; if (!menuItem) { return false; } const 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(() => { onUpdate(); }, [isLoading, onUpdate]); useEffect(() => { var _menuItemRefs$map$fin; const firstFocusableRef = (_menuItemRefs$map$fin = menuItemRefs.map(({ current }) => current).find(el => !!el && !el.hasAttribute('disabled'))) !== null && _menuItemRefs$map$fin !== void 0 ? _menuItemRefs$map$fin : null; if (shouldRenderToParent && (isTriggeredUsingKeyboard || autoFocus)) { firstFocusableRef === null || firstFocusableRef === void 0 ? void 0 : firstFocusableRef.focus(); } setInitialFocusRef === null || setInitialFocusRef === void 0 ? 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 && `${testId}--menu-group` }, isLoading ? /*#__PURE__*/React.createElement(LoadingIndicator, { statusLabel: statusLabel, testId: testId && `${testId}--loading-indicator` }) : children); }; export default MenuWrapper;