UNPKG

@fluentui/react-northstar

Version:
398 lines (392 loc) 16.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.toolbarMenuItemSlotClassNames = exports.toolbarMenuItemClassName = exports.ToolbarMenuItem = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _some2 = _interopRequireDefault(require("lodash/some")); var _invoke2 = _interopRequireDefault(require("lodash/invoke")); var _accessibility = require("@fluentui/accessibility"); var React = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var PropTypes = _interopRequireWildcard(require("prop-types")); var _reactComponentEventListener = require("@fluentui/react-component-event-listener"); var _reactComponentRef = require("@fluentui/react-component-ref"); var customPropTypes = _interopRequireWildcard(require("@fluentui/react-proptypes")); var _reactBindings = require("@fluentui/react-bindings"); var _reactComponentNestingRegistry = require("@fluentui/react-component-nesting-registry"); var _utils = require("../../utils"); var _positioner = require("../../utils/positioner"); var _Box = require("../Box/Box"); var _Popup = require("../Popup/Popup"); var _ToolbarMenu = require("./ToolbarMenu"); var _ToolbarMenuItemIcon = require("./ToolbarMenuItemIcon"); var _toolbarVariablesContext = require("./toolbarVariablesContext"); var _ToolbarMenuItemSubmenuIndicator = require("./ToolbarMenuItemSubmenuIndicator"); var _ToolbarMenuItemActiveIndicator = require("./ToolbarMenuItemActiveIndicator"); var _toolbarMenuContext = require("./toolbarMenuContext"); var _ToolbarMenuItemContent = require("./ToolbarMenuItemContent"); var _reactIconsNorthstar = require("@fluentui/react-icons-northstar"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } var toolbarMenuItemClassName = 'ui-toolbar__menuitem'; exports.toolbarMenuItemClassName = toolbarMenuItemClassName; var toolbarMenuItemSlotClassNames = { wrapper: toolbarMenuItemClassName + "__wrapper", submenu: toolbarMenuItemClassName + "__submenu" }; /** * A ToolbarMenuItem renders ToolbarMenu item as button. */ exports.toolbarMenuItemSlotClassNames = toolbarMenuItemSlotClassNames; var ToolbarMenuItem = (0, _reactBindings.compose)(function (props, ref, composeOptions) { var context = (0, _reactBindings.useFluentContext)(); var _useTelemetry = (0, _reactBindings.useTelemetry)(composeOptions.displayName, context.telemetry), setStart = _useTelemetry.setStart, setEnd = _useTelemetry.setEnd; setStart(); var active = props.active, activeIndicator = props.activeIndicator, children = props.children, content = props.content, disabled = props.disabled, disabledFocusable = props.disabledFocusable, submenuIndicator = props.submenuIndicator, icon = props.icon, popup = props.popup, wrapper = props.wrapper, inSubmenu = props.inSubmenu, className = props.className, design = props.design, styles = props.styles, variables = props.variables; var _partitionPopperProps = (0, _positioner.partitionPopperPropsFromShorthand)(props.menu), menu = _partitionPopperProps[0], menuPositioningProps = _partitionPopperProps[1]; var _useAutoControlled = (0, _reactBindings.useAutoControlled)({ defaultValue: props.defaultMenuOpen, value: props.menuOpen, initialValue: false }), menuOpen = _useAutoControlled[0], setMenuOpen = _useAutoControlled[1]; var itemRef = React.useRef(); var menuRef = React.useRef(); var _ref = (0, _reactBindings.useContextSelectors)(_toolbarMenuContext.ToolbarMenuContext, { menuSlot: function menuSlot(v) { return v.slots.menu; } }), menuSlot = _ref.menuSlot; // TODO: we should improve typings for the useContextSelectors var parentVariables = React.useContext(_toolbarVariablesContext.ToolbarVariablesContext); var mergedVariables = (0, _reactBindings.mergeVariablesOverrides)(parentVariables, variables); var ElementType = (0, _reactBindings.getElementType)(props); var slotProps = composeOptions.resolveSlotProps(props); var unhandledProps = (0, _reactBindings.useUnhandledProps)(composeOptions.handledProps, props); var getA11yProps = (0, _reactBindings.useAccessibility)(props.accessibility, { debugName: composeOptions.displayName, mapPropsToBehavior: function mapPropsToBehavior() { return { hasMenu: !!menu, active: active, menuOpen: menuOpen, disabled: disabled, disabledFocusable: disabledFocusable, 'aria-label': props['aria-label'], 'aria-labelledby': props['aria-labelledby'], 'aria-describedby': props['aria-describedby'] }; }, actionHandlers: { performClick: function performClick(event) { event.preventDefault(); handleClick(event); }, openMenu: function openMenu(event) { return _openMenu(event); }, closeAllMenusAndFocusNextParentItem: function closeAllMenusAndFocusNextParentItem(event) { return _closeAllMenus(event); }, closeMenu: function closeMenu(event) { return _closeMenu(event); }, closeMenuAndFocusTrigger: function closeMenuAndFocusTrigger(event) { return _closeMenu(event); }, doNotNavigateNextParentItem: function doNotNavigateNextParentItem(event) { event.stopPropagation(); }, closeAllMenus: function closeAllMenus(event) { return _closeAllMenus(event); } }, rtl: context.rtl }); var _useStyles = (0, _reactBindings.useStyles)(composeOptions.displayName, { className: composeOptions.className, composeOptions: composeOptions, mapPropsToStyles: function mapPropsToStyles() { return { disabled: disabled, disabledFocusable: disabledFocusable, hasContent: !!content }; }, mapPropsToInlineStyles: function mapPropsToInlineStyles() { return { className: className, design: design, styles: styles, variables: mergedVariables }; }, rtl: context.rtl, unstable_props: props }), classes = _useStyles.classes, resolvedStyles = _useStyles.styles; var _openMenu = function _openMenu(e) { if (menu && !menuOpen) { trySetMenuOpen(true, e); e.stopPropagation(); e.preventDefault(); } }; var _closeMenu = function _closeMenu(e) { if (!isSubmenuOpen()) { return; } trySetMenuOpen(false, e, function () { (0, _reactBindings.focusAsync)(itemRef.current); }); e.stopPropagation(); }; var _closeAllMenus = function _closeAllMenus(e) { if (!isSubmenuOpen()) { return; } trySetMenuOpen(false, e, function () { if (!inSubmenu) { (0, _reactBindings.focusAsync)(itemRef.current); } }); // avoid spacebar scrolling the page if (!inSubmenu) { e.preventDefault(); } }; var isSubmenuOpen = function isSubmenuOpen() { return !!(menu && menuOpen); }; var trySetMenuOpen = function trySetMenuOpen(newValue, e, onStateChanged) { setMenuOpen(newValue); // The reason why post-effect is not passed as callback to trySetState method // is that in 'controlled' mode the post-effect is applied before final re-rendering // which cause a broken behavior: for e.g. when it is needed to focus submenu trigger on ESC. // TODO: all DOM post-effects should be applied at componentDidMount & componentDidUpdated stages. onStateChanged && onStateChanged(); (0, _invoke2.default)(props, 'onMenuOpenChange', e, Object.assign({}, props, { menuOpen: newValue })); }; var outsideClickHandler = function outsideClickHandler(getRefs) { return function (e) { var isItemClick = (0, _utils.doesNodeContainClick)(itemRef.current, e, context.target); var isNestedClick = (0, _some2.default)(getRefs(), function (childRef) { return (0, _utils.doesNodeContainClick)(childRef.current, e, context.target); }); var isInside = isItemClick || isNestedClick; if (!isInside) { trySetMenuOpen(false, e); } }; }; var handleMenuOverrides = function handleMenuOverrides(predefinedProps) { return { onItemClick: function onItemClick(e, itemProps) { var popup = itemProps.popup, menuOpen = itemProps.menuOpen; (0, _invoke2.default)(predefinedProps, 'onItemClick', e, itemProps); if (popup) { return; } trySetMenuOpen(menuOpen, e); if (!menuOpen) { (0, _invoke2.default)(itemRef.current, 'focus'); } } }; }; var handleClick = function handleClick(e) { if (disabled) { e.preventDefault(); return; } if (menu) { // the menuItem element was clicked => toggle the open/close and stop propagation trySetMenuOpen(!menuOpen, e); e.stopPropagation(); e.preventDefault(); } if (popup) { e.stopPropagation(); e.preventDefault(); return; } (0, _invoke2.default)(props, 'onClick', e, props); }; var element = /*#__PURE__*/React.createElement(ElementType, getA11yProps('root', Object.assign({ className: classes.root, onClick: handleClick, disabled: disabled, ref: ref }, unhandledProps)), (0, _utils.childrenExist)(children) ? children : /*#__PURE__*/React.createElement(React.Fragment, null, (0, _utils.createShorthand)(composeOptions.slots.icon, icon, { defaultProps: function defaultProps() { return slotProps.icon; } }), (0, _utils.createShorthand)(composeOptions.slots.content, content, { defaultProps: function defaultProps() { return getA11yProps('content', slotProps.content); } }), active && (0, _utils.createShorthand)(composeOptions.slots.activeIndicator, activeIndicator, { defaultProps: function defaultProps() { return slotProps.activeIndicator; } }), menu && (0, _utils.createShorthand)(composeOptions.slots.submenuIndicator, submenuIndicator, { defaultProps: function defaultProps() { return slotProps.submenuIndicator; } }))); var hasChildren = (0, _utils.childrenExist)(children); if (popup && !hasChildren) { var popupElement = (0, _utils.createShorthand)(composeOptions.slots.popup, popup, { defaultProps: function defaultProps() { return Object.assign({}, slotProps.popup, { onOpenChange: function onOpenChange(e) { e.stopPropagation(); } }); }, overrideProps: { trigger: element, children: undefined // force-reset `children` defined for `Popup` as it collides with the `trigger` } }); setEnd(); return popupElement; } var menuItemInner = hasChildren ? children : /*#__PURE__*/React.createElement(_reactComponentRef.Ref, { innerRef: itemRef }, element); var maybeSubmenu = menu && menuOpen ? /*#__PURE__*/React.createElement(_reactComponentNestingRegistry.Unstable_NestingAuto, null, function (getRefs, nestingRef) { return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_reactComponentRef.Ref, { innerRef: function innerRef(node) { nestingRef.current = node; menuRef.current = node; } }, /*#__PURE__*/React.createElement(_positioner.Popper, (0, _extends2.default)({ align: "top", position: context.rtl ? 'before' : 'after', targetRef: itemRef }, menuPositioningProps), /*#__PURE__*/React.createElement(_toolbarVariablesContext.ToolbarVariablesProvider, { value: mergedVariables }, (0, _utils.createShorthand)(composeOptions.slots.menu || menuSlot || _ToolbarMenu.ToolbarMenu, menu, { defaultProps: function defaultProps() { return Object.assign({ className: toolbarMenuItemSlotClassNames.submenu, styles: resolvedStyles.menu, submenu: true, submenuIndicator: submenuIndicator }, slotProps.menu); }, overrideProps: handleMenuOverrides })))), /*#__PURE__*/React.createElement(_reactComponentEventListener.EventListener, { capture: true, listener: outsideClickHandler(getRefs), target: context.target, type: "click" })); }) : null; if (!wrapper) { setEnd(); return menuItemInner; } var wrapperElement = _Box.Box.create(wrapper, { defaultProps: function defaultProps() { return getA11yProps('wrapper', { className: (0, _classnames.default)(toolbarMenuItemSlotClassNames.wrapper, classes.wrapper) }); }, overrideProps: function overrideProps() { return { children: /*#__PURE__*/React.createElement(React.Fragment, null, menuItemInner, maybeSubmenu) }; } }); setEnd(); return wrapperElement; }, { className: toolbarMenuItemClassName, displayName: 'ToolbarMenuItem', slots: { icon: _ToolbarMenuItemIcon.ToolbarMenuItemIcon, submenuIndicator: _ToolbarMenuItemSubmenuIndicator.ToolbarMenuItemSubmenuIndicator, activeIndicator: _ToolbarMenuItemActiveIndicator.ToolbarMenuItemActiveIndicator, popup: _Popup.Popup, content: _ToolbarMenuItemContent.ToolbarMenuItemContent }, slotProps: function slotProps(props) { return { icon: { hasContent: !!props.content }, submenuIndicator: { accessibility: _accessibility.indicatorBehavior }, activeIndicator: { accessibility: _accessibility.indicatorBehavior }, popup: { trapFocus: true }, content: {} }; }, shorthandConfig: { mappedProp: 'content' }, handledProps: ['accessibility', 'as', 'children', 'className', 'content', 'design', 'styles', 'variables', 'disabledFocusable', 'active', 'activeIndicator', 'defaultMenuOpen', 'disabled', 'icon', 'index', 'submenuIndicator', 'inSubmenu', 'menu', 'menuOpen', 'onClick', 'onMenuOpenChange', 'popup', 'wrapper'] }); exports.ToolbarMenuItem = ToolbarMenuItem; ToolbarMenuItem.propTypes = Object.assign({}, _utils.commonPropTypes.createCommon(), { active: PropTypes.bool, activeIndicator: customPropTypes.shorthandAllowingChildren, defaultMenuOpen: PropTypes.bool, disabled: PropTypes.bool, disabledFocusable: PropTypes.bool, icon: customPropTypes.shorthandAllowingChildren, index: PropTypes.number, submenuIndicator: customPropTypes.shorthandAllowingChildren, inSubmenu: PropTypes.bool, menu: PropTypes.oneOfType([customPropTypes.itemShorthand, customPropTypes.collectionShorthand]), menuOpen: PropTypes.bool, onClick: PropTypes.func, onMenuOpenChange: PropTypes.func, popup: PropTypes.oneOfType([PropTypes.shape(Object.assign({}, _Popup.Popup.propTypes, { trigger: customPropTypes.never, children: customPropTypes.never })), PropTypes.string]), wrapper: customPropTypes.itemShorthand }); ToolbarMenuItem.defaultProps = { as: 'button', accessibility: _accessibility.toolbarMenuItemBehavior, activeIndicator: {}, submenuIndicator: /*#__PURE__*/React.createElement(_reactIconsNorthstar.ChevronEndIcon, { outline: true }), wrapper: { as: 'li' } }; //# sourceMappingURL=ToolbarMenuItem.js.map