UNPKG

@spaced-out/ui-design-system

Version:
168 lines (143 loc) 4.21 kB
// @flow strict import * as React from 'react'; import type {MenuClassNames, MenuLabelTooltip} from '../../types/menu'; import type {ClickAwayRefType} from '../../utils/click-away'; import { getButtonLabelFromSelectedKeys, getSelectedKeysFromSelectedOption, } from '../../utils/menu'; import type {ButtonProps} from '../Button'; import type {AnchorType} from '../ButtonDropdown'; import type {MenuOption, MenuOptionsVariant, Virtualization} from '../Menu'; import type {ElevationType} from '../Tooltip'; import {InlineDropdown} from './InlineDropdown'; type ClassNames = $ReadOnly<{ buttonWrapper?: string, dropdownContainer?: string, }>; export type SimpleInlineDropdownRef = { selectedKeys?: Array<string>, }; export type SimpleInlineDropdownProps = { // Input props ...ButtonProps, elevation?: ElevationType, classNames?: ClassNames, anchorPosition?: AnchorType, // Menu props options?: Array<MenuOption>, optionsVariant?: MenuOptionsVariant, allowSearch?: boolean, selectedKeys?: Array<string>, showLabelTooltip?: MenuLabelTooltip, allowWrap?: boolean, // events onOptionSelect?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed, onMenuOpen?: () => mixed, onMenuClose?: () => mixed, menuVirtualization?: Virtualization, header?: React.Node, footer?: React.Node, menuClassNames?: MenuClassNames, // Resolvers resolveLabel?: (option: MenuOption) => string | React.Node, resolveSecondaryLabel?: (option: MenuOption) => string | React.Node, clickAwayRef?: ClickAwayRefType, ... }; const SimpleInlineDropdownBase = (props: SimpleInlineDropdownProps, ref) => { const { size = 'medium', classNames, anchorPosition, options, optionsVariant, allowSearch, selectedKeys, onOptionSelect, onMenuOpen, onMenuClose, resolveLabel, resolveSecondaryLabel, children, isFluid, menuVirtualization, header, footer, menuClassNames, showLabelTooltip, clickAwayRef, allowWrap = false, elevation = 'modal', ...buttonProps } = props; const [btnText, setBtnText] = React.useState(''); const [inlineDropdownSelectedKeys, setInlineDropdownSelectedKeys] = React.useState(selectedKeys); React.useEffect(() => { const newBtnText = getButtonLabelFromSelectedKeys(selectedKeys, children); setInlineDropdownSelectedKeys(selectedKeys); setBtnText(newBtnText); }, [selectedKeys]); const handleOptionChange = (selectedOption: MenuOption, e) => { e?.stopPropagation(); let newSelectedKeys = []; if (optionsVariant === 'checkbox') { newSelectedKeys = getSelectedKeysFromSelectedOption( selectedOption, inlineDropdownSelectedKeys, ); } else { newSelectedKeys = [selectedOption.key]; } const newBtnText = getButtonLabelFromSelectedKeys( newSelectedKeys, children, ); setInlineDropdownSelectedKeys(newSelectedKeys); setBtnText(newBtnText); setTimeout(() => { onOptionSelect?.(selectedOption, e); }); }; React.useImperativeHandle(ref, () => ({ selectedKeys: inlineDropdownSelectedKeys, })); return ( <InlineDropdown {...buttonProps} anchorPosition={anchorPosition} classNames={classNames} size={size} onOptionSelect={handleOptionChange} onMenuOpen={onMenuOpen} onMenuClose={onMenuClose} clickAwayRef={clickAwayRef} elevation={elevation} menu={{ isFluid, options, selectedKeys: inlineDropdownSelectedKeys, optionsVariant, allowSearch, resolveLabel, resolveSecondaryLabel, size: size === 'extraSmall' ? 'small' : size, virtualization: menuVirtualization, header, footer, classNames: menuClassNames, showLabelTooltip, allowWrap, }} > {optionsVariant === 'checkbox' ? btnText : children} </InlineDropdown> ); }; export const SimpleInlineDropdown: React.AbstractComponent< SimpleInlineDropdownProps, SimpleInlineDropdownRef, > = React.forwardRef<SimpleInlineDropdownProps, SimpleInlineDropdownRef>( SimpleInlineDropdownBase, );