Skip to content

Commit

Permalink
wip on refactoring the way multi drag overrides core defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
sashamilenkovic committed Sep 17, 2024
1 parent 1e3691b commit 18929b3
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 60 deletions.
83 changes: 47 additions & 36 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,11 @@ export function setDragState<T>(
dragStateProps:
| (SynthDragStateProps & DragStateProps<T>)
| DragStateProps<T>
| undefined,
data: NodeDragEventData<T> | NodePointerEventData<T>
| undefined
): DragState<T> | SynthDragState<T> {
Object.assign(state, dragStateProps);

state.emit("dragStarted", { state, data });
//state.emit("dragStarted", state);

return state as DragState<T> | SynthDragState<T>;
}
Expand Down Expand Up @@ -146,7 +145,8 @@ export function dragAndDrop<T>({
config: {
dragDropEffect: "move",
dragEffectAllowed: "move",
dragImage: setDragImage,
draggedNodes,
dragImage,
deepCopyStyles: false,
handleKeydownNode,
handleKeydownParent,
Expand Down Expand Up @@ -214,12 +214,17 @@ export function dragAndDrop<T>({
remapNodes(parent, true);
}

function setDragImage(data: NodeDragEventData<any>) {
return data.targetData.node.el;
function dragImage<T>(
_draggedNode: NodeRecord<T>,
draggedNodes: Array<NodeRecord<T>>,
_data: ParentData<T>
) {
return draggedNodes[0].el;
}

export function dragStateProps<T>(
data: NodeDragEventData<T> | NodePointerEventData<T>,
draggedNodes: Array<NodeRecord<T>>,
nativeDrag = true
): DragStateProps<T> {
const { x, y } = eventCoordinates(data.e);
Expand Down Expand Up @@ -262,12 +267,7 @@ export function dragStateProps<T>(
el: data.targetData.node.el,
data: data.targetData.node.data,
},
draggedNodes: [
{
el: data.targetData.node.el,
data: data.targetData.node.data,
},
],
draggedNodes,
incomingDirection: undefined,
initialIndex: data.targetData.node.data.index,
initialParent: {
Expand Down Expand Up @@ -840,6 +840,10 @@ export function validateDragstart(data: NodeEventData<any>): boolean {
return !!data.targetData.parent.data.config.nativeDrag;
}

function draggedNodes<T>(data: NodeEventData<T>): Array<NodeRecord<T>> {
return [data.targetData.node];
}

export function handleDragstart<T>(
data: NodeDragEventData<T>,
_state: BaseDragState<T>
Expand All @@ -852,20 +856,22 @@ export function handleDragstart<T>(

const config = data.targetData.parent.data.config;

const originalZIndex = data.targetData.node.el.style.zIndex;
const nodes = config.draggedNodes(data);

console.log("dragstart");
//const originalZIndex = data.targetData.node.el.style.zIndex;

const dragState = initDrag(data);
const dragState = initDrag(data, nodes);

dragstartClasses(
data.targetData.node.el,
config.draggingClass,
config.dropZoneClass,
config.dragPlaceholderClass
);
for (const node of dragState.draggedNodes) {
dragstartClasses(
node.el,
config.draggingClass,
config.dropZoneClass,
config.dragPlaceholderClass
);
}

dragState.originalZIndex = originalZIndex;
//dragState.originalZIndex = originalZIndex;

if (config.onDragstart)
config.onDragstart({
Expand Down Expand Up @@ -912,8 +918,11 @@ export function dragstartClasses(
});
}

export function initDrag<T>(data: NodeDragEventData<T>): DragState<T> {
const dragState = setDragState(dragStateProps(data), data);
export function initDrag<T>(
data: NodeDragEventData<T>,
draggedNodes: Array<NodeRecord<T>>
): DragState<T> {
const dragState = setDragState(dragStateProps(data, draggedNodes));

data.e.stopPropagation();

Expand All @@ -922,15 +931,17 @@ export function initDrag<T>(data: NodeDragEventData<T>): DragState<T> {

data.e.dataTransfer.dropEffect = config.dragDropEffect;

console.log("config", config);

data.e.dataTransfer.effectAllowed = config.dragEffectAllowed;

const dragImage = config?.dragImage;

if (dragImage)
data.e.dataTransfer.setDragImage(
dragImage(data) || data.targetData.node.el,
dragImage(
data.targetData.node,
draggedNodes,
data.targetData.parent.data
) || data.targetData.node.el,
data.e.offsetX,
data.e.offsetY
);
Expand Down Expand Up @@ -1106,7 +1117,7 @@ export function handlePointermove<T>(
if (isNative || !synthNodePointerDown || !validateDragHandle(data)) return;

if (!isSynthDragState(state)) {
const synthDragState = initSyntheticDrag(data, state) as SynthDragState<T>;
const synthDragState = initSynthDrag(data, state) as SynthDragState<T>;

synthMove(data, synthDragState);

Expand All @@ -1132,10 +1143,13 @@ export function handlePointermove<T>(
synthMove(data, state as SynthDragState<T>);
}

function initSyntheticDrag<T>(
function initSynthDrag<T>(
data: NodePointerEventData<T>,
_state: BaseDragState<T>
): SynthDragState<T> {
// NEXT STEP HERE:
console.log("init synth drag");

const display = data.targetData.node.el.style.display;

const rect = data.targetData.node.el.getBoundingClientRect();
Expand Down Expand Up @@ -1171,13 +1185,10 @@ function initSyntheticDrag<T>(
contextmenu: noDefault,
});

const synthDragState = setDragState(
{
...dragStateProps(data, false),
...synthDragStateProps,
},
data
) as SynthDragState<T>;
const synthDragState = setDragState({
...dragStateProps(data, [data.targetData.node], false),
...synthDragStateProps,
}) as SynthDragState<T>;

return synthDragState;
}
Expand Down
80 changes: 73 additions & 7 deletions src/plugins/multiDrag/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import type {
SetupNodeData,
MultiDragConfig,
MultiDragParentConfig,
ParentConfig,
BaseDragState,
} from "../../types";

import {
parents,
initDrag,
dragstartClasses,
end,
state,
resetState,
Expand All @@ -40,14 +40,79 @@ export function multiDrag<T>(

return {
setup() {
state.on("dragStarted", multiDragConfig.dragStarted || dragStarted);
//state.on("dragStarted", multiDragConfig.dragStarted || dragStarted);

//multiDragParentConfig.handleDragstart =
// multiDragConfig.handleDragstart || handleDragstart;

//multiDragParentConfig.handlePointerdownNode =
// multiDragConfig.handlePointerdownNode || handlePointerdownNode;

multiDragParentConfig.dragImage = (
_draggedNode: NodeRecord<T>,
draggedNodes: Array<NodeRecord<T>>,
data: ParentData<T>
) => {
const wrapper = document.createElement("div");

draggedNodes.map((x: NodeRecord<T>) => {
const el = x.el.cloneNode(true) as Node;

copyNodeStyle(x.el, el, true);

addNodeClass([el], data.config.draggingClass);

if (el instanceof HTMLElement) el.style.pointerEvents = "none";

wrapper.append(el);

const { width } = draggedNodes[0].el.getBoundingClientRect();

wrapper.style.cssText = `
display: flex;
flex-direction: column;
width: ${width}px;
position: fixed;
pointer-events: none;
z-index: 9999;
left: -9999px
`;

return el;
});

document.body.append(wrapper);

return wrapper;
};

multiDragParentConfig.draggedNodes = (data: NodeEventData<T>) => {
const parentRecord = data.targetData.parent;

let selectedValues: Array<T> = [];

if (multiDragConfig.selectedValues) {
selectedValues = multiDragConfig.selectedValues(
parentRecord.data.getValues(parentRecord.el),
parentRecord.el
);
}

if (!selectedValues.length) return [data.targetData.node];

const selectedNodes = parentRecord.data.enabledNodes.filter((x) =>
selectedValues.includes(x.data.value)
);

if (
!selectedNodes.map((x) => x.el).includes(data.targetData.node.el)
) {
selectedNodes.unshift(data.targetData.node);
}

return selectedNodes;
};

multiDragParentConfig.handleEnd =
multiDragConfig.handleEnd || handleEnd;

Expand Down Expand Up @@ -156,6 +221,7 @@ export function handleDragstart<T>(

export function dragstart<T>(data: NodeDragEventData<T>, _state: DragState<T>) {
console.log("multi dragstart");
return;
const dragState = initDrag(data);
//const multiDragConfig = data.targetData.parent.data.config.multiDragConfig;

Expand Down Expand Up @@ -320,13 +386,13 @@ export function handleSelections<T>(
x: number,
y: number
) {
for (const child of data.targetData.parent.data.enabledNodes) {
if (child.el === state.draggedNode.el) continue;
//for (const child of data.targetData.parent.data.enabledNodes) {
// if (child.el === state.draggedNode.el) continue;

if (!selectedValues.includes(child.data.value)) continue;
// if (!selectedValues.includes(child.data.value)) continue;

state.draggedNodes.push(child);
}
// state.draggedNodes.push(child);
//}

const config = data.targetData.parent.data.config.multiDragConfig;

Expand Down
9 changes: 7 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ export interface ParentConfig<T> {
/**
* A function that returns the image to use for the drag operation.
*/
dragImage: (data: NodeDragEventData<T>) => HTMLElement;
dragImage: (
draggedNode: NodeRecord<T>,
draggedNodes: Array<NodeRecord<T>>,
data: ParentData<T>
) => HTMLElement;
/**
* A flag to disable dragability of all nodes in the parent.
*/
Expand All @@ -61,6 +65,7 @@ export interface ParentConfig<T> {
* A function that returns whether a given node is draggable.
*/
draggable?: (child: HTMLElement) => boolean;
draggedNodes: (data: NodeEventData<T>) => Array<NodeRecord<T>>;
/**
* The class to add to a node when it is being dragged.
*/
Expand Down Expand Up @@ -927,7 +932,7 @@ export interface MultiDragConfig<T> {
* Function to set which values of a given parent are "selected". This is
* called on dragstart or touchstart.
*/
selections?: (parentValues: Array<T>, parent: HTMLElement) => Array<T>;
selectedValues?: (parentValues: Array<T>, parent: HTMLElement) => Array<T>;
/**
* Class added when a node is being (touch) dragged.
*/
Expand Down
35 changes: 20 additions & 15 deletions tests/pages/multi-drag/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,43 @@
import { useDragAndDrop } from "../../../src/vue/index";
import { multiDrag, selections } from "../../../src";
const selectedValues: Ref<Array<string>> = ref([]);
const [parent, values] = useDragAndDrop(
["Apple", "Banana", "Orange", "Strawberry", "Pineapple", "Grapes"],
{
plugins: [
multiDrag({
selections: () => {
return ["Apple", "Banana"];
selectedValues: () => {
return selectedValues.value;
},
plugins: [
selections({
synthSelectedClass: "blue",
}),
],
// plugins: [
// selections({
// synthSelectedClass: "blue",
// }),
// ],
}),
],
}
);
onMounted(() => {
const el = document.getElementById("hello-world");
//el.addEventListener("click", () => {
// console.log("Hello world clicked");
//});
});
function selectValue(value: string) {
selectedValues.value = [...selectedValues.value, value];
}
</script>

<template>
<h2>Place Plugin</h2>
<h2>Multi drag plugin</h2>
<p id="hello-world">Hello world</p>
<div>
<ul ref="parent" class="list">
<li v-for="value in values" :id="value" :key="value" class="item">
<li
v-for="value in values"
:id="value"
:key="value"
class="item"
@click="selectValue(value)"
>
{{ value }}
</li>
</ul>
Expand Down

0 comments on commit 18929b3

Please sign in to comment.