import React, { useMemo, useState, useRef, useContext, createContext, useEffect, useLayoutEffect } from 'react'; import PropTypes from 'prop-types'; import { Combobox, ComboboxInput, ComboboxList, ComboboxOption, ComboboxPopover } from '@reach/combobox'; import '@reach/combobox/styles.css'; import matchSorter from 'match-sorter'; import { fire } from '@utils'; const Context = createContext(); function ComboMultipleDropdownList({ options, hiddenFieldId, selected, label, acceptNewValues = false }) { if (label == undefined) { label = 'Choisir une option'; } if (Array.isArray(options[0]) == false) { options = options.map((o) => [o, o]); } const inputRef = useRef(); const [term, setTerm] = useState(''); const [selections, setSelections] = useState(selected); const [newValues, setNewValues] = useState([]); const results = useMemo( () => (term ? matchSorter( options.filter((o) => !o[0].startsWith('--')), term ) : options ).filter((o) => o[0] && !selections.includes(o[1])), [term, selections] ); const hiddenField = useMemo( () => document.querySelector(`input[data-uuid="${hiddenFieldId}"]`), [hiddenFieldId] ); const handleChange = (event) => { setTerm(event.target.value); }; const onKeyDown = (event) => { if (event.key === 'Enter') { if (term && options.map((o) => o[0]).includes(term)) { event.preventDefault(); return onSelect(term); } if ( acceptNewValues && term && matchSorter( options.map((o) => o[0]), term ).length == 0 // ignore when was pressed for selecting popover option ) { event.preventDefault(); setNewValues([...newValues, term]); saveSelection([...selections, term]); setTerm(''); } } }; const saveSelection = (selections) => { setSelections(selections); if (hiddenField) { hiddenField.setAttribute('value', JSON.stringify(selections)); fire(hiddenField, 'autosave:trigger'); } }; const onSelect = (value) => { let sel = options.find((o) => o[0] == value)[1]; saveSelection([...selections, sel]); setTerm(''); }; const onRemove = (value) => { saveSelection( selections.filter((s) => newValues.includes(value) ? s != value : s !== options.find((o) => o[0] == value)[1] ) ); inputRef.current.focus(); }; return ( {results && ( {results.length === 0 && (

Aucun résultat{' '}

)} {results.map((value, index) => { if (value[0].startsWith('--')) { return ; } return ; })}
)}
); } function ComboboxTokenLabel({ onRemove, ...props }) { const selectionsRef = useRef([]); useLayoutEffect(() => { selectionsRef.current = []; return () => (selectionsRef.current = []); }); const context = { onRemove, selectionsRef }; return (
); } ComboboxTokenLabel.propTypes = { onRemove: PropTypes.func }; function ComboboxSeparator({ value }) { return (
  • {value.slice(2, -2)}
  • ); } ComboboxSeparator.propTypes = { value: PropTypes.string }; function ComboboxToken({ value, ...props }) { const { selectionsRef, onRemove } = useContext(Context); useEffect(() => { selectionsRef.current.push(value); }); return (
  • { if (event.key === 'Backspace') { onRemove(value); } }} {...props} > { onRemove(value); }} > x {value}
  • ); } ComboboxToken.propTypes = { value: PropTypes.string, label: PropTypes.string }; ComboMultipleDropdownList.propTypes = { options: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.string), PropTypes.arrayOf( PropTypes.arrayOf( PropTypes.oneOfType([PropTypes.string, PropTypes.number]) ) ) ]), hiddenFieldId: PropTypes.string, selected: PropTypes.arrayOf(PropTypes.string), arraySelected: PropTypes.arrayOf(PropTypes.array), label: PropTypes.string, acceptNewValues: PropTypes.bool }; export default ComboMultipleDropdownList;