UNPKG

@wordpress/components

Version:
250 lines (244 loc) 7.52 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.DropdownMenu = void 0; var _clsx = _interopRequireDefault(require("clsx")); var _icons = require("@wordpress/icons"); var _context = require("../context"); var _button = _interopRequireDefault(require("../button")); var _dropdown = _interopRequireDefault(require("../dropdown")); var _navigableContainer = require("../navigable-container"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ function mergeProps(defaultProps = {}, props = {}) { const mergedProps = { ...defaultProps, ...props }; if (props.className && defaultProps.className) { mergedProps.className = (0, _clsx.default)(props.className, defaultProps.className); } return mergedProps; } function isFunction(maybeFunc) { return typeof maybeFunc === 'function'; } function UnconnectedDropdownMenu(dropdownMenuProps) { const { children, className, controls, icon = _icons.menu, label, popoverProps, toggleProps, menuProps, disableOpenOnArrowDown = false, text, noIcons, open, defaultOpen, onToggle: onToggleProp, // Context variant } = (0, _context.useContextSystem)(dropdownMenuProps, 'DropdownMenu'); if (!controls?.length && !isFunction(children)) { return null; } // Normalize controls to nested array of objects (sets of controls) let controlSets; if (controls?.length) { // @ts-expect-error The check below is needed because `DropdownMenus` // rendered by `ToolBarGroup` receive controls as a nested array. controlSets = controls; if (!Array.isArray(controlSets[0])) { // This is not ideal, but at this point we know that `controls` is // not a nested array, even if TypeScript doesn't. controlSets = [controls]; } } const mergedPopoverProps = mergeProps({ className: 'components-dropdown-menu__popover', variant }, popoverProps); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_dropdown.default, { className: className, popoverProps: mergedPopoverProps, renderToggle: ({ isOpen, onToggle }) => { var _toggleProps$showTool; const openOnArrowDown = event => { if (disableOpenOnArrowDown) { return; } if (!isOpen && event.code === 'ArrowDown') { event.preventDefault(); onToggle(); } }; const { as: Toggle = _button.default, ...restToggleProps } = toggleProps !== null && toggleProps !== void 0 ? toggleProps : {}; const mergedToggleProps = mergeProps({ className: (0, _clsx.default)('components-dropdown-menu__toggle', { 'is-opened': isOpen }) }, restToggleProps); return /*#__PURE__*/(0, _jsxRuntime.jsx)(Toggle, { ...mergedToggleProps, icon: icon, onClick: event => { onToggle(); if (mergedToggleProps.onClick) { mergedToggleProps.onClick(event); } }, onKeyDown: event => { openOnArrowDown(event); if (mergedToggleProps.onKeyDown) { mergedToggleProps.onKeyDown(event); } }, "aria-haspopup": "true", "aria-expanded": isOpen, label: label, text: text, showTooltip: (_toggleProps$showTool = toggleProps?.showTooltip) !== null && _toggleProps$showTool !== void 0 ? _toggleProps$showTool : true, children: mergedToggleProps.children }); }, renderContent: props => { const mergedMenuProps = mergeProps({ 'aria-label': label, className: (0, _clsx.default)('components-dropdown-menu__menu', { 'no-icons': noIcons }) }, menuProps); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_navigableContainer.NavigableMenu, { ...mergedMenuProps, role: "menu", children: [isFunction(children) ? children(props) : null, controlSets?.flatMap((controlSet, indexOfSet) => controlSet.map((control, indexOfControl) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.default, { __next40pxDefaultSize: true, onClick: event => { event.stopPropagation(); props.onClose(); if (control.onClick) { control.onClick(); } }, className: (0, _clsx.default)('components-dropdown-menu__menu-item', { 'has-separator': indexOfSet > 0 && indexOfControl === 0, 'is-active': control.isActive, 'is-icon-only': !control.title }), icon: control.icon, label: control.label, "aria-checked": control.role === 'menuitemcheckbox' || control.role === 'menuitemradio' ? control.isActive : undefined, role: control.role === 'menuitemcheckbox' || control.role === 'menuitemradio' ? control.role : 'menuitem', accessibleWhenDisabled: true, disabled: control.isDisabled, children: control.title }, [indexOfSet, indexOfControl].join())))] }); }, open: open, defaultOpen: defaultOpen, onToggle: onToggleProp }); } /** * * The DropdownMenu displays a list of actions (each contained in a MenuItem, * MenuItemsChoice, or MenuGroup) in a compact way. It appears in a Popover * after the user has interacted with an element (a button or icon) or when * they perform a specific action. * * Render a Dropdown Menu with a set of controls: * * ```jsx * import { DropdownMenu } from '@wordpress/components'; * import { * more, * arrowLeft, * arrowRight, * arrowUp, * arrowDown, * } from '@wordpress/icons'; * * const MyDropdownMenu = () => ( * <DropdownMenu * icon={ more } * label="Select a direction" * controls={ [ * { * title: 'Up', * icon: arrowUp, * onClick: () => console.log( 'up' ), * }, * { * title: 'Right', * icon: arrowRight, * onClick: () => console.log( 'right' ), * }, * { * title: 'Down', * icon: arrowDown, * onClick: () => console.log( 'down' ), * }, * { * title: 'Left', * icon: arrowLeft, * onClick: () => console.log( 'left' ), * }, * ] } * /> * ); * ``` * * Alternatively, specify a `children` function which returns elements valid for * use in a DropdownMenu: `MenuItem`, `MenuItemsChoice`, or `MenuGroup`. * * ```jsx * import { DropdownMenu, MenuGroup, MenuItem } from '@wordpress/components'; * import { more, arrowUp, arrowDown, trash } from '@wordpress/icons'; * * const MyDropdownMenu = () => ( * <DropdownMenu icon={ more } label="Select a direction"> * { ( { onClose } ) => ( * <> * <MenuGroup> * <MenuItem icon={ arrowUp } onClick={ onClose }> * Move Up * </MenuItem> * <MenuItem icon={ arrowDown } onClick={ onClose }> * Move Down * </MenuItem> * </MenuGroup> * <MenuGroup> * <MenuItem icon={ trash } onClick={ onClose }> * Remove * </MenuItem> * </MenuGroup> * </> * ) } * </DropdownMenu> * ); * ``` * */ const DropdownMenu = exports.DropdownMenu = (0, _context.contextConnectWithoutRef)(UnconnectedDropdownMenu, 'DropdownMenu'); var _default = exports.default = DropdownMenu; //# sourceMappingURL=index.js.map