UNPKG

glass-app-manager

Version:

Informatica's Glass Framework CLI for bootstrapping

195 lines (174 loc) 6.27 kB
// @flow import * as React from "react"; import Downshift from "downshift/dist/downshift.cjs"; import { filterOptions } from "./utils"; type OptionDefinition = { text: string, value: any, }; type Options = Array<OptionDefinition>; type DownshiftWrapperProps = { onChange?: () => void, options: Options, placeholder?: string, search?: boolean, selectedItems?: any, setSelectedItem: OptionDefinition => void, setUserInput: boolean => void, setVisibleOptions: Options => void, }; export default function DownshiftWrapper(props: DownshiftWrapperProps) { const { inputValue, multiple, options, search, selectedItems, setInputValue, setSelectedItem, setUserInput, setVisibleOptions, } = props; const addItem = React.useCallback((itemArray, item) => { return [...itemArray, item]; }, []); const removeItem = React.useCallback((itemArray, item) => { return itemArray.filter(i => i !== item); }, []); const handleChange = React.useCallback( item => { if (multiple) { let prevSelectedItems = selectedItems; if (prevSelectedItems.includes(item)) { prevSelectedItems = removeItem(prevSelectedItems, item); } else { prevSelectedItems = addItem(prevSelectedItems, item); } setSelectedItem(prevSelectedItems); props.onChange(prevSelectedItems); } else { setSelectedItem(item); props.onChange(item); } }, [multiple, options, selectedItems, setSelectedItem] ); const handleInputValueChange = React.useCallback( (changes, downshiftState) => { switch (downshiftState.type) { case Downshift.stateChangeTypes.keyDownEscape: setUserInput(false); setVisibleOptions(options); if (multiple) { setInputValue(""); } else { setInputValue(changes); } break; case Downshift.stateChangeTypes.changeInput: if (search) { setVisibleOptions(filterOptions(options, changes)); } setUserInput(true); setInputValue(changes); break; default: } }, [filterOptions, options, setUserInput, setVisibleOptions] ); const handleOuterClick = React.useCallback( downshiftState => { if (multiple) { setInputValue(""); } else { setInputValue(downshiftState.selectedItem ? downshiftState.selectedItem.text : ""); } setUserInput(false); setVisibleOptions(options); }, [options, setInputValue, setUserInput, setVisibleOptions] ); const handleSelect = React.useCallback( item => { if (!multiple) { setInputValue(item.text); setUserInput(false); setVisibleOptions(options); } }, [multiple, options, setInputValue, setUserInput, setVisibleOptions] ); const handleStateChange = React.useCallback( (changes, state) => { let selectedItem = changes.selectedItem ? changes.selectedItem : state.selectedItem; if (changes.hasOwnProperty("isOpen")) { if (changes.isOpen) { props.onOpen && props.onOpen(selectedItem); } else { props.onClose && props.onClose(selectedItem); } } else if ( multiple && !state.isOpen && changes.type === Downshift.stateChangeTypes.controlledPropUpdatedSelectedItem ) { props.onClose && props.onClose(selectedItem); } }, [props.onOpen, props.onClose] ); const stateReducer = React.useCallback( (state, changes) => { switch (changes.type) { case Downshift.stateChangeTypes.changeInput: if (search) { return changes; } return { ...changes, highlightedIndex: options.findIndex(option => option.text.toUpperCase().includes(changes.inputValue.toUpperCase()) ), }; case Downshift.stateChangeTypes.clickItem: case Downshift.stateChangeTypes.keyDownEnter: if (multiple) { return { ...changes, highlightedIndex: state.highlightedIndex, isOpen: true, }; } return changes; default: return changes; } }, [multiple, options] ); const getStateAndHelpers = React.useCallback( downshift => { return { handleChange, ...downshift, }; }, [handleChange] ); const { render, children = render } = props; return ( <Downshift {...props} inputValue={inputValue} onChange={React.useCallback(e => handleChange(e), [handleChange])} onInputValueChange={handleInputValueChange} onOuterClick={handleOuterClick} onSelect={handleSelect} onStateChange={handleStateChange} selectedItem={selectedItems} stateReducer={stateReducer}> {downshift => children(getStateAndHelpers(downshift))} </Downshift> ); }