suomifi-ui-components
Version:
Suomi.fi UI component library
273 lines (270 loc) • 9.64 kB
JavaScript
import { __rest, __assign, __makeTemplateObject } 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, HtmlDiv } 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 './LanguageMenuPopover.baseStyles.js';
var baseClassName = 'fi-language-menu-popover';
var languageMenuPopoverClassNames = {
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),
LanguageMenuProvider = _a.Provider,
LanguageMenuConsumer = _a.Consumer;
var scrollItemList = function scrollItemList(elementId, wrapperRef) {
var _a, _b;
var wrapperOffsetPx = 10;
if (wrapperRef !== null && wrapperRef.current !== null) {
var elementOffsetTop = ((_a = document.getElementById(elementId)) === null || _a === void 0 ? void 0 : _a.offsetTop) || 0;
var elementOffsetHeight = ((_b = document.getElementById(elementId)) === null || _b === void 0 ? void 0 : _b.offsetHeight) || 0;
if (elementOffsetTop < wrapperRef.current.scrollTop) {
wrapperRef.current.scrollTop = elementOffsetTop - wrapperOffsetPx;
} else {
var offsetBottom = elementOffsetTop + elementOffsetHeight;
var scrollBottom = wrapperRef.current.scrollTop + wrapperRef.current.offsetHeight;
if (offsetBottom > scrollBottom) {
wrapperRef.current.scrollTop = offsetBottom - wrapperRef.current.offsetHeight + wrapperOffsetPx;
}
}
}
};
var BaseLanguageMenuPopover = function BaseLanguageMenuPopover(props) {
var _a;
var _b;
var openButtonRef = props.openButtonRef,
onClose = props.onClose,
className = props.className,
children = props.children,
menuId = props.menuId,
parentId = props.parentId,
initialActiveDescendant = props.initialActiveDescendant,
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 _f = useState(false),
preventScroll = _f[0],
setPreventScroll = _f[1];
var menuRef = useRef(null);
useEnhancedEffect(function () {
setMountNode(window.document.body);
}, []);
useEffect(function () {
if (isOpen) {
document.addEventListener('keydown', globalKeyDownHandler, {
capture: true
});
if (!preventScroll) {
scrollItemList("".concat(parentId, "-list-item-").concat(activeChild), menuRef);
}
return function () {
document.removeEventListener('keydown', globalKeyDownHandler, {
capture: true
});
};
}
}, [activeChild]);
useEffect(function () {
if (isOpen) {
document.addEventListener('click', globalClickHandler, {
capture: true
});
return function () {
document.removeEventListener('click', globalClickHandler, {
capture: true
});
};
}
}, [isOpen]);
useEffect(function () {
var isMounted = true;
setTimeout(function () {
if (isMounted) {
if (initialActiveDescendant === 'first') {
setActiveChild(0);
} else if (initialActiveDescendant === 'last') {
setActiveChild(React.Children.count(children) - 1);
}
}
}, 0);
return function () {
setActiveChild(-1);
isMounted = false;
};
}, [isOpen]);
var globalClickHandler = function globalClickHandler(nativeEvent) {
var _a, _b;
if (!((_a = menuRef.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 globalKeyDownHandler = function globalKeyDownHandler(event) {
setPreventScroll(false);
if (event.key === 'Escape') {
handleClose(true);
event.preventDefault();
}
if (event.key === 'Tab') {
handleClose(true);
}
var popoverItemsLength = React.Children.count(children);
var getNextIndex = function getNextIndex() {
return activeChild < popoverItemsLength - 1 ? activeChild + 1 : 0;
};
var getPreviousIndex = function getPreviousIndex() {
return activeChild !== 0 ? activeChild - 1 : popoverItemsLength - 1;
};
if (event.key === 'ArrowDown') {
event.preventDefault();
setActiveChild(getNextIndex());
}
if (event.key === 'ArrowUp') {
event.preventDefault();
setActiveChild(getPreviousIndex());
}
};
var defaultModifiers = [{
name: 'eventListeners',
enabled: isOpen
}, {
name: 'offset',
options: {
offset: [0, 15]
}
}, {
name: 'flip',
options: {
fallbackPlacements: ['top-end']
}
}, {
name: 'preventOverflow',
options: {
padding: 5
}
}];
var _g = usePopper(openButtonRef.current, dialogElement, {
strategy: 'fixed',
modifiers: defaultModifiers,
placement: 'bottom-end'
}),
styles = _g.styles,
attributes = _g.attributes;
var handleClose = function handleClose(moveFocus) {
onClose(moveFocus);
};
if (React.Children.count(children) < 1) {
getLogger().warn("LanguageMenu ".concat(menuId, " does not contain items"));
return null;
}
var itemMouseOver = function itemMouseOver(value) {
setActiveChild(value);
};
if (!mountNode) {
return null;
}
var menuItems = function menuItems(childs) {
return React.Children.map(childs, function (child, index) {
if ( /*#__PURE__*/React.isValidElement(child)) {
return /*#__PURE__*/React.cloneElement(child, {
itemIndex: index
});
}
return child;
});
};
return /*#__PURE__*/React.createElement(HtmlDivWithRef, {
className: classnames(className, baseClassName, (_a = {}, _a[languageMenuPopoverClassNames.hidden] = !isOpen, _a)),
style: styles.popper,
forwardedRef: setDialogElement
}, /*#__PURE__*/React.createElement(LanguageMenuProvider, {
value: {
onItemClick: function onItemClick() {
return handleClose(true);
},
onItemMouseOver: function onItemMouseOver(itemIndex) {
setPreventScroll(true);
itemMouseOver(itemIndex);
},
activeDescendantIndex: activeChild,
parentId: parentId || ''
}
}, /*#__PURE__*/React.createElement(HtmlDivWithRef, {
role: "menu",
id: menuId,
tabIndex: -1,
className: languageMenuPopoverClassNames.list,
forwardedRef: menuRef
}, menuItems(children))), /*#__PURE__*/React.createElement(HtmlDiv, {
className: languageMenuPopoverClassNames.popperArrow,
style: styles.arrow,
"data-popper-arrow": true,
"data-popper-placement": (_b = attributes.popper) === null || _b === void 0 ? void 0 : _b['data-popper-placement']
}));
};
var StyledLanguageMenuPopover = styled(function (_a) {
_a.theme;
var passProps = __rest(_a, ["theme"]);
return /*#__PURE__*/React.createElement(BaseLanguageMenuPopover, __assign({}, passProps));
}).withConfig({
componentId: "sc-1xc0eyf-0"
})(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n ", "\n"], ["\n ", "\n"])), function (_a) {
var theme = _a.theme;
return baseStyles(theme);
});
var LanguageMenuPopover = function LanguageMenuPopover(props) {
return /*#__PURE__*/React.createElement(SuomifiThemeConsumer, null, function (_a) {
var suomifiTheme = _a.suomifiTheme;
return /*#__PURE__*/React.createElement(StyledLanguageMenuPopover, __assign({
theme: suomifiTheme
}, props));
});
};
LanguageMenuPopover.displayName = 'LanguageMenuPopover';
var templateObject_1;
export { BaseLanguageMenuPopover, LanguageMenuConsumer, LanguageMenuPopover, LanguageMenuProvider, languageMenuPopoverClassNames };
//# sourceMappingURL=LanguageMenuPopover.js.map