UNPKG

@spaced-out/ui-design-system

Version:
171 lines (147 loc) 4.12 kB
// @flow strict import * as React from 'react'; import type {MenuClassNames, MenuLabelTooltip} from '../../types/menu'; import type {ClickAwayRefType} from '../../utils/click-away'; import { getSelectedKeysFromSelectedOption, getTextLabelFromSelectedKeys, } from '../../utils/menu'; import type {InputProps} from '../Input'; import type {MenuOption, MenuOptionsVariant, Virtualization} from '../Menu'; import type {ElevationType} from '../Tooltip'; import {Dropdown} from './Dropdown'; type ClassNames = $ReadOnly<{ wrapper?: string, box?: string, }>; export type SimpleDropdownRef = { selectedKeys?: Array<string>, }; export type SimpleDropdownProps = { // Input props ...InputProps, elevation?: ElevationType, classNames?: ClassNames, clickAwayRef?: ClickAwayRefType, // Menu props options?: Array<MenuOption>, optionsVariant?: MenuOptionsVariant, allowSearch?: boolean, selectedKeys?: Array<string>, isMenuFluid?: boolean, menuVirtualization?: Virtualization, header?: React.Node, footer?: React.Node, menuClassNames?: MenuClassNames, showLabelTooltip?: MenuLabelTooltip, allowWrap?: boolean, staticLabels?: { RESULT?: string, RESULTS?: string, SEARCH_PLACEHOLDER?: string, }, // events onChange?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed, onMenuOpen?: () => mixed, onMenuClose?: () => mixed, // Resolvers resolveLabel?: (option: MenuOption) => string | React.Node, resolveSecondaryLabel?: (option: MenuOption) => string | React.Node, ... }; const SimpleDropdownBase = (props: SimpleDropdownProps, ref) => { const { size = 'medium', classNames, placeholder = 'Select...', options, optionsVariant, allowSearch, selectedKeys, onChange, onMenuOpen, onMenuClose, resolveLabel, elevation = 'modal', menuVirtualization, resolveSecondaryLabel, isMenuFluid = true, header, footer, menuClassNames, showLabelTooltip, clickAwayRef, allowWrap = false, staticLabels, ...inputProps } = props; const [dropdownInputText, setDropdownInputText] = React.useState(''); const [dropdownSelectedKeys, setDropdownSelectedKeys] = React.useState(selectedKeys); React.useEffect(() => { const newDropdownText = getTextLabelFromSelectedKeys(selectedKeys, options); setDropdownSelectedKeys(selectedKeys); setDropdownInputText(newDropdownText); }, [selectedKeys]); const handleOptionChange = (selectedOption: MenuOption, e) => { e?.stopPropagation(); let newSelectedKeys = []; if (optionsVariant === 'checkbox') { newSelectedKeys = getSelectedKeysFromSelectedOption( selectedOption, dropdownSelectedKeys, ); } else { newSelectedKeys = [selectedOption.key]; } const newDropdownText = getTextLabelFromSelectedKeys( newSelectedKeys, options, ); setDropdownSelectedKeys(newSelectedKeys); setDropdownInputText(newDropdownText); setTimeout(() => { onChange?.(selectedOption, e); }); }; React.useImperativeHandle(ref, () => ({ selectedKeys: dropdownSelectedKeys, })); return ( <Dropdown {...inputProps} classNames={classNames} size={size} elevation={elevation} placeholder={placeholder} onChange={handleOptionChange} onMenuOpen={onMenuOpen} onMenuClose={onMenuClose} dropdownInputText={dropdownInputText} clickAwayRef={clickAwayRef} menu={{ options, selectedKeys: dropdownSelectedKeys, optionsVariant, allowSearch, resolveLabel, resolveSecondaryLabel, virtualization: menuVirtualization, size, isFluid: isMenuFluid, header, footer, classNames: menuClassNames, showLabelTooltip, allowWrap, staticLabels, }} /> ); }; export const SimpleDropdown: React.AbstractComponent< SimpleDropdownProps, SimpleDropdownRef, > = React.forwardRef<SimpleDropdownProps, SimpleDropdownRef>( SimpleDropdownBase, );