UNPKG

@spaced-out/ui-design-system

Version:
165 lines (141 loc) 4.04 kB
// @flow strict import * as React from 'react'; import type {MenuClassNames, MenuLabelTooltip} from '../../types/menu'; import type {ClickAwayRefType} from '../../utils/click-away'; import {getTextLabelFromSelectedKeys} from '../../utils/menu'; import type {InputProps} from '../Input'; import type {MenuOption, Virtualization} from '../Menu'; import type {ElevationType} from '../Tooltip'; import {Typeahead} from './Typeahead'; type ClassNames = $ReadOnly<{ wrapper?: string, box?: string, }>; export type SimpleTypeaheadRef = { selectedKeys?: Array<string>, }; export type SimpleTypeaheadProps = { // Input props ...InputProps, isLoading?: boolean, menuOpenOffset?: number, classNames?: ClassNames, // Menu props options?: Array<MenuOption>, selectedKeys?: Array<string>, menuVirtualization?: Virtualization, header?: React.Node, footer?: React.Node, menuClassNames?: MenuClassNames, showLabelTooltip?: MenuLabelTooltip, allowWrap?: boolean, elevation?: ElevationType, // events onSelect?: (option: MenuOption, ?SyntheticEvent<HTMLElement>) => mixed, onSearch?: (evt: SyntheticInputEvent<HTMLInputElement>) => mixed, onMenuOpen?: () => mixed, onMenuClose?: () => mixed, onClear?: () => void, // Resolvers resolveLabel?: (option: MenuOption) => string | React.Node, resolveSecondaryLabel?: (option: MenuOption) => string | React.Node, clickAwayRef?: ClickAwayRefType, allowInternalFilter?: boolean, ... }; const SimpleTypeaheadBase = (props: SimpleTypeaheadProps, ref) => { const { size = 'medium', classNames, placeholder = 'Select...', options, selectedKeys, onSelect, onMenuOpen, onMenuClose, resolveLabel, resolveSecondaryLabel, onClear, onSearch, menuVirtualization, header, footer, menuClassNames, clickAwayRef, showLabelTooltip, allowInternalFilter = true, allowWrap = false, elevation = 'modal', ...inputProps } = props; const [typeaheadInputText, setTypeaheadInputText] = React.useState(''); const [typeaheadSelectedKeys, setTypeaheadSelectedKeys] = React.useState(selectedKeys); React.useEffect(() => { const newTypeaheadText = getTextLabelFromSelectedKeys( selectedKeys, options, ); setTypeaheadSelectedKeys(selectedKeys); setTypeaheadInputText(newTypeaheadText); }, [selectedKeys]); const handleOptionChange = (selectedOption: MenuOption, e) => { e?.stopPropagation(); const newSelectedKeys = [selectedOption.key]; const newTypeaheadText = getTextLabelFromSelectedKeys( newSelectedKeys, options, ); setTypeaheadSelectedKeys(newSelectedKeys); setTypeaheadInputText(newTypeaheadText); setTimeout(() => { onSelect?.(selectedOption, e); }); }; React.useImperativeHandle(ref, () => ({ selectedKeys: typeaheadSelectedKeys, })); return ( <Typeahead {...inputProps} allowInternalFilter={allowInternalFilter} classNames={classNames} size={size} placeholder={placeholder} onSelect={handleOptionChange} onMenuOpen={onMenuOpen} onMenuClose={onMenuClose} typeaheadInputText={typeaheadInputText} onSearch={(e) => { setTypeaheadInputText(e.target.value); onSearch?.(e); }} onClear={() => { setTypeaheadInputText(''); setTypeaheadSelectedKeys([]); onClear?.(); }} menu={{ options, selectedKeys: typeaheadSelectedKeys, resolveLabel, resolveSecondaryLabel, size, virtualization: menuVirtualization, header, footer, classNames: menuClassNames, showLabelTooltip, allowWrap, }} clickAwayRef={clickAwayRef} elevation={elevation} /> ); }; export const SimpleTypeahead: React.AbstractComponent< SimpleTypeaheadProps, SimpleTypeaheadRef, > = React.forwardRef<SimpleTypeaheadProps, SimpleTypeaheadRef>( SimpleTypeaheadBase, );