From 2bd54b62cafe39c07e160322992fabc4f2b239eb Mon Sep 17 00:00:00 2001 From: mohamedsalem401 Date: Sun, 22 Sep 2024 08:58:39 +0300 Subject: [PATCH] Refactor droplocationdeteminer and improve performance --- .../core/src/commands/view/SelectPosition.ts | 4 +- packages/core/src/navigator/view/ItemsView.ts | 4 +- .../core/src/style_manager/view/LayersView.ts | 4 +- packages/core/src/utils/Droppable.ts | 6 +- .../core/src/utils/sorter/ComponentSorter.ts | 14 +- .../utils/sorter/DropLocationDeterminer.ts | 228 +++++++++++++----- .../core/src/utils/sorter/PlaceholderClass.ts | 20 +- .../core/src/utils/sorter/SortableTreeNode.ts | 4 + packages/core/src/utils/sorter/Sorter.ts | 40 ++- packages/core/src/utils/sorter/SorterUtils.ts | 21 +- .../src/utils/sorter/StyleManagerSorter.ts | 5 +- packages/core/src/utils/sorter/types.ts | 20 +- 12 files changed, 226 insertions(+), 144 deletions(-) diff --git a/packages/core/src/commands/view/SelectPosition.ts b/packages/core/src/commands/view/SelectPosition.ts index 38957d375..647622bbb 100644 --- a/packages/core/src/commands/view/SelectPosition.ts +++ b/packages/core/src/commands/view/SelectPosition.ts @@ -1,6 +1,6 @@ import { $ } from '../../common'; import CanvasComponentNode from '../../utils/sorter/CanvasComponentNode'; -import { SorterDirection } from '../../utils/sorter/types'; +import { DragDirection } from '../../utils/sorter/types'; import { CommandObject } from './CommandAbstract'; export default { /** @@ -31,7 +31,7 @@ export default { canvasRelative: true, }, dragBehavior: { - dragDirection: SorterDirection.BothDirections, + dragDirection: DragDirection.BothDirections, nested: true, } }); diff --git a/packages/core/src/navigator/view/ItemsView.ts b/packages/core/src/navigator/view/ItemsView.ts index 9ed655cd4..087224612 100644 --- a/packages/core/src/navigator/view/ItemsView.ts +++ b/packages/core/src/navigator/view/ItemsView.ts @@ -5,7 +5,7 @@ import EditorModel from '../../editor/model/Editor'; import ItemView from './ItemView'; import Components from '../../dom_components/model/Components'; import LayerManager from '..'; -import { SorterDirection } from '../../utils/sorter/types'; +import { DragDirection } from '../../utils/sorter/types'; import LayersComponentNode from '../../utils/sorter/LayersComponentNode'; export default class ItemsView extends View { @@ -51,7 +51,7 @@ export default class ItemsView extends View { placeholderElement: this.placeholderElement }, dragBehavior: { - dragDirection: SorterDirection.Vertical, + dragDirection: DragDirection.Vertical, ignoreViewChildren: true, nested: true, } diff --git a/packages/core/src/style_manager/view/LayersView.ts b/packages/core/src/style_manager/view/LayersView.ts index 6730f6602..81addfb09 100644 --- a/packages/core/src/style_manager/view/LayersView.ts +++ b/packages/core/src/style_manager/view/LayersView.ts @@ -1,6 +1,6 @@ import { View } from '../../common'; import EditorModel from '../../editor/model/Editor'; -import { SorterDirection } from '../../utils/sorter/types'; +import { DragDirection } from '../../utils/sorter/types'; import Layer from '../model/Layer'; import Layers from '../model/Layers'; import LayerView from './LayerView'; @@ -46,7 +46,7 @@ export default class LayersView extends View { placeholderElement: this.placeholderElement }, dragBehavior: { - dragDirection: SorterDirection.Vertical, + dragDirection: DragDirection.Vertical, ignoreViewChildren: true, nested: true, }, diff --git a/packages/core/src/utils/Droppable.ts b/packages/core/src/utils/Droppable.ts index 1da1f4e18..e5befd3bc 100644 --- a/packages/core/src/utils/Droppable.ts +++ b/packages/core/src/utils/Droppable.ts @@ -3,7 +3,7 @@ import CanvasModule from '../canvas'; import { ObjectStrings } from '../common'; import EditorModel from '../editor/model/Editor'; import { getDocumentScroll, off, on } from './dom'; -import { SorterDirection } from './sorter/types'; +import { DragDirection } from './sorter/types'; import CanvasNewComponentNode from './sorter/CanvasNewComponentNode'; // TODO move in sorter @@ -158,7 +158,7 @@ export default class Droppable { dragStop = (cancel?: boolean) => dragger.stop(ev, { cancel }); dragContent = (cnt: any) => (content = cnt); } else { - const handleOnDrop = (targetNode: CanvasNewComponentNode | undefined, sourceNodes: CanvasNewComponentNode[], index: number): void => { + const handleOnDrop = (targetNode: CanvasNewComponentNode | undefined, sourceNodes: CanvasNewComponentNode[], index: number | undefined): void => { if (!targetNode) return const insertingTextableIntoText = targetNode.model?.isInstanceOf?.('text') && sourceNodes?.some(node => node.model?.get?.('textable')); let sourceModel; @@ -184,7 +184,7 @@ export default class Droppable { document: this.el.ownerDocument, }, dragBehavior: { - dragDirection: SorterDirection.BothDirections, + dragDirection: DragDirection.BothDirections, ignoreViewChildren: true, nested: true, }, diff --git a/packages/core/src/utils/sorter/ComponentSorter.ts b/packages/core/src/utils/sorter/ComponentSorter.ts index 538cebb03..4d33cc78c 100644 --- a/packages/core/src/utils/sorter/ComponentSorter.ts +++ b/packages/core/src/utils/sorter/ComponentSorter.ts @@ -42,7 +42,7 @@ export default class ComponentSorter extends Sorter { + onDrop: (targetNode: BaseComponentNode | undefined, sourceNodes: BaseComponentNode[], index: number | undefined) => { eventHandlers.onDrop?.(targetNode, sourceNodes, index); this.onDrop(targetNode, sourceNodes, index); }, @@ -58,7 +58,7 @@ export default class ComponentSorter extends Sorter { + private onMouseMove = (mouseEvent: MouseEvent) => { const insertingTextableIntoText = this.targetIsText && this.sourceNodes?.some(node => node.isTextable()) if (insertingTextableIntoText) { this.updateTextViewCursorPosition(mouseEvent); } } - onDrop = (targetNode: BaseComponentNode | undefined, sourceNodes: BaseComponentNode[], index: number) => { + private onDrop = (targetNode: BaseComponentNode | undefined, sourceNodes: BaseComponentNode[], index: number | undefined) => { if (!targetNode) return + index = typeof index === 'number' ? index : -1; const legacyOnEndMove = this.eventHandlers.legacyOnEndMove; const model = this.sourceNodes?.[0].model; const data = { @@ -101,7 +102,6 @@ export default class ComponentSorter extends Sorter this.em!.getZoomDecimal() - } } \ No newline at end of file diff --git a/packages/core/src/utils/sorter/DropLocationDeterminer.ts b/packages/core/src/utils/sorter/DropLocationDeterminer.ts index faf20b0c4..7d44120c8 100644 --- a/packages/core/src/utils/sorter/DropLocationDeterminer.ts +++ b/packages/core/src/utils/sorter/DropLocationDeterminer.ts @@ -4,36 +4,63 @@ import EditorModel from '../../editor/model/Editor'; import { isTextNode, off, on } from '../dom'; import { getModel } from '../mixins'; import { SortableTreeNode } from './SortableTreeNode'; -import { Dimension, Position, PositionOptions, SorterContainerContext, SorterDirection, SorterDragBehaviorOptions, SorterEventHandlers } from './types'; +import { Dimension, Placement, PositionOptions, DragDirection, SorterEventHandlers, CustomTarget } from './types'; import { bindAll, each } from 'underscore'; import { matches, findPosition, offset, isInFlow } from './SorterUtils'; +type ContainerContext = { + container: HTMLElement; + itemSel: string; + customTarget?: CustomTarget; +}; + interface DropLocationDeterminerOptions> { em: EditorModel; treeClass: new (model: T) => NodeType; - containerContext: SorterContainerContext; + containerContext: ContainerContext; positionOptions: PositionOptions; - dragBehavior: SorterDragBehaviorOptions; + dragDirection: DragDirection; eventHandlers: SorterEventHandlers; } +/** + * Represents the data related to the last move event during drag-and-drop sorting. + * This type is discriminated by the presence or absence of a valid target node. + */ +type LastMoveData = + | { + /** The target node under the mouse pointer during the last move. */ + lastTargetNode: NodeType; + /** The index where the placeholder or dragged element should be inserted. */ + lastIndex: number; + /** Placement relative to the target ('before' or 'after'). */ + lastPlacement: Placement; + /** The dimensions of the child elements within the target node. */ + lastChildrenDimensions: Dimension[]; + } + | { + /** Indicates that there is no valid target node. */ + lastTargetNode: undefined; + lastIndex: undefined; + lastPlacement: undefined; + lastChildrenDimensions: undefined; + }; + export class DropLocationDeterminer> extends View { em: EditorModel; treeClass: new (model: any) => NodeType; positionOptions: PositionOptions; - containerContext: SorterContainerContext; - dragBehavior: SorterDragBehaviorOptions; + containerContext: ContainerContext; + dragDirection: DragDirection; eventHandlers: SorterEventHandlers; - targetNode?: NodeType; - lastPos?: Position; - targetDimensions?: Dimension[]; - sourceNodes!: NodeType[]; - docs!: Document[]; - containerOffset: { - top: number; - left: number; + sourceNodes: NodeType[] = []; + lastMoveData!: LastMoveData; + docs: Document[] = []; + containerOffset = { + top: 0, + left: 0, } constructor(options: DropLocationDeterminerOptions) { @@ -42,13 +69,11 @@ export class DropLocationDeterminer> ext this.em = options.em; this.containerContext = options.containerContext; this.positionOptions = options.positionOptions; - this.dragBehavior = options.dragBehavior; + this.dragDirection = options.dragDirection; this.eventHandlers = options.eventHandlers || {}; bindAll(this, 'startSort', 'onDragStart', 'onMove', 'endDrag'); - this.containerOffset = { - top: 0, - left: 0 - }; + + this.restLastMoveData(); } /** @@ -66,51 +91,124 @@ export class DropLocationDeterminer> ext on(docs, 'mouseup dragend touchend', this.endDrag); } - onMove(mouseEvent: MouseEvent): void { + private onMove(mouseEvent: MouseEvent): void { this.eventHandlers.onMouseMove?.(mouseEvent); - const customTarget = this.containerContext.customTarget; - this.cacheContainerPosition(this.containerContext.container); - const { mouseXRelativeToContainer, mouseYRelativeToContainer } = this.getMousePositionRelativeToContainer(mouseEvent); - - let mouseTargetEl: HTMLElement | null = customTarget ? customTarget({ event: mouseEvent }) : mouseEvent.target as HTMLElement; - const targetEl = this.getFirstElementWithAModel(mouseTargetEl); - if (!targetEl) return - - const targetModel = $(targetEl)?.data("model"); - const mouseTargetNode = new this.treeClass(targetModel); - const targetNode = this.getValidParentNode(mouseTargetNode); + const { mouseXRelativeToContainer: mouseX, mouseYRelativeToContainer: mouseY } = this.getMousePositionRelativeToContainer(mouseEvent); + const targetNode = this.getTargetNode(mouseEvent); if (!targetNode) { this.eventHandlers.onPlaceholderPositionChange?.(false); - return + this.eventHandlers.onTargetChange?.(this.lastMoveData.lastTargetNode, undefined); + this.restLastMoveData(); + this.triggerMoveEvent(mouseX, mouseY); + + return; } - const dims = this.dimsFromTarget(targetNode); - const pos = findPosition(dims, mouseXRelativeToContainer, mouseYRelativeToContainer); - this.eventHandlers.onPlaceholderPositionChange?.(true, dims, pos); - this.eventHandlers.onTargetChange?.(this.targetNode, targetNode); - this.targetNode = targetNode; - this.lastPos = pos; - this.targetDimensions = dims; + // Handle movement over the valid target node + const index = this.handleMovementOnTarget(targetNode, mouseX, mouseY); + + this.triggerMoveEvent(mouseX, mouseY); + this.triggerLegacyOnMoveCallback(mouseEvent, index); + } + + private restLastMoveData() { + this.lastMoveData = { + lastTargetNode: undefined, + lastIndex: undefined, + lastPlacement: undefined, + lastChildrenDimensions: undefined, + }; + } - // For compatibility with old sorter + private triggerLegacyOnMoveCallback(mouseEvent: MouseEvent, index: number) { this.eventHandlers.legacyOnMoveClb?.({ event: mouseEvent, target: this.sourceNodes.map(node => node.model), - parent: this.targetNode.model, - index: pos.index + (pos.method == 'after' ? 1 : 0), + parent: this.lastMoveData.lastTargetNode?.model, + index: index, }); + } + + private triggerMoveEvent(mouseX: number, mouseY: number) { + const { lastTargetNode: targetNode, lastPlacement: placement, lastIndex: index, lastChildrenDimensions: childrenDimensions } = this.lastMoveData; + const legacyIndex = index ? (index + (placement === 'after' ? -1 : 0)) : 0; this.em.trigger('sorter:drag', { - target: targetEl, - targetModel, - sourceModel: this.sourceNodes.map(node => node.model), - dims, - pos, - x: mouseXRelativeToContainer, - y: mouseYRelativeToContainer, + target: targetNode?.element || null, + targetModel: this.lastMoveData.lastTargetNode?.model, + sourceModel: this.sourceNodes[0].model, + dims: childrenDimensions || [], + pos: { + index: legacyIndex, + indexEl: legacyIndex, + placement + }, + x: mouseX, + y: mouseY, }); } + /** + * Handles the movement of the dragged element over a target node. + * Updates the placeholder position and triggers relevant events when necessary. + * + * @param hoveredNode - The node currently being hovered over. + * @param mouseX - The x-coordinate of the mouse relative to the container. + * @param mouseY - The y-coordinate of the mouse relative to the container. + * @returns The index at which the placeholder should be positioned. + */ + private handleMovementOnTarget(hoveredNode: NodeType, mouseX: number, mouseY: number): number { + const { lastTargetNode, lastChildrenDimensions } = this.lastMoveData; + + const targetChanged = !hoveredNode.equals(lastTargetNode); + + this.eventHandlers.onTargetChange?.(lastTargetNode, hoveredNode); + + const childrenDimensions = targetChanged ? this.dimsFromTarget(hoveredNode) : lastChildrenDimensions!; + let { index, placement } = findPosition(childrenDimensions, mouseX, mouseY); + const elementDimension = childrenDimensions[index]; + index = index + (placement == 'after' ? 1 : 0); + + if (this.hasDropPositionChanged(targetChanged, index, placement)) { + this.eventHandlers.onPlaceholderPositionChange?.(true, elementDimension, placement); + } + + this.lastMoveData = { + lastTargetNode: hoveredNode, + lastChildrenDimensions: childrenDimensions, + lastIndex: index, + lastPlacement: placement, + }; + + return index; + } + + /** + * Checks if the drop position has changed. + * + * @param targetChanged - Whether the target node has changed. + * @param newIndex - The new index for the placeholder. + * @param newPlacement - The new placement for the placeholder. + * @returns Whether the drop position has changed. + */ + private hasDropPositionChanged(targetChanged: boolean, newIndex: number, newPlacement: Placement): boolean { + const { lastIndex, lastPlacement } = this.lastMoveData; + return targetChanged || lastIndex !== newIndex || lastPlacement !== newPlacement; + } + + private getTargetNode(mouseEvent: MouseEvent) { + const customTarget = this.containerContext.customTarget; + this.cacheContainerPosition(this.containerContext.container); + + let mouseTargetEl: HTMLElement | null = customTarget ? customTarget({ event: mouseEvent }) : mouseEvent.target as HTMLElement; + const targetEl = this.getFirstElementWithAModel(mouseTargetEl); + if (!targetEl) return + const targetModel = $(targetEl)?.data("model"); + const mouseTargetNode = new this.treeClass(targetModel); + const targetNode = this.getValidParentNode(mouseTargetNode); + return targetNode; + } + private onDragStart(mouseEvent: MouseEvent): void { this.eventHandlers.onDragStart && this.eventHandlers.onDragStart(mouseEvent); } @@ -121,7 +219,8 @@ export class DropLocationDeterminer> ext } cancelDrag() { - this.eventHandlers.onTargetChange?.(this.targetNode, undefined); + const { lastTargetNode } = this.lastMoveData; + this.eventHandlers.onTargetChange?.(lastTargetNode, undefined); this.finalizeMove(); } @@ -132,36 +231,31 @@ export class DropLocationDeterminer> ext } private dropDragged() { - const targetNode = this.targetNode; - const lastPos = this.lastPos; - let index = -1; - if (lastPos) { - index = lastPos.method === 'after' ? lastPos.indexEl + 1 : lastPos.indexEl; - } - - this.eventHandlers.onDrop?.(targetNode, this.sourceNodes, index); + const { lastTargetNode, lastIndex } = this.lastMoveData; + this.eventHandlers.onDrop?.(lastTargetNode, this.sourceNodes, lastIndex); } private triggerOnDragEndEvent() { - const targetNode = this.targetNode; - const lastPos = this.lastPos; + const { lastTargetNode: targetNode } = this.lastMoveData; + + // For backward compatibility, leave it to a single node + const sourceNode = this.sourceNodes[0]; this.em.trigger('sorter:drag:end', { - targetCollection: this.targetNode ? this.targetNode.getChildren() : null, - modelToDrop: this.sourceNodes.map(node => node.model), + targetCollection: targetNode ? targetNode.getChildren() : null, + modelToDrop: sourceNode.model, warns: [''], validResult: { result: true, src: this.sourceNodes.map(node => node.element), - srcModel: this.sourceNodes.map(node => node.model), + srcModel: sourceNode.model, trg: targetNode?.element, trgModel: targetNode?.model, draggable: true, droppable: true, }, dst: targetNode?.element, - srcEl: this.sourceNodes.map(node => node.element), + srcEl: sourceNode.element, }); - return { lastPos, targetNode }; } /** @@ -255,11 +349,11 @@ export class DropLocationDeterminer> ext // TODO const dim = this.getDim(el, containerOffset.left, containerOffset.top, this.positionOptions.relative!, !!this.positionOptions.canvasRelative, this.positionOptions.windowMargin!, this.em); - let dir = this.dragBehavior.dragDirection; + let dir = this.dragDirection; let dirValue: boolean; - if (dir === SorterDirection.Vertical) dirValue = true; - else if (dir === SorterDirection.Horizontal) dirValue = false; + if (dir === DragDirection.Vertical) dirValue = true; + else if (dir === DragDirection.Horizontal) dirValue = false; else dirValue = isInFlow(el, targetElement); dim.dir = dirValue; diff --git a/packages/core/src/utils/sorter/PlaceholderClass.ts b/packages/core/src/utils/sorter/PlaceholderClass.ts index b52a1be24..17f3f2650 100644 --- a/packages/core/src/utils/sorter/PlaceholderClass.ts +++ b/packages/core/src/utils/sorter/PlaceholderClass.ts @@ -1,5 +1,5 @@ import { View } from '../../common'; -import { Dimension, Position } from './types'; +import { Dimension, Placement } from './types'; export class PlaceholderClass extends View { pfx: string; @@ -41,13 +41,12 @@ export class PlaceholderClass extends View { /** * Updates the position of the placeholder. - * @param {Dimension[]} elementsDimension Array of element dimensions. - * @param {Position} position Object representing position details (index and method). - * @param {Dimension} [targetDimension] Optional target dimensions ([top, left, height, width]). + * @param {Dimension} elementDimension element dimensions. + * @param {Position} placement either before or after the target. */ move( - elementsDimension: Dimension[], - position: Position, + elementDimension: Dimension, + placement: Placement, ) { const marginOffset = 0; const unit = 'px'; @@ -55,12 +54,7 @@ export class PlaceholderClass extends View { let left = 0; let width = ''; let height = ''; - - const { method, index } = position; - const elementDimension = elementsDimension[index]; - this.setOrientation(elementDimension); - const { top: elTop, left: elLeft, height: elHeight, width: elWidth, dir } = elementDimension; if (!dir) { @@ -68,13 +62,13 @@ export class PlaceholderClass extends View { width = 'auto'; height = (elHeight - marginOffset * 2) + unit; top = elTop + marginOffset; - left = method === 'before' ? elLeft - marginOffset : elLeft + elWidth - marginOffset; + left = placement === 'before' ? elLeft - marginOffset : elLeft + elWidth - marginOffset; this.setToVertical(); } else { width = elWidth + unit; height = 'auto'; - top = method === 'before' ? elTop - marginOffset : elTop + elHeight - marginOffset; + top = placement === 'before' ? elTop - marginOffset : elTop + elHeight - marginOffset; left = elLeft; } diff --git a/packages/core/src/utils/sorter/SortableTreeNode.ts b/packages/core/src/utils/sorter/SortableTreeNode.ts index a8bdc83a6..f92a3aec0 100644 --- a/packages/core/src/utils/sorter/SortableTreeNode.ts +++ b/packages/core/src/utils/sorter/SortableTreeNode.ts @@ -79,4 +79,8 @@ export abstract class SortableTreeNode { get model(): T { return this._model; } + + equals(node?: SortableTreeNode): boolean { + return !!node?._model && this._model === node._model; + } } diff --git a/packages/core/src/utils/sorter/Sorter.ts b/packages/core/src/utils/sorter/Sorter.ts index 6597de8ea..b9a9d5929 100644 --- a/packages/core/src/utils/sorter/Sorter.ts +++ b/packages/core/src/utils/sorter/Sorter.ts @@ -6,7 +6,7 @@ import { SortableTreeNode } from './SortableTreeNode'; import { DropLocationDeterminer } from './DropLocationDeterminer'; import { PlaceholderClass } from './PlaceholderClass'; import { getMergedOptions, getDocument, matches, closest } from './SorterUtils'; -import { SorterContainerContext, PositionOptions, SorterDragBehaviorOptions, SorterEventHandlers, Dimension, Position, OnPlaceholderPositionChangeHandler } from './types'; +import { SorterContainerContext, PositionOptions, SorterDragBehaviorOptions, SorterEventHandlers, Dimension, OnPlaceholderPositionChangeHandler, Placement } from './types'; import { SorterOptions } from './types'; export type RequiredEmAndTreeClassPartialSorterOptions> = Partial> & { @@ -29,7 +29,7 @@ export default class Sorter> { constructor(sorterOptions: SorterOptions) { const mergedOptions = getMergedOptions(sorterOptions); - bindAll(this, 'startSort', 'cancelDrag', 'rollback', 'updateOffset'); + bindAll(this, 'startSort', 'cancelDrag', 'rollback', 'updateOffset', 'handlePlaceholderMove'); this.containerContext = mergedOptions.containerContext; this.positionOptions = mergedOptions.positionOptions; this.dragBehavior = mergedOptions.dragBehavior; @@ -41,36 +41,34 @@ export default class Sorter> { this.em.on(this.em.Canvas.events.refresh, this.updateOffset); this.placeholder = this.createPlaceholder(); - const onPlaceholderPositionChange = this.handlePlaceholderMove().bind(this) as OnPlaceholderPositionChangeHandler; - this.dropLocationDeterminer = new DropLocationDeterminer({ em: this.em, treeClass: this.treeClass, containerContext: this.containerContext, positionOptions: this.positionOptions, - dragBehavior: this.dragBehavior, + dragDirection: this.dragBehavior.dragDirection, eventHandlers: { ...this.eventHandlers, - onPlaceholderPositionChange + onPlaceholderPositionChange: this.handlePlaceholderMove as OnPlaceholderPositionChangeHandler }, }); } - private handlePlaceholderMove() { - return ( - show: boolean, - dims: Dimension[], - newPosition: Position) => { - if (show) { - this.ensurePlaceholderElement(); - this.placeholder.show(); - this.updatePlaceholderPosition(dims, newPosition); - } else { - this.placeholder.hide(); - } - }; + private handlePlaceholderMove( + show: boolean, + elementDimension: Dimension, + placement: Placement, + ) { + if (show) { + this.ensurePlaceholderElement(); + this.placeholder.show(); + this.updatePlaceholderPosition(elementDimension, placement); + } else { + this.placeholder.hide(); + } } + /** * Creates a new placeholder element for the drag-and-drop operation. * @@ -157,8 +155,8 @@ export default class Sorter> { this.dropLocationDeterminer.updateDocs(docs); } - private updatePlaceholderPosition(dims: Dimension[], pos: Position) { - this.placeholder.move(dims, pos) + private updatePlaceholderPosition(targetDimension: Dimension, placement: Placement) { + this.placeholder.move(targetDimension, placement) } /** diff --git a/packages/core/src/utils/sorter/SorterUtils.ts b/packages/core/src/utils/sorter/SorterUtils.ts index aaef012d4..97349c4da 100644 --- a/packages/core/src/utils/sorter/SorterUtils.ts +++ b/packages/core/src/utils/sorter/SorterUtils.ts @@ -4,7 +4,7 @@ import { isTextNode } from '../dom'; import { matches as matchesMixin } from '../mixins'; import { SortableTreeNode } from './SortableTreeNode'; import { RequiredEmAndTreeClassPartialSorterOptions } from './Sorter'; -import { Dimension, Position, SorterDirection } from './types'; +import { Dimension, Placement, DragDirection } from './types'; /** * Find the position based on passed dimensions and coordinates @@ -13,8 +13,8 @@ import { Dimension, Position, SorterDirection } from './types'; * @param {number} posY Y coordindate * @return {Object} * */ -export function findPosition(dims: Dimension[], posX: number, posY: number): Position { - const result: Position = { index: 0, indexEl: 0, method: 'before' }; +export function findPosition(dims: Dimension[], posX: number, posY: number) { + const result = { index: 0, placement: 'before' as Placement }; let leftLimit = 0; let xLimit = 0; let dimRight = 0; @@ -42,24 +42,23 @@ export function findPosition(dims: Dimension[], posX: number, posY: number): Pos (leftLimit && dimRight < leftLimit)) continue; result.index = i; - result.indexEl = dim.indexEl!; // If it's not in flow (like 'float' element) if (!dim.dir) { if (posY < dimDown) yLimit = dimDown; //If x lefter than center if (posX < xCenter) { xLimit = xCenter; - result.method = 'before'; + result.placement = 'before'; } else { leftLimit = xCenter; - result.method = 'after'; + result.placement = 'after'; } } else { // If y upper than center if (posY < yCenter) { - result.method = 'before'; + result.placement = 'before'; break; - } else result.method = 'after'; // After last element + } else result.placement = 'after'; // After last element } } @@ -300,7 +299,7 @@ export function getMergedOptions>(sorter canvasRelative: false }, dragBehavior: { - dragDirection: SorterDirection.Vertical, + dragDirection: DragDirection.Vertical, nested: false, ignoreViewChildren: false, selectOnEnd: true, @@ -330,7 +329,3 @@ export function getMergedOptions>(sorter }; return mergedOptions; } - -export function hasPointerPositionChanged(pos: Position, lastPos?: Position) { - return !lastPos || lastPos.index !== pos.index || lastPos.method !== pos.method; -} diff --git a/packages/core/src/utils/sorter/StyleManagerSorter.ts b/packages/core/src/utils/sorter/StyleManagerSorter.ts index dd6aba9c5..7eeb58f0a 100644 --- a/packages/core/src/utils/sorter/StyleManagerSorter.ts +++ b/packages/core/src/utils/sorter/StyleManagerSorter.ts @@ -30,7 +30,7 @@ export default class StyleManagerSorter extends Sorter { + onDrop: (targetNode: LayerNode | undefined, sourceNodes: LayerNode[], index: number | undefined) => { eventHandlers.onDrop?.(targetNode, sourceNodes, index); this.onLayerDrop(targetNode, sourceNodes, index); }, @@ -48,10 +48,11 @@ export default class StyleManagerSorter extends Sorter { + onLayerDrop = (targetNode: LayerNode | undefined, sourceNodes: LayerNode[], index: number | undefined) => { if (!targetNode) { return; } + index = typeof index === 'number' ? index : -1; for (let idx = 0; idx < sourceNodes.length; idx++) { const sourceNode = sourceNodes[idx]; if (!targetNode.canMove(sourceNode, idx)) { diff --git a/packages/core/src/utils/sorter/types.ts b/packages/core/src/utils/sorter/types.ts index e35dd0977..7bc0b1f56 100644 --- a/packages/core/src/utils/sorter/types.ts +++ b/packages/core/src/utils/sorter/types.ts @@ -13,18 +13,18 @@ export interface Dimension { indexEl?: number; } -export interface Position { - index: number; - indexEl: number; - method: string; -} +export type Placement = 'before' | 'after'; -export enum SorterDirection { +export enum DragDirection { Vertical = "Vertical", Horizontal = "Horizontal", BothDirections = "BothDirections" } +export type CustomTarget = ({ event }: { + event: MouseEvent; +}) => HTMLElement | null; + export interface SorterContainerContext { container: HTMLElement; containerSel: string; @@ -32,7 +32,7 @@ export interface SorterContainerContext { pfx: string; document: Document; placeholderElement: HTMLElement; - customTarget?: ({ event }: { event: MouseEvent }) => HTMLElement | null; + customTarget?: CustomTarget; } export interface PositionOptions { @@ -60,11 +60,11 @@ type OnStartSortHandler = (sourceNodes: NodeType[], container?: HTMLEl */ type OnDragStartHandler = (mouseEvent: MouseEvent) => void; type OnMouseMoveHandler = (mouseEvent: MouseEvent) => void; -type OnDropHandler = (targetNode: NodeType | undefined, sourceNodes: NodeType[], index: number) => void; +type OnDropHandler = (targetNode: NodeType | undefined, sourceNodes: NodeType[], index: number | undefined) => void; type OnTargetChangeHandler = (oldTargetNode: NodeType | undefined, newTargetNode: NodeType | undefined) => void; export type OnPlaceholderPositionChangeHandler = { (show: false): void; - (show: true, dims: Dimension[], newPosition: Position): void; + (show: true, targetDimension: Dimension, placement: Placement): void; }; type OnEndMoveHandler = () => void; @@ -88,7 +88,7 @@ export interface SorterEventHandlers { } export interface SorterDragBehaviorOptions { - dragDirection: SorterDirection; + dragDirection: DragDirection; ignoreViewChildren?: boolean; nested?: boolean; selectOnEnd?: boolean;