suomifi-ui-components
Version:
Suomi.fi UI component library
297 lines (294 loc) • 10.3 kB
JavaScript
import { __rest, __assign, __makeTemplateObject, __spreadArray } from 'tslib';
import React, { useState, useRef, useEffect } from 'react';
import { styled } from 'styled-components';
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';
import { useFloating, offset, flip, shift, arrow, size, autoUpdate } from '@floating-ui/react-dom';
var baseClassName = 'fi-action-menu-popover';
var actionMenuClassNames = {
baseClassName: baseClassName,
hidden: "".concat(baseClassName, "--hidden"),
list: "".concat(baseClassName, "_list"),
floatinguiArrow: "".concat(baseClassName, "_floatingui-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 BaseActionMenuPopover = function BaseActionMenuPopover(props) {
var _a;
var _b, _c, _d;
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 _e = useState(null),
mountNode = _e[0],
setMountNode = _e[1];
var _f = useState(null),
dialogElement = _f[0],
setDialogElement = _f[1];
var _g = useState(-1),
activeChild = _g[0],
setActiveChild = _g[1];
var divRef = useRef(null);
var arrowRef = 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 _h = useFloating({
open: isOpen,
middleware: __spreadArray([offset(10), flip(), shift(), arrow({
element: arrowRef
})], fullWidth ? [size({
apply: function apply(_a) {
var rects = _a.rects,
elements = _a.elements;
var floatingElement = elements.floating;
floatingElement.style.width = "".concat(rects.reference.width, "px");
}
})] : [], true),
whileElementsMounted: autoUpdate,
placement: 'bottom-end'
}),
floatingUiRefs = _h.refs,
floatingStyles = _h.floatingStyles,
middlewareData = _h.middlewareData;
useEffect(function () {
if (openButtonRef.current) {
floatingUiRefs.setReference(openButtonRef.current);
}
}, [floatingUiRefs, openButtonRef]);
useEffect(function () {
if (dialogElement) {
floatingUiRefs.setFloating(dialogElement);
}
}, [floatingUiRefs, dialogElement]);
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: floatingStyles,
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(HtmlDivWithRef, {
forwardedRef: arrowRef,
className: actionMenuClassNames.floatinguiArrow,
"data-floatingui-placement": (_b = middlewareData === null || middlewareData === void 0 ? void 0 : middlewareData.offset) === null || _b === void 0 ? void 0 : _b.placement,
"aria-hidden": true,
style: {
position: 'absolute',
left: (_c = middlewareData.arrow) === null || _c === void 0 ? void 0 : _c.x,
top: (_d = middlewareData.arrow) === null || _d === void 0 ? void 0 : _d.y
}
}));
};
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