UNPKG

@momentum-ui/react-collaboration

Version:

Cisco Momentum UI Framework for React Collaboration Applications

104 lines 5.85 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; import React, { useRef, Children, useState, useEffect, useImperativeHandle, forwardRef, } from 'react'; import classnames from 'classnames'; import { STYLE, DEFAULTS } from './MenuTrigger.constants'; import './MenuTrigger.style.scss'; import { useMenuTriggerState } from '@react-stately/menu'; import { useMenuTrigger } from '@react-aria/menu'; import { MenuContext } from '../Menu'; import { useKeyboard } from '@react-aria/interactions'; import ContentSeparator from '../ContentSeparator'; import Popover from '../Popover'; import { useSpatialNavigationContext } from '../SpatialNavigationProvider/SpatialNavigationProvider.utils'; var MenuTrigger = forwardRef(function (props, ref) { var _a; var className = props.className, id = props.id, style = props.style, closeOnSelect = props.closeOnSelect, children = props.children, isOpen = props.isOpen, delay = props.delay, _b = props.variant, variant = _b === void 0 ? DEFAULTS.VARIANT : _b, _c = props.color, color = _c === void 0 ? DEFAULTS.COLOR : _c, _d = props.showArrow, showArrow = _d === void 0 ? DEFAULTS.SHOW_ARROW : _d, _e = props.placement, placement = _e === void 0 ? DEFAULTS.PLACEMENT : _e, triggerComponent = props.triggerComponent, zIndex = props.zIndex; var state = useMenuTriggerState(props); var _f = useState(), popoverInstance = _f[0], setPopoverInstance = _f[1]; var buttonRef = useRef(); var spatialNav = useSpatialNavigationContext(); useImperativeHandle(ref, function () { return ({ triggerComponentRef: buttonRef, }); }, []); var menus = Children.toArray(children).slice(0); var menuTriggerType = ((_a = triggerComponent.props) === null || _a === void 0 ? void 0 : _a['aria-haspopup']) || 'menu'; var _g = useMenuTrigger({ type: menuTriggerType }, state, buttonRef), menuTriggerProps = _g.menuTriggerProps, menuProps = _g.menuProps; menuTriggerProps['aria-haspopup'] = menuTriggerProps['aria-haspopup'] || menuTriggerType; /** * Handle closeOnSelect from @react-aria manually */ var closeMenuTrigger = function () { state.close(); popoverInstance.hide(); }; var menuContext = __assign(__assign({}, menuProps), { onClose: closeMenuTrigger, closeOnSelect: closeOnSelect }); /** * Handle isOpen from @react-aria manually */ useEffect(function () { if (popoverInstance) { if (isOpen) { popoverInstance.show(); } else { popoverInstance.hide(); } } }, [isOpen, popoverInstance]); /** * Add manual keyboard accessibility because our Popover component * doesn't work well with @react-aria */ var keyboardProps = useKeyboard({ onKeyDown: function (event) { if (event.key === 'Escape' || (spatialNav && event.key === spatialNav.back)) { closeMenuTrigger(); if (spatialNav) { // skip spatial navigation event.nativeEvent.stopImmediatePropagation(); } } }, }).keyboardProps; // delete color prop which is passed down and used in the ModalContainer // because it conflicts with the HTML color property delete keyboardProps.color; // delete the onKeyDown provided by Aria because Popover component will add // appropriate keyboard accessibility instead. delete menuTriggerProps.onKeyDown; return (React.createElement(Popover, __assign({ triggerComponent: React.cloneElement(triggerComponent, __assign(__assign({}, menuTriggerProps), { ref: buttonRef })), className: classnames(className, STYLE.wrapper), trigger: "click", id: id, role: "generic", style: style, placement: placement, interactive: true, showArrow: showArrow, variant: variant, delay: delay, color: color, onClickOutside: closeMenuTrigger, setInstance: setPopoverInstance, // after migrating to new momentum-design components, // ReactAria doesn't work as expected. Firing the onOpenChange // manually after popover is shown / hidden onShow: function () { var _a; (_a = props.onOpenChange) === null || _a === void 0 ? void 0 : _a.call(props, true); }, onHidden: function () { var _a; (_a = props.onOpenChange) === null || _a === void 0 ? void 0 : _a.call(props, false); }, hideOnEsc: false, // Set autofocus to false if there are multiple menus, since the FocusScope in Popover shouldn't automatically focus anywhere, but the // MenuContext.Provider should take care of the auto focusing // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus: false, zIndex: zIndex }, keyboardProps), menus.map(function (menu, index) { return (React.createElement(MenuContext.Provider, { value: // when we have multiple menus inside the menu trigger, we want only the first menu // to autoFocus on open. If we add autoFocus for all Menus, the last menu in the menu // trigger will have the first focus, which is wrong index === 0 ? __assign(__assign({}, menuContext), { autoFocus: 'first' }) : menuContext, key: "{context-".concat(index, "}") }, menu, index !== menus.length - 1 && React.createElement(ContentSeparator, { key: "separator-".concat(index) }))); }))); }); export default MenuTrigger; //# sourceMappingURL=MenuTrigger.js.map