import { DndContext, PointerSensor, useSensor, useSensors } from "@dnd-kit/core"; import { restrictToVerticalAxis } from "@dnd-kit/modifiers"; import { arrayMove, SortableContext, verticalListSortingStrategy, useSortable } from "@dnd-kit/sortable"; import { memo, useEffect, useMemo, useRef, useState } from "@wordpress/element"; import { CSS } from "@dnd-kit/utilities"; import "./dnd-select.scss"; const SortableItem = memo((props) => { const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: props.id }); const style = { transform: CSS.Transform.toString(transform), transition: transition, }; const { item, onChange } = props; // Delete Icon const DeleteIcon = () => { return ( ); }; return ( <>
{/* Display the label of the item */} {item?.label} {/* Delete button */} onChange(item.id)} >
); }); const MultiSelectDndKit = ({ label = "", items, values, onChange, onInputChange = false, searchable = false }) => { const [allOptions, setAllOptions] = useState([]); const [toggleSelectField, setToggleSelectField] = useState(false); const [optionOpen, setOptionOpen] = useState(true); const [searchFieldData, setSearchFieldData] = useState(""); const dndRef = useRef(null); const containerRef = useRef(null); const allValues = useMemo(() => { if (!Array.isArray(values) || values.some(item => !item.value) ) {return []}; // prevents the crash return values.map(item => item.value); } , [values]); const sensors = useSensors( useSensor(PointerSensor, { activationConstraint: { distance: 5 }, }) ); // icons const ArrowIconOne = () => ( ); const ArrowIconTwo = () => ( ); const containerHeight = values?.length * 34 + 2 + "px"; const handleDragEnd = (event) => { setToggleSelectField(false); const { active, over } = event; if (active.id !== over.id) { const oldIndex = values.findIndex((i) => `${i.id}` === `${active.id}`); const newIndex = values.findIndex((i) => `${i.id}` === `${over.id}`); const updateValues = arrayMove(values, oldIndex, newIndex); onChange(updateValues); setOptionOpen(true); } }; const onDragStart = () => { setOptionOpen(false); setToggleSelectField(false); }; const handleRemoveItems = (id) => { const updatedValues = values?.filter((val) => val.id !== id); onChange(updatedValues); }; const toggleSelectFieldVal = () => { if (optionOpen) { setToggleSelectField((prev) => !prev); } }; const filterNotSelectedItems = (selectFieldItems) => { const result = selectFieldItems?.filter((item) => !allValues.includes(item.value)); return result; }; const handleSelectField = (data) => { // const { id, value, label, slug, order } = data; // const newValue = [ ...values, { id, value, label, slug, order } ]; const newValue = [...values, { ...data }]; setSearchFieldData(""); onChange(newValue); }; const handleSearchField = (event) => { const value = event.target.value.toLowerCase(); setSearchFieldData(value); const searchableArray = filterNotSelectedItems(items); const matchedOption = searchableArray?.filter((i) => i.label.toLowerCase().includes(value)); onInputChange ? onInputChange(value) : setAllOptions(matchedOption); }; useEffect(() => { let options = []; if (toggleSelectField) { options = filterNotSelectedItems(items); } else { options = [items]; } setAllOptions(options); }, [items, values, toggleSelectField]); useEffect(() => { const handleClickOutside = (event) => { if (containerRef.current && !containerRef.current.contains(event.target)) { setToggleSelectField(false); } }; if (toggleSelectField) { document.addEventListener("click", handleClickOutside); } return () => { document.removeEventListener("click", handleClickOutside); }; }, [toggleSelectField]); return (

{label}

`${item.id}`)} strategy={verticalListSortingStrategy} > {values?.map((item, index) => ( ))}
{toggleSelectField ? : }
{toggleSelectField && (
{searchable && ( handleSearchField(e)} className="sp-select-search-field" /> )} {allOptions?.length > 0 && allOptions?.map((option, i) => { return (
{option?.label && option?.value && (

handleSelectField(option)} className={`sp-select-option ${ values === option.value ? "selected" : "" }`} > {option.label}

)}
); })}
)}
); }; export default memo(MultiSelectDndKit);