diff --git a/package.json b/package.json index 3d22823..acef9c6 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "dist" ], "description": "*An awesome drag and drop library for Svelte 3 (not using the browser's built-in dnd, thanks god): Rich animations, nested containers, touch support and more *", - "version": "0.9.17", + "version": "0.9.18", "repository": { "type": "git", "url": "git+https://github.com/isaacHagoel/svelte-dnd-action.git" diff --git a/release-notes.md b/release-notes.md index f4bb86f..1fe4db9 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,5 +1,8 @@ ## Svelte Dnd Action - Release Notes +### [0.9.18](https://github.com/isaacHagoel/svelte-dnd-action/pull/365) +fix: if a drop zone is removed mid-drag it was causing the lib to throw errors + ### [0.9.17](https://github.com/isaacHagoel/svelte-dnd-action/pull/320) fix: dropdowns (select elements) will now maintain their value during drag diff --git a/src/helpers/styler.js b/src/helpers/styler.js index 6734a48..505063b 100644 --- a/src/helpers/styler.js +++ b/src/helpers/styler.js @@ -136,7 +136,7 @@ export function styleDraggable(draggableEl, dragDisabled) { * Hides the provided element so that it can stay in the dom without interrupting * @param {HTMLElement} dragTarget */ -export function hideOriginalDragTarget(dragTarget) { +export function hideElement(dragTarget) { dragTarget.style.display = "none"; dragTarget.style.position = "fixed"; dragTarget.style.zIndex = "-5"; diff --git a/src/pointerAction.js b/src/pointerAction.js index 24530a9..5caa152 100644 --- a/src/pointerAction.js +++ b/src/pointerAction.js @@ -13,7 +13,7 @@ import {armWindowScroller, disarmWindowScroller} from "./helpers/windowScroller" import { createDraggedElementFrom, decorateShadowEl, - hideOriginalDragTarget, + hideElement, morphDraggedElementToBeLike, moveDraggedElementToWasDroppedState, preventShrinking, @@ -55,6 +55,7 @@ let isWorkingOnPreviousDrag = false; let finalizingPreviousDrag = false; let unlockOriginDzMinDimensions; let isDraggedOutsideOfAnyDz = false; +let scheduledForRemovalAfterDrop = []; // a map from type to a set of drop-zones const typeToDropZones = new Map(); @@ -280,10 +281,25 @@ function animateDraggedToFinalPosition(shadowElIdx, callback) { window.setTimeout(callback, dropAnimationDurationMs); } +function scheduleDZForRemovalAfterDrop(dz, destroy) { + scheduledForRemovalAfterDrop.push({dz, destroy}); + window.requestAnimationFrame(() => { + hideElement(dz); + document.body.appendChild(dz); + }); +} /* cleanup */ function cleanupPostDrop() { draggedEl.remove(); originalDragTarget.remove(); + if (scheduledForRemovalAfterDrop.length) { + printDebug(() => ["will destroy zones that were removed during drag", scheduledForRemovalAfterDrop]); + scheduledForRemovalAfterDrop.forEach(({dz, destroy}) => { + destroy(); + dz.remove(); + }) + scheduledForRemovalAfterDrop = []; + } draggedEl = undefined; originalDragTarget = undefined; draggedElData = undefined; @@ -398,7 +414,7 @@ export function dndzone(node, options) { // to prevent the outline from disappearing draggedEl.focus(); watchDraggedElement(); - hideOriginalDragTarget(originalDragTarget); + hideElement(originalDragTarget); originDropZoneRoot.appendChild(originalDragTarget); } else { window.requestAnimationFrame(keepOriginalElementInDom); @@ -529,9 +545,17 @@ export function dndzone(node, options) { configure(newOptions); }, destroy: () => { - printDebug(() => "pointer dndzone will destroy"); - unregisterDropZone(node, config.type); - dzToConfig.delete(node); + function destroyDz() { + printDebug(() => "pointer dndzone will destroy"); + unregisterDropZone(node, dzToConfig.get(node).type); + dzToConfig.delete(node); + } + if (isWorkingOnPreviousDrag) { + printDebug(() => "pointer dndzone will be scheduled for destruction"); + scheduleDZForRemovalAfterDrop(node, destroyDz); + } else { + destroyDz(); + } } }; }