Browse Source

Add drop zone to the sorter

pull/6200/head
mohamedsalem401 1 year ago
parent
commit
af52c81d9f
  1. 2
      packages/core/src/canvas/index.ts
  2. 76
      packages/core/src/utils/sorter/DropLocationDeterminer.ts
  3. 6
      packages/core/src/utils/sorter/types.ts

2
packages/core/src/canvas/index.ts

@ -499,7 +499,7 @@ export default class CanvasModule extends Module<CanvasConfig> {
* @return {Object} * @return {Object}
* @private * @private
*/ */
getMouseRelativeCanvas(ev: MouseEvent, opts: any) { getMouseRelativeCanvas(ev: MouseEvent | { clientX: number; clientY: number }, opts: any) {
const zoom = this.getZoomDecimal(); const zoom = this.getZoomDecimal();
const { top = 0, left = 0 } = this.getCanvasView().getPosition(opts) ?? {}; const { top = 0, left = 0 } = this.getCanvasView().getPosition(opts) ?? {};

76
packages/core/src/utils/sorter/DropLocationDeterminer.ts

@ -116,8 +116,10 @@ export class DropLocationDeterminer<T, NodeType extends SortableTreeNode<T>> ext
const { targetNode: lastTargetNode } = this.lastMoveData; const { targetNode: lastTargetNode } = this.lastMoveData;
this.eventHandlers.onMouseMove?.(mouseEvent); this.eventHandlers.onMouseMove?.(mouseEvent);
const { mouseXRelativeToContainer: mouseX, mouseYRelativeToContainer: mouseY } = const { mouseXRelative: mouseX, mouseYRelative: mouseY } = this.getMousePositionRelativeToContainer(
this.getMousePositionRelativeToContainer(mouseEvent); mouseEvent.clientX,
mouseEvent.clientY,
);
const targetNode = this.getTargetNode(mouseEvent); const targetNode = this.getTargetNode(mouseEvent);
const targetChanged = !targetNode?.equals(lastTargetNode); const targetChanged = !targetNode?.equals(lastTargetNode);
if (targetChanged) { if (targetChanged) {
@ -138,6 +140,8 @@ export class DropLocationDeterminer<T, NodeType extends SortableTreeNode<T>> ext
!placeholderDimensions.equals(this.lastMoveData.placeholderDimensions) || !placeholderDimensions.equals(this.lastMoveData.placeholderDimensions) ||
placement !== this.lastMoveData.placement; placement !== this.lastMoveData.placement;
if (placeHolderMoved) { if (placeHolderMoved) {
console.log('🚀 ~ DropLocationDeterminer<T, ~ handleMove ~ targetNode:', targetNode);
console.log('🚀 ~ DropLocationDeterminer<T, ~ handleMove ~ placeholderDimensions:', placeholderDimensions);
this.eventHandlers.onPlaceholderPositionChange?.(placeholderDimensions!, placement!); this.eventHandlers.onPlaceholderPositionChange?.(placeholderDimensions!, placement!);
} }
@ -257,6 +261,10 @@ export class DropLocationDeterminer<T, NodeType extends SortableTreeNode<T>> ext
*/ */
private getTargetNode(mouseEvent: MouseEvent): NodeType | undefined { private getTargetNode(mouseEvent: MouseEvent): NodeType | undefined {
this.cacheContainerPosition(this.containerContext.container); this.cacheContainerPosition(this.containerContext.container);
const { mouseXRelative, mouseYRelative } = this.getMousePositionRelativeToContainer(
mouseEvent.clientX,
mouseEvent.clientY,
);
// Get the element under the mouse // Get the element under the mouse
const mouseTargetEl = this.getMouseTargetElement(mouseEvent); const mouseTargetEl = this.getMouseTargetElement(mouseEvent);
@ -268,10 +276,10 @@ export class DropLocationDeterminer<T, NodeType extends SortableTreeNode<T>> ext
let hoveredNode = this.getOrCreateHoveredNode(hoveredModel); let hoveredNode = this.getOrCreateHoveredNode(hoveredModel);
// Get the drop position index based on the mouse position // Get the drop position index based on the mouse position
const { index } = this.getDropPosition(hoveredNode, mouseEvent.clientX, mouseEvent.clientY); const { index } = this.getDropPosition(hoveredNode, mouseXRelative, mouseYRelative);
// Determine the valid target node (or its valid parent) // Determine the valid target node (or its valid parent)
let targetNode = this.getValidParent(hoveredNode, index, mouseEvent.clientX, mouseEvent.clientY); let targetNode = this.getValidParent(hoveredNode, index, mouseXRelative, mouseYRelative);
return this.getOrReuseTargetNode(targetNode); return this.getOrReuseTargetNode(targetNode);
} }
@ -389,21 +397,44 @@ export class DropLocationDeterminer<T, NodeType extends SortableTreeNode<T>> ext
private getValidParent(targetNode: NodeType, index: number, mouseX: number, mouseY: number): NodeType | undefined { private getValidParent(targetNode: NodeType, index: number, mouseX: number, mouseY: number): NodeType | undefined {
if (!targetNode) return; if (!targetNode) return;
const positionNotChanged = targetNode.equals(this.lastMoveData.targetNode) && index === this.lastMoveData.index;
if (positionNotChanged) return targetNode; const lastTargetNode = this.lastMoveData.targetNode;
const targetNotChanged = targetNode.equals(lastTargetNode);
targetNode.nodeDimensions = targetNotChanged ? lastTargetNode.nodeDimensions! : this.getDim(targetNode.element!);
if (!targetNode.isWithinDropBounds(mouseX, mouseY)) {
return this.handleParentTraversal(targetNode, mouseX, mouseY);
}
const positionNotChanged = targetNotChanged && index === this.lastMoveData.index;
if (positionNotChanged) return lastTargetNode;
const canMove = this.sourceNodes.some((node) => targetNode.canMove(node, index)); const canMove = this.sourceNodes.some((node) => targetNode.canMove(node, index));
this.triggerDragValidation(canMove, targetNode); this.triggerDragValidation(canMove, targetNode);
if (canMove) return targetNode; if (canMove) return targetNode;
return this.handleParentTraversal(targetNode, mouseX, mouseY);
}
private handleParentTraversal(targetNode: NodeType, mouseX: number, mouseY: number): NodeType | undefined {
const parent = targetNode.getParent() as NodeType; const parent = targetNode.getParent() as NodeType;
if (!parent) return; if (!parent) return;
const indexInParent = this.getIndexInParent(parent, targetNode, targetNode.nodeDimensions!, mouseX, mouseY);
return this.getValidParent(parent, indexInParent, mouseX, mouseY);
}
private getIndexInParent(
parent: NodeType,
targetNode: NodeType,
nodeDimensions: Dimension,
mouseX: number,
mouseY: number,
) {
let indexInParent = parent?.indexOfChild(targetNode); let indexInParent = parent?.indexOfChild(targetNode);
const nodeDimensions = this.getDim(targetNode.element!);
nodeDimensions.dir = this.getDirection(targetNode.element!, parent.element!); nodeDimensions.dir = this.getDirection(targetNode.element!, parent.element!);
indexInParent = indexInParent + (nodeDimensions.determinePlacement(mouseX, mouseY) == 'after' ? 1 : 0); indexInParent = indexInParent + (nodeDimensions.determinePlacement(mouseX, mouseY) == 'after' ? 1 : 0);
return this.getValidParent(parent, indexInParent, mouseX, mouseY); return indexInParent;
} }
private triggerDragValidation(canMove: boolean, targetNode: NodeType) { private triggerDragValidation(canMove: boolean, targetNode: NodeType) {
@ -488,27 +519,26 @@ export class DropLocationDeterminer<T, NodeType extends SortableTreeNode<T>> ext
/** /**
* Gets the mouse position relative to the container, adjusting for scroll and canvas relative options. * Gets the mouse position relative to the container, adjusting for scroll and canvas relative options.
* *
* @param {MouseEvent} mouseEvent - The current mouse event.
* @return {{ mouseXRelativeToContainer: number, mouseYRelativeToContainer: number }} - The mouse X and Y positions relative to the container. * @return {{ mouseXRelativeToContainer: number, mouseYRelativeToContainer: number }} - The mouse X and Y positions relative to the container.
* @private * @private
*/ */
private getMousePositionRelativeToContainer(mouseEvent: MouseEvent): { private getMousePositionRelativeToContainer(
mouseXRelativeToContainer: number; mouseX: number,
mouseYRelativeToContainer: number; mouseY: number,
): {
mouseXRelative: number;
mouseYRelative: number;
} { } {
const { em } = this; let mouseYRelative = mouseY - this.containerOffset.top + this.containerContext.container.scrollTop;
let mouseYRelativeToContainer = let mouseXRelative = mouseX - this.containerOffset.left + this.containerContext.container.scrollLeft;
mouseEvent.pageY - this.containerOffset.top + this.containerContext.container.scrollTop;
let mouseXRelativeToContainer = if (this.positionOptions.canvasRelative) {
mouseEvent.pageX - this.containerOffset.left + this.containerContext.container.scrollLeft; const mousePos = this.em.Canvas.getMouseRelativeCanvas({ clientX: mouseX, clientY: mouseY }, { noScroll: 1 });
mouseXRelative = mousePos.x;
if (this.positionOptions.canvasRelative && !!em) { mouseYRelative = mousePos.y;
const mousePos = em.Canvas.getMouseRelativeCanvas(mouseEvent, { noScroll: 1 });
mouseXRelativeToContainer = mousePos.x;
mouseYRelativeToContainer = mousePos.y;
} }
return { mouseXRelativeToContainer, mouseYRelativeToContainer }; return { mouseXRelative, mouseYRelative };
} }
/** /**

6
packages/core/src/utils/sorter/types.ts

@ -26,6 +26,12 @@ export type DragSource<T> = DraggableContent & {
export type Placement = 'inside' | 'before' | 'after'; export type Placement = 'inside' | 'before' | 'after';
export type DroppableZoneConfig = {
ratio: number;
minDroppableDimension: number; // In px
maxUndroppableDimension: number; // In px
};
export enum DragDirection { export enum DragDirection {
Vertical = 'Vertical', Vertical = 'Vertical',
Horizontal = 'Horizontal', Horizontal = 'Horizontal',

Loading…
Cancel
Save