@momentum-ui/react-collaboration
Version:
Cisco Momentum UI Framework for React Collaboration Applications
104 lines • 5.85 kB
JavaScript
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