-
-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clone on drop / #106
Comments
@agotfredsen82 You got it; I will look into updating that example. |
Thanks from me, too! I'm looking to migrate from dndkit and I'll require cloning functionality. |
Just putting this rough hack of code from #8 that gets me some cloning. I'm sure I have adapted the code incorrectly but it's cloning. The biggest issue that I can see is that for some reason when I drag from the done back to the todos then I lose the DnD. I get a warning about the number of elements doesn't match the number expected but I can't see what I'm doing wrong. import {
type BaseDragState,
type DragState,
type NodeRecord,
type ParentRecord,
type SynthDragState,
dragValues,
parentValues,
parents,
setParentValues,
} from "@formkit/drag-and-drop";
import { useDragAndDrop } from "@formkit/drag-and-drop/react";
import { useState } from "react";
// Functions and plugins
const sourceTransfer = <T,>({
currentParent,
targetParent,
initialParent,
draggedNodes,
initialIndex,
state,
targetNode,
}: {
currentParent: ParentRecord<T>;
targetParent: ParentRecord<T>;
initialParent: ParentRecord<T>;
draggedNodes: Array<NodeRecord<T>>;
initialIndex: number;
state: BaseDragState<T> | DragState<T> | SynthDragState<T>;
targetNode?: NodeRecord<T>;
}) => {
const draggedValues = dragValues(state);
const initialParentValues = parentValues(
initialParent.el,
initialParent.data,
);
const newInitialValues = initialParentValues.filter(
(x) => !draggedValues.includes(x),
);
setParentValues(initialParent.el, initialParent.data, newInitialValues);
};
const findDuplicates = (values) => {
const uniqueElements = new Set();
const duplicates = [];
for (const item of values) {
if (uniqueElements.has(item)) {
duplicates.push(item);
} else {
uniqueElements.add(item);
}
}
return duplicates;
};
const targetTransfer = <T,>({
currentParent,
targetParent,
initialParent,
draggedNodes,
initialIndex,
state,
targetNode,
}: {
currentParent: ParentRecord<T>;
targetParent: ParentRecord<T>;
initialParent: ParentRecord<T>;
draggedNodes: Array<NodeRecord<T>>;
initialIndex: number;
state: BaseDragState<T> | DragState<T> | SynthDragState<T>;
targetNode?: NodeRecord<T>;
}) => {
const draggedValues = dragValues(state);
const targetData = targetParent.data;
const targetParentValues = parentValues(targetParent.el, targetParent.data);
const reset =
currentParent.el === initialParent.el &&
currentParent.data.config.sortable === false;
let targetIndex;
if ("node" in targetData) {
if (reset) {
targetIndex = initialIndex;
} else if (targetParent.data.config.sortable === false) {
targetIndex = targetParent.data.enabledNodes.length;
} else {
targetIndex = targetData.node.data.index;
}
targetParentValues.splice(targetIndex, 0, ...draggedValues);
} else {
targetIndex = reset ? initialIndex : targetParent.data.enabledNodes.length;
targetParentValues.splice(targetIndex, 0, ...draggedValues);
}
const duplicates = findDuplicates(targetParentValues);
for (const duplicate of duplicates) {
if (!("key" in duplicate) || typeof duplicate !== "object") continue;
const index = targetParentValues.indexOf(duplicate);
const newKey = `${duplicate.key}-${Math.random()
.toString(36)
.substring(2, 15)}`;
targetParentValues[index] = {
...targetParentValues[index],
key: newKey,
};
}
setParentValues(targetParent.el, targetParent.data, targetParentValues);
};
export const targetClone = (parent: HTMLElement) => {
const parentData = parents.get(parent);
if (!parentData) return;
return {
setup() {
parentData.config.performTransfer = targetTransfer;
},
};
};
export const sourceClone = (parent: HTMLElement) => {
const parentData = parents.get(parent);
if (!parentData) return;
return {
setup() {
parentData.config.performTransfer = sourceTransfer;
},
};
};
export function FormkitDnd() {
// Functions and plugins
// Initial todos and done values
const [initialTodos] = useState([
{
label: "Schedule perm",
key: "schedule-perm",
},
{
label: "Rewind VHS tapes",
key: "rewind-vhs",
},
{
label: "Make change for the arcade",
key: "make-change",
},
{
label: "Get disposable camera developed",
key: "disposable-camera",
},
{
label: "Learn C++",
key: "learn-cpp",
},
{
label: "Return Nintendo Power Glove",
key: "return-power-glove",
},
]);
const [todoList, todos] = useDragAndDrop(initialTodos, {
group: "todoList",
sortable: false,
plugins: [sourceClone],
});
const [doneValues] = useState([
{
label: "Pickup new mix-tape from Beth",
key: "mix-tape",
},
]);
const [doneList, dones] = useDragAndDrop(doneValues, {
group: "todoList",
plugins: [targetClone],
});
return (
<div>
<h2>Cloning example</h2>
<div className="group bg-slate-800">
<div className="kanban-board p-px grid grid-cols-2 gap-px text-slate-400">
<div className="kanban-column">
<h2 className="kanban-title">ToDos</h2>
<ul ref={todoList} className="kanban-list">
{todos.map((todo) => (
<li key={todo.key} className="kanban-item flex items-center">
{todo.label}
</li>
))}
</ul>
</div>
<div className="kanban-column ">
<h2 className="kanban-title">Complete</h2>
<ul ref={doneList} className="kanban-list border min-h-24">
{dones.map((done) => (
<li
key={done.key}
className="kanban-item kanban-complete flex items-center"
>
<span>{done.label}</span>
</li>
))}
</ul>
</div>
<pre style={{ fontSize: "10px", color: "white" }}>
{JSON.stringify(todos, null, 2)}
</pre>
<pre style={{ fontSize: "10px", color: "white" }}>
{JSON.stringify(dones, null, 2)}
</pre>
</div>
</div>
</div>
);
} |
Hi We love the new 2.0.2 works perfect ..
we used to use a solution similar to this #8
to do clone / copy instead of transfer .. but it does not work anymore with the latest update . is there any build in flag / solution to clone on drop instead of transfer ? or any plugin you haven't released yet that fix this ?
The text was updated successfully, but these errors were encountered: