@primer/components
Version:
Primer react components
101 lines (97 loc) • 3.51 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import React, { useCallback, useEffect, useRef, useState } from 'react';
import styled from 'styled-components';
import { COMMON } from '../constants';
import sx from '../sx';
import useKeyboardNav from './hooks/useKeyboardNav';
import { MenuContext } from './SelectMenuContext';
import SelectMenuDivider from './SelectMenuDivider';
import SelectMenuFilter from './SelectMenuFilter';
import SelectMenuFooter from './SelectMenuFooter';
import SelectMenuHeader from './SelectMenuHeader';
import SelectMenuItem from './SelectMenuItem';
import SelectMenuList from './SelectMenuList';
import SelectMenuLoadingAnimation from './SelectMenuLoadingAnimation';
import SelectMenuModal from './SelectMenuModal';
import SelectMenuTab from './SelectMenuTab';
import SelectMenuTabPanel from './SelectMenuTabPanel';
import SelectMenuTabs from './SelectMenuTabs';
const wrapperStyles = `
// Remove marker added by the display: list-item browser default
> summary {
list-style: none;
}
// Remove marker added by details polyfill
> summary::before {
display: none;
}
// Remove marker added by Chrome
> summary::-webkit-details-marker {
display: none;
}
`;
const StyledSelectMenu = styled.details.withConfig({
displayName: "SelectMenu__StyledSelectMenu",
componentId: "i7h45b-0"
})(["", " ", " ", ";"], wrapperStyles, COMMON, sx);
// 'as' is spread out because we don't want users to be able to change the tag.
const SelectMenu = /*#__PURE__*/React.forwardRef(({
children,
initialTab = '',
as: _ignoredAs,
...rest
}, forwardedRef) => {
const backupRef = useRef(null);
const ref = forwardedRef !== null && forwardedRef !== void 0 ? forwardedRef : backupRef;
const [selectedTab, setSelectedTab] = useState(initialTab);
const [open, setOpen] = useState(false);
const menuProviderValues = {
selectedTab,
setSelectedTab,
setOpen,
open,
initialTab
};
const onClickOutside = useCallback(event => {
if ('current' in ref && ref.current && !ref.current.contains(event.target)) {
if (!event.defaultPrevented) {
setOpen(false);
}
}
}, [ref, setOpen]); // handles the overlay behavior - closing the menu when clicking outside of it
useEffect(() => {
if (open) {
document.addEventListener('click', onClickOutside);
return () => {
document.removeEventListener('click', onClickOutside);
};
}
}, [open, onClickOutside]);
function toggle(event) {
setOpen(event.target.open);
}
useKeyboardNav(ref, open, setOpen);
return /*#__PURE__*/React.createElement(MenuContext.Provider, {
value: menuProviderValues
}, /*#__PURE__*/React.createElement(StyledSelectMenu, _extends({
ref: ref
}, rest, {
open: open,
onToggle: toggle
}), children));
});
SelectMenu.displayName = 'SelectMenu';
export default Object.assign(SelectMenu, {
MenuContext,
List: SelectMenuList,
Divider: SelectMenuDivider,
Filter: SelectMenuFilter,
Footer: SelectMenuFooter,
Item: SelectMenuItem,
Modal: SelectMenuModal,
Tabs: SelectMenuTabs,
Tab: SelectMenuTab,
TabPanel: SelectMenuTabPanel,
Header: SelectMenuHeader,
LoadingAnimation: SelectMenuLoadingAnimation
});