umami/components/common/MenuButton.js

88 lines
2.1 KiB
JavaScript
Raw Normal View History

import { useState, useRef } from 'react';
import PropTypes from 'prop-types';
2020-09-21 06:31:53 +02:00
import classNames from 'classnames';
import Menu from 'components/common/Menu';
import useDocumentClick from 'hooks/useDocumentClick';
import styles from './MenuButton.module.css';
import { Button } from 'react-basics';
2020-09-21 06:31:53 +02:00
function MenuButton({
children,
2020-09-21 06:31:53 +02:00
value,
options,
2020-10-04 03:05:46 +02:00
buttonClassName,
2022-03-04 04:45:49 +01:00
buttonVariant,
2020-10-04 03:05:46 +02:00
menuClassName,
2020-09-21 06:31:53 +02:00
menuPosition = 'bottom',
menuAlign = 'right',
onSelect,
renderValue,
2021-11-04 23:55:12 +01:00
hideLabel,
2020-09-21 06:31:53 +02:00
}) {
const [showMenu, setShowMenu] = useState(false);
const ref = useRef();
const selectedOption = options.find(e => e.value === value);
function handleSelect(value) {
onSelect(value);
setShowMenu(false);
}
function toggleMenu() {
setShowMenu(state => !state);
}
useDocumentClick(e => {
2021-01-21 04:11:36 +01:00
if (!ref.current?.contains(e.target)) {
2020-09-21 06:31:53 +02:00
setShowMenu(false);
}
});
return (
<div className={styles.container} ref={ref}>
<Button
2020-10-04 03:05:46 +02:00
className={classNames(styles.button, buttonClassName, { [styles.open]: showMenu })}
2020-09-21 06:31:53 +02:00
onClick={toggleMenu}
2022-03-04 04:45:49 +01:00
variant={buttonVariant}
2020-09-21 06:31:53 +02:00
>
2021-11-04 23:55:12 +01:00
{!hideLabel && (
<div className={styles.text}>{renderValue ? renderValue(selectedOption) : value}</div>
)}
{children}
2020-09-21 06:31:53 +02:00
</Button>
{showMenu && (
<Menu
2020-10-04 03:05:46 +02:00
className={menuClassName}
2020-09-21 06:31:53 +02:00
options={options}
selectedOption={selectedOption}
onSelect={handleSelect}
float={menuPosition}
align={menuAlign}
/>
)}
</div>
);
}
MenuButton.propTypes = {
icon: PropTypes.node,
value: PropTypes.any,
options: PropTypes.arrayOf(
PropTypes.shape({
label: PropTypes.node,
value: PropTypes.any,
className: PropTypes.string,
render: PropTypes.func,
divider: PropTypes.bool,
}),
),
buttonClassName: PropTypes.string,
menuClassName: PropTypes.string,
menuPosition: PropTypes.oneOf(['top', 'bottom']),
menuAlign: PropTypes.oneOf(['left', 'right']),
onSelect: PropTypes.func,
renderValue: PropTypes.func,
};
export default MenuButton;