import { ComponentType } from 'react' import ReactSelect, { components, GroupTypeBase, MultiValueProps, OptionTypeBase } from 'react-select' import { SortableContainer, SortableElement, SortableHandle, } from 'react-sortable-hoc' function arrayMove(array, from, to) { array = array.slice() array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]) return array } const SortableMultiValue = SortableElement(props => { // this prevents the menu from being opened/closed when the user clicks // on a value to begin dragging it. ideally, detecting a click (instead of // a drag) would still focus the control and toggle the menu, but that // requires some magic with refs that are out of scope for this example const onMouseDown = e => { e.preventDefault() e.stopPropagation() } const innerProps = { ...props.innerProps, onMouseDown } return }) const SortableMultiValueLabel = SortableHandle(props => ( )) const SortableSelect = SortableContainer(ReactSelect) const Select: React.FC = ({ placeholder, options, values, setValues, handleChange, handleTouch }) => { const onSortEnd = ({ oldIndex, newIndex }) => { const newValue = arrayMove(values, oldIndex, newIndex) setValues(newValue) } return node.getBoundingClientRect()} onSortEnd={onSortEnd} // select props styles={{ control: (provided) => { return { ...provided, border: 'none' } }, option: (provided) => { return { ...provided, cursor: 'pointer', ':hover': { opacity: '0.7' } } } }} isMulti className='border border-grey-light dark:border-transparent rounded' classNamePrefix='outline-none text-black dark:bg-very-black dark:text-white cursor-pointer ' placeholder={placeholder || '선택해주세요.'} options={options} onChange={handleChange} onBlur={handleTouch} noOptionsMessage={() => '검색 결과가 없습니다.'} value={values.map(el => ({ label: el, value: el}))} components={{ MultiValue: SortableMultiValue as ComponentType>>, MultiValueLabel: SortableMultiValueLabel, }} closeMenuOnSelect={false} /> } interface SelectProps { placeholder?: string options: Option[] values: string[] setValues: (value: string[]) => void handleChange: (value: Option[]) => void handleTouch: () => void } interface Option { value: string label: string } export default Select