UNPKG

suomifi-ui-components

Version:
305 lines (302 loc) 10.1 kB
import { __rest, __assign, __makeTemplateObject, __spreadArray } from 'tslib'; import React, { useState, useRef, useEffect } from 'react'; import { styled } from 'styled-components'; import { usePopper } from 'react-popper'; import classnames from 'classnames'; import { useEnhancedEffect } from '../../../utils/common/common.js'; import { SuomifiThemeConsumer } from '../../theme/SuomifiThemeProvider/SuomifiThemeProvider.js'; import '../../theme/SuomifiTheme/SuomifiTheme.js'; import '../../theme/SpacingProvider/SpacingProvider.js'; import '../../../reset/HtmlA/HtmlA.js'; import '../../../reset/HtmlButton/HtmlButton.js'; import { HtmlDivWithRef } from '../../../reset/HtmlDiv/HtmlDiv.js'; import '../../../reset/HtmlFieldSet/HtmlFieldSet.js'; import '../../../reset/HtmlH/HtmlH.js'; import '../../../reset/HtmlInput/HtmlInput.js'; import '../../../reset/HtmlLabel/HtmlLabel.js'; import '../../../reset/HtmlLegend/HtmlLegend.js'; import '../../../reset/HtmlLi/HtmlLi.js'; import '../../../reset/HtmlNav/HtmlNav.js'; import '../../../reset/HtmlOl/HtmlOl.js'; import '../../../reset/HtmlSpan/HtmlSpan.js'; import '../../../reset/HtmlTextarea/HtmlTextarea.js'; import '../../../reset/HtmlUl/HtmlUl.js'; import '../../../reset/HtmlTable/HtmlTable.js'; import '../../../reset/HtmlTable/HtmlTableCaption.js'; import '../../../reset/HtmlTable/HtmlTableHeader.js'; import '../../../reset/HtmlTable/HtmlTableRow.js'; import '../../../reset/HtmlTable/HtmlTableBody.js'; import '../../../reset/HtmlTable/HtmlTableHeaderCell.js'; import '../../../reset/HtmlTable/HtmlTableCell.js'; import { getLogger } from '../../../utils/log/logger.js'; import { baseStyles } from './ActionMenuPopover.baseStyles.js'; var baseClassName = 'fi-action-menu-popover'; var actionMenuClassNames = { baseClassName: baseClassName, hidden: "".concat(baseClassName, "--hidden"), list: "".concat(baseClassName, "_list"), popperArrow: "".concat(baseClassName, "_popper-arrow") }; var defaultProviderValue = { onItemClick: function onItemClick() { return null; }, onItemMouseOver: function onItemMouseOver() { return null; }, activeDescendantIndex: -1, parentId: '' }; var _a = /*#__PURE__*/React.createContext(defaultProviderValue), ActionMenuProvider = _a.Provider, ActionMenuConsumer = _a.Consumer; var sameWidth = { name: 'sameWidth', enabled: true, phase: 'beforeWrite', requires: ['computeStyles'], fn: function fn(_a) { var state = _a.state; state.styles.popper.width = "".concat(state.rects.reference.width, "px"); }, effect: function effect(_a) { var state = _a.state; state.elements.popper.style.width = "".concat(state.elements.reference.offsetWidth, "px"); } }; var BaseActionMenuPopover = function BaseActionMenuPopover(props) { var _a; var _b; var openButtonRef = props.openButtonRef, onClose = props.onClose, className = props.className, children = props.children, menuId = props.menuId, buttonId = props.buttonId, initialActiveDescendant = props.initialActiveDescendant, fullWidth = props.fullWidth, isOpen = props.isOpen; var _c = useState(null), mountNode = _c[0], setMountNode = _c[1]; var _d = useState(null), dialogElement = _d[0], setDialogElement = _d[1]; var _e = useState(-1), activeChild = _e[0], setActiveChild = _e[1]; var divRef = useRef(null); useEnhancedEffect(function () { setMountNode(window.document.body); }, []); useEffect(function () { if (isOpen) { document.addEventListener('keydown', globalKeyDownHandler, { capture: true }); return function () { document.removeEventListener('keydown', globalKeyDownHandler, { capture: true }); }; } }, [isOpen]); useEffect(function () { if (isOpen) { document.addEventListener('click', globalClickHandler, { capture: true }); return function () { document.removeEventListener('click', globalClickHandler, { capture: true }); }; } }, [isOpen]); useEffect(function () { var isSubscribed = true; setTimeout(function () { if (isSubscribed) { if (initialActiveDescendant === 'first') { setActiveChild(0); } else if (initialActiveDescendant === 'last') { setActiveChild(React.Children.count(children) - 1); } } }, 0); return function () { setActiveChild(-1); isSubscribed = false; }; }, [isOpen]); var globalClickHandler = function globalClickHandler(nativeEvent) { var _a, _b; if (!((_a = divRef.current) === null || _a === void 0 ? void 0 : _a.contains(nativeEvent.target)) && !((_b = openButtonRef.current) === null || _b === void 0 ? void 0 : _b.contains(nativeEvent.target))) { handleClose(false); } }; var isActivable = function isActivable(child) { var _a; return ((_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName) === 'ActionMenuItem'; }; var nextActivable = function nextActivable(current) { var nextActivableIndex = -1; var firstActivableIndex = -1; var startFrom = 0; if (current) { startFrom = current; } React.Children.forEach(children, function (child, index) { if (isActivable(child) && firstActivableIndex === -1) { firstActivableIndex = index; } if (index > startFrom && isActivable(child) && nextActivableIndex === -1) { nextActivableIndex = index; } }); if (nextActivableIndex !== -1) { return nextActivableIndex; } return firstActivableIndex; }; var previousActivable = function previousActivable(current) { var result = -1; var lastActivable = -1; React.Children.forEach(children, function (child, index) { if (isActivable(child)) { lastActivable = index; } if (index < current && isActivable(child)) { result = index; } }); if (result !== -1) { return result; } return lastActivable; }; var globalKeyDownHandler = function globalKeyDownHandler(event) { if (event.key === 'Escape') { handleClose(true); event.preventDefault(); } if (event.key === 'Tab') { handleClose(true); } if (event.key === 'ArrowDown') { event.preventDefault(); setActiveChild(function (previous) { return nextActivable(previous); }); } if (event.key === 'ArrowUp') { event.preventDefault(); setActiveChild(function (previous) { return previousActivable(previous); }); } }; var defaultModifiers = [{ name: 'eventListeners', enabled: isOpen }, { name: 'offset', options: { offset: [0, 10] } }, { name: 'flip', options: { fallbackPlacements: ['top-end'] } }, { name: 'preventOverflow', options: { padding: 5 } }]; var _f = usePopper(openButtonRef.current, dialogElement, { strategy: 'fixed', modifiers: fullWidth ? __spreadArray(__spreadArray([], defaultModifiers, true), [sameWidth], false) : defaultModifiers, placement: 'bottom-end' }), styles = _f.styles, attributes = _f.attributes; var handleClose = function handleClose(moveFocus) { onClose(moveFocus); }; if (React.Children.count(children) < 1) { getLogger().warn("Action Menu does not contain items"); return null; } var menuItems = function menuItems(childs) { return React.Children.map(childs, function (child, index) { if ( /*#__PURE__*/React.isValidElement(child) && isActivable(child)) { return /*#__PURE__*/React.cloneElement(child, { itemIndex: index }); } return child; }); }; var itemMouseOver = function itemMouseOver(value) { setActiveChild(value); }; if (!mountNode) { return null; } return /*#__PURE__*/React.createElement(HtmlDivWithRef, { className: classnames(className, baseClassName, (_a = {}, _a[actionMenuClassNames.hidden] = !isOpen, _a)), style: styles.popper, forwardedRef: setDialogElement, tabIndex: -1, role: "none" }, /*#__PURE__*/React.createElement(ActionMenuProvider, { value: { onItemClick: function onItemClick() { return handleClose(true); }, onItemMouseOver: function onItemMouseOver(itemIndex) { itemMouseOver(itemIndex); }, activeDescendantIndex: activeChild, parentId: menuId } }, /*#__PURE__*/React.createElement(HtmlDivWithRef, { role: "menu", forwardedRef: divRef, id: menuId, "aria-labelledby": buttonId, tabIndex: -1, className: actionMenuClassNames.list }, menuItems(children))), /*#__PURE__*/React.createElement("div", { className: actionMenuClassNames.popperArrow, style: styles.arrow, "aria-hidden": true, tabIndex: -1, "data-popper-arrow": true, "data-popper-placement": (_b = attributes.popper) === null || _b === void 0 ? void 0 : _b['data-popper-placement'] })); }; var StyledActionMenuPopover = styled(function (_a) { _a.theme; var passProps = __rest(_a, ["theme"]); return /*#__PURE__*/React.createElement(BaseActionMenuPopover, __assign({}, passProps)); }).withConfig({ componentId: "sc-1cahlko-0" })(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n ", "\n"], ["\n ", "\n"])), function (_a) { var theme = _a.theme; return baseStyles(theme); }); var ActionMenuPopover = function ActionMenuPopover(props) { return /*#__PURE__*/React.createElement(SuomifiThemeConsumer, null, function (_a) { var suomifiTheme = _a.suomifiTheme; return /*#__PURE__*/React.createElement(StyledActionMenuPopover, __assign({ theme: suomifiTheme }, props)); }); }; ActionMenuPopover.displayName = 'ActionMenuPopover'; var templateObject_1; export { ActionMenuConsumer, ActionMenuPopover, ActionMenuProvider, BaseActionMenuPopover, actionMenuClassNames }; //# sourceMappingURL=ActionMenuPopover.js.map