I am using sortable js
The issue occurs because the filterValue state you use for the search functionality applies a hidden class to the drag source items, but this hidden state affects the dropped items
"use client";
import {WEB_FUNC,SAP_FUNC,CONTROLS} from "./options";
Sortable.mount(new MultiDrag(), new Swap());
export default function Home() {
function addChildFunctions(evt:any) {
const draggedElement = evt.item.cloneNode(); // The dragged DOM element
evt.item.replaceWith(draggedElement)
if(!draggedElement) return;
const draggedIndex = draggedElement.getAttribute("data-el-id"); // Retrieve index
const draggedGroup = draggedElement.getAttribute("data-group"); // Retrieve index
const draggedData = CONTROLS.find(
(group ) => group.id == draggedGroup && group.items.find(item=>item.id==draggedIndex)?.hasChild
);
if (draggedData ) {
// Make the dropped element a drop container dynamically
const childContainer = document.createElement("ul");
childContainer.className = "dynamic-drop-area bg-blue-50 drop-area p-5";
draggedElement.appendChild(childContainer);
// Initialize Sortable on the new container
Sortable.create(childContainer, {
handle: ".drag-handle",
group: {
name: "shared",
pull: "clone",
},
forceFallback: true,
animation: 200,
sort: true,
multiDrag: true, // Enable multi-drag
selectedClass: "selected",
onAdd: addChildFunctions,
});
}
}
const dragElement = useRef([]);
const dropArea = useRef(null); // Single reference for the drop area
const searchInput = useRef([]);
useEffect(() => {
dragElement.current.forEach((a) =>
Sortable.create(a, {
animation: 200,
group: {
name: "shared",
pull: "clone",
put: false,
},
forceFallback: true,dragoverBubble: false,
sort: false,
})
);
if (dropArea.current) {
Sortable.create(dropArea.current, {
handle: ".drag-handle",
animation: 200,
group: {
name: "shared",
pull: false, // Drop area should not pull items
put: true, // Accept items
},
forceFallback: true,dragoverBubble: false,
sort: true,
multiDrag: true, // Enable multi-drag
selectedClass: "selected",
});
}
}, []);
const [filterValue,setFilterValue]=useState("");
return (
<>
<div className={ "flex flex-row "}>
<div className="basis-1/5 p-5 max-h-screen overflow-auto">
<div className="flex items-center rounded-md bg-white pl-3 outline outline-1 -outline-offset-1 outline-gray-300 has-[input:focus-within]:outline has-[input:focus-within]:outline-2 has-[input:focus-within]:-outline-offset-2 has-[input:focus-within]:outline-indigo-600">
<input type="text" name="price" id="price" onChange={()=>{
setFilterValue(searchInput.current.value)
}} ref={searchInput} className="block min-w-0 grow py-1.5 pl-1 pr-3 text-base text-gray-900 placeholder:text-gray-400 focus:outline focus:outline-0 sm:text-sm/6" placeholder="Search" />
</div>
{[...CONTROLS,...WEB_FUNC ] .map((group, index) => {
return (
<div className="border-b border-slate-200" key={group.id}>
<button
onClick={() => toggleAccordion(index)}
className="w-full flex justify-between items-center py-5
text-slate-800"
>
<span>{group.group}</span>
<span
id={"icon-" + index}
className="text-slate-800 transition-transform duration-300"
>
-
</span>
</button>
<div
id={"content-" + index}
className="open overflow-hidden transition-all duration-300 ease-in-out"
>
<div className="pb-5 text-sm text-slate-500 connect">
<ul ref={(el) => (dragElement.current[index] = el)}>
{
group.items.map((a, i) => (
<li
className={"gap-x-6 p-2 my-2 bg-gray-50 " + ((filterValue===""?"": a.label.toLowerCase().includes(filterValue?.toLowerCase?.())?"":"hidden"))}
data-el-id={a.id}
data-group={group.id}
key={group.id+"_"+a.id}
data-id={group.id+"_"+a.id}
>
<div className="flex px-2 items-center drag-handle">
{a?.icon}
<span className=" px-2">{a.label}</span>
</div>
</li>
))}
</ul>
</div>
</div>
</div>
);
})}
</div>
<ul
className="drop-area min-h-screen bg-red-50 basis-4/5 p-5"
ref={dropArea}
></ul>
</div>
</>
);
}
Initial state:
- drag source contains items like Item 1, Item 2, and Item 3.
- drop area contains Item 1 (dragged from the source).
Search action: - i search for Item 2.
- in the source list, only Item 2 is shown, and Item 1 and Item 3 are hidden by applying the hidden class.
Unexpected Behavior: - the hidden class is also applied to Item 1 in the drop area because it shares the same DOM attributes and filtering logic.