UNPKG

@i-novus/ui-core

Version:

Базовые UI компоненты

133 lines (132 loc) 5.75 kB
import { jsx as _jsx } from "react/jsx-runtime"; import { forwardRef, useCallback, useEffect, useState } from 'react'; import classNames from 'classnames'; import { useConfigProvider } from '../../core'; import { OptionList } from './components'; import { defaultOptions, noOption, noOptions } from './constants'; import { DropdownInput } from './DropdownInput'; import { MultipleSelector } from './MultipleSelector'; // FIXME: Требуется отсмотреть компоненту. Собрать корнер кейсы и провести рефакторинг. Внутри слишком много внутренних состояний. // eslint-disable-next-line sonarjs/cognitive-complexity export const InputSelect = forwardRef((props, ref) => { const { prefix, className, selectedInputValue = '', value, options = defaultOptions, onChange, onSearch, onOpen, onScroll, style, hasSearch = false, visible = true, multiple = false, disabled = false, emptyText, ...restProps } = props; const [dropdownOptions, setDropdownOptions] = useState(defaultOptions); const [selectedOptions, setSelectedOptions] = useState(defaultOptions); const [inputValue, setInputValue] = useState(selectedInputValue); const { getPrefix } = useConfigProvider(); const prefixCls = getPrefix(prefix); const onOptionClick = useCallback((newValue, event) => { setSelectedOptions(newValue); if (multiple) { // @ts-ignore onChange(newValue, event); } else { const [selectedOption] = newValue; if (selectedOption) { // @ts-ignore onChange(selectedOption, event); setInputValue(selectedOption.label); } } }, [multiple, onChange]); const onInputValueChange = useCallback((newValue, event) => { setInputValue(newValue); if (!newValue && !multiple) { setSelectedOptions([]); // @ts-ignore onChange?.(null, event); } if (hasSearch && onSearch) { // @ts-ignore onSearch(newValue, event); return; } if (!newValue) { setDropdownOptions(options); } else { const filteredOptions = options .filter(option => option.label.toLowerCase().includes(newValue.toLowerCase())); setDropdownOptions(filteredOptions.length ? filteredOptions : noOptions); } }, [hasSearch, multiple, onChange, onSearch, options]); const onCloseTag = useCallback((id, evt) => { setSelectedOptions((prev) => { const newSelectedOptions = prev.filter(item => item.id !== id); // @ts-ignore onChange?.(newSelectedOptions, evt); return newSelectedOptions; }); }, [onChange]); const onCloseDropdown = useCallback(() => { if (!inputValue) { return; } if ((!multiple && !selectedOptions.length) || multiple) { setInputValue(''); } else { const [selected] = selectedOptions; setInputValue(selected?.label || ''); } }, [multiple, inputValue, selectedOptions]); const handleOpen = useCallback((event) => { if (onOpen) { onOpen(event); } setDropdownOptions(options); }, [onOpen, options]); const handleClearAllSelectedOptions = useCallback((event) => { event.stopPropagation(); onInputValueChange(''); setSelectedOptions(defaultOptions); // @ts-ignore onChange?.(defaultOptions, event); }, [onInputValueChange, onChange]); useEffect(() => { if (Array.isArray(value)) { setSelectedOptions(value); } else if (value && typeof value === 'object' && 'label' in value) { setSelectedOptions([value]); setInputValue(value.label); } else { setSelectedOptions([]); setInputValue(''); } }, [value]); useEffect(() => { setDropdownOptions(options?.length ? options : [{ ...noOption, label: emptyText || noOption.label, }]); }, [emptyText, options]); if (!visible) { return null; } if (multiple) { return (_jsx("div", { className: classNames(className, `${prefixCls}-multiple-selector`), style: style, children: _jsx(MultipleSelector, { ...restProps, disabled: disabled, ref: ref, prefixCls: prefixCls, value: inputValue, onChange: onInputValueChange, onOpen: handleOpen, dropdownInnerComponent: OptionList, onClose: onCloseDropdown, dropdownInnerComponentProps: { options: dropdownOptions, selected: selectedOptions, onOptionClick, multiple, onScroll, }, tagListProps: { selectedOptions, onCloseTag, handleClearAllSelectedOptions, } }) })); } return (_jsx("div", { className: classNames(className, `${prefixCls}-input-select`), style: style, children: _jsx(DropdownInput, { ...restProps, disabled: disabled, ref: ref, prefixCls: prefixCls, value: inputValue, onChange: onInputValueChange, onOpen: handleOpen, dropdownInnerComponent: OptionList, onClose: onCloseDropdown, dropdownInnerComponentProps: { options: dropdownOptions, selected: selectedOptions, onOptionClick, multiple, onScroll, } }) })); }); InputSelect.displayName = 'InputSelect';