svelte-dnd-action 0.9.70 → 0.9.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +124 -46
- package/dist/index.mjs +124 -46
- package/package.json +1 -1
- package/src/keyboardAction.js +43 -18
- package/src/pointerAction.js +56 -22
- package/src/wrappers/withDragHandles.js +2 -0
package/dist/index.js
CHANGED
|
@@ -1413,6 +1413,8 @@
|
|
|
1413
1413
|
var touchDragHoldTimer;
|
|
1414
1414
|
var touchHoldElapsed = false;
|
|
1415
1415
|
var useCursorForDetectionActive = false;
|
|
1416
|
+
var pendingDragOwner;
|
|
1417
|
+
var watchedDropZones = new Set();
|
|
1416
1418
|
|
|
1417
1419
|
// a map from type to a set of drop-zones
|
|
1418
1420
|
var typeToDropZones$1 = new Map();
|
|
@@ -1435,9 +1437,10 @@
|
|
|
1435
1437
|
}
|
|
1436
1438
|
}
|
|
1437
1439
|
function unregisterDropZone$1(dropZoneEl, type) {
|
|
1438
|
-
typeToDropZones$1.get(type)
|
|
1440
|
+
var dropZones = typeToDropZones$1.get(type);
|
|
1441
|
+
if (!dropZones || !dropZones["delete"](dropZoneEl)) return;
|
|
1439
1442
|
decrementActiveDropZoneCount();
|
|
1440
|
-
if (
|
|
1443
|
+
if (dropZones.size === 0) {
|
|
1441
1444
|
typeToDropZones$1["delete"](type);
|
|
1442
1445
|
}
|
|
1443
1446
|
}
|
|
@@ -1448,7 +1451,10 @@
|
|
|
1448
1451
|
return "watching dragged element";
|
|
1449
1452
|
});
|
|
1450
1453
|
var dropZones = typeToDropZones$1.get(draggedElType);
|
|
1451
|
-
|
|
1454
|
+
if (!dropZones || dropZones.size === 0) return;
|
|
1455
|
+
if (watchedDropZones.size > 0) unWatchDraggedElement();
|
|
1456
|
+
watchedDropZones = new Set(dropZones);
|
|
1457
|
+
var _iterator = _createForOfIteratorHelper(watchedDropZones),
|
|
1452
1458
|
_step;
|
|
1453
1459
|
try {
|
|
1454
1460
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
@@ -1465,11 +1471,11 @@
|
|
|
1465
1471
|
window.addEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop$1);
|
|
1466
1472
|
|
|
1467
1473
|
// it is important that we don't have an interval that is faster than the flip duration because it can cause elements to jump bach and forth
|
|
1468
|
-
var setIntervalMs = Math.max.apply(Math, _toConsumableArray(Array.from(
|
|
1474
|
+
var setIntervalMs = Math.max.apply(Math, _toConsumableArray(Array.from(watchedDropZones).map(function (dz) {
|
|
1469
1475
|
return dzToConfig$1.get(dz).dropAnimationDurationMs;
|
|
1470
1476
|
})));
|
|
1471
1477
|
var observationIntervalMs = setIntervalMs === 0 ? DISABLED_OBSERVATION_INTERVAL_MS : Math.max(setIntervalMs, MIN_OBSERVATION_INTERVAL_MS); // if setIntervalMs is 0 it goes to 20, otherwise it is max between it and min observation.
|
|
1472
|
-
multiScroller = createMultiScroller(
|
|
1478
|
+
multiScroller = createMultiScroller(watchedDropZones, function () {
|
|
1473
1479
|
return currentMousePosition;
|
|
1474
1480
|
});
|
|
1475
1481
|
// Returns reference point in document coordinates - either cursor position or element center
|
|
@@ -1481,14 +1487,13 @@
|
|
|
1481
1487
|
} : function () {
|
|
1482
1488
|
return findCenterOfElement(draggedEl);
|
|
1483
1489
|
};
|
|
1484
|
-
observe(draggedEl,
|
|
1490
|
+
observe(draggedEl, watchedDropZones, observationIntervalMs * 1.07, multiScroller, getReferencePoint);
|
|
1485
1491
|
}
|
|
1486
1492
|
function unWatchDraggedElement() {
|
|
1487
1493
|
printDebug(function () {
|
|
1488
1494
|
return "unwatching dragged element";
|
|
1489
1495
|
});
|
|
1490
|
-
var
|
|
1491
|
-
var _iterator2 = _createForOfIteratorHelper(dropZones),
|
|
1496
|
+
var _iterator2 = _createForOfIteratorHelper(watchedDropZones),
|
|
1492
1497
|
_step2;
|
|
1493
1498
|
try {
|
|
1494
1499
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
@@ -1502,6 +1507,7 @@
|
|
|
1502
1507
|
} finally {
|
|
1503
1508
|
_iterator2.f();
|
|
1504
1509
|
}
|
|
1510
|
+
watchedDropZones = new Set();
|
|
1505
1511
|
window.removeEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop$1);
|
|
1506
1512
|
// ensuring multiScroller is not already destroyed before destroying
|
|
1507
1513
|
if (multiScroller) {
|
|
@@ -1687,6 +1693,9 @@
|
|
|
1687
1693
|
return item[SHADOW_ITEM_MARKER_PROPERTY_NAME] ? draggedElData : item;
|
|
1688
1694
|
});
|
|
1689
1695
|
function finalizeWithinZone() {
|
|
1696
|
+
// The original-element rAF loop may have re-armed observation during the settle animation.
|
|
1697
|
+
// Cancel again before dispatching events that can update or destroy drop zones.
|
|
1698
|
+
unWatchDraggedElement();
|
|
1690
1699
|
unlockOriginDzMinDimensions();
|
|
1691
1700
|
dispatchFinalizeEvent(shadowElDropZone, items, {
|
|
1692
1701
|
trigger: isDraggedOutsideOfAnyDz ? TRIGGERS.DROPPED_OUTSIDE_OF_ANY : TRIGGERS.DROPPED_INTO_ZONE,
|
|
@@ -1730,11 +1739,13 @@
|
|
|
1730
1739
|
window.setTimeout(callback, dropAnimationDurationMs);
|
|
1731
1740
|
}
|
|
1732
1741
|
function scheduleDZForRemovalAfterDrop(dz, destroy) {
|
|
1733
|
-
|
|
1742
|
+
var scheduledRemoval = {
|
|
1734
1743
|
dz: dz,
|
|
1735
1744
|
destroy: destroy
|
|
1736
|
-
}
|
|
1745
|
+
};
|
|
1746
|
+
scheduledForRemovalAfterDrop.push(scheduledRemoval);
|
|
1737
1747
|
window.requestAnimationFrame(function () {
|
|
1748
|
+
if (!scheduledForRemovalAfterDrop.includes(scheduledRemoval)) return;
|
|
1738
1749
|
hideElement(dz);
|
|
1739
1750
|
document.body.appendChild(dz);
|
|
1740
1751
|
});
|
|
@@ -1768,6 +1779,7 @@
|
|
|
1768
1779
|
touchDragHoldTimer = undefined;
|
|
1769
1780
|
touchHoldElapsed = false;
|
|
1770
1781
|
useCursorForDetectionActive = false;
|
|
1782
|
+
pendingDragOwner = undefined;
|
|
1771
1783
|
if (scheduledForRemovalAfterDrop.length) {
|
|
1772
1784
|
printDebug(function () {
|
|
1773
1785
|
return ["will destroy zones that were removed during drag", scheduledForRemovalAfterDrop];
|
|
@@ -1783,6 +1795,7 @@
|
|
|
1783
1795
|
}
|
|
1784
1796
|
function dndzone$2(node, options) {
|
|
1785
1797
|
var initialized = false;
|
|
1798
|
+
var destroyed = false;
|
|
1786
1799
|
var config = {
|
|
1787
1800
|
items: undefined,
|
|
1788
1801
|
type: undefined,
|
|
@@ -1830,11 +1843,17 @@
|
|
|
1830
1843
|
touchHoldElapsed = false;
|
|
1831
1844
|
}
|
|
1832
1845
|
}
|
|
1833
|
-
function
|
|
1846
|
+
function cancelPendingDrag() {
|
|
1847
|
+
if (pendingDragOwner !== node) return;
|
|
1834
1848
|
removeMaybeListeners();
|
|
1849
|
+
pendingDragOwner = undefined;
|
|
1835
1850
|
originalDragTarget = undefined;
|
|
1836
1851
|
dragStartMousePosition = undefined;
|
|
1837
1852
|
currentMousePosition = undefined;
|
|
1853
|
+
}
|
|
1854
|
+
function handleFalseAlarm(e) {
|
|
1855
|
+
if (pendingDragOwner !== node) return;
|
|
1856
|
+
cancelPendingDrag();
|
|
1838
1857
|
|
|
1839
1858
|
// dragging initiated by touch events prevents onclick from initially firing
|
|
1840
1859
|
if (e.type === "touchend") {
|
|
@@ -1847,6 +1866,7 @@
|
|
|
1847
1866
|
}
|
|
1848
1867
|
}
|
|
1849
1868
|
function handleMouseMoveMaybeDragStart(e) {
|
|
1869
|
+
if (destroyed || pendingDragOwner !== node) return;
|
|
1850
1870
|
var isTouch = !!e.touches;
|
|
1851
1871
|
var c = isTouch ? e.touches[0] : e;
|
|
1852
1872
|
// If touch drag delay is configured and not elapsed yet, allow scrolling until either
|
|
@@ -1875,7 +1895,6 @@
|
|
|
1875
1895
|
y: c.clientY
|
|
1876
1896
|
};
|
|
1877
1897
|
if (Math.abs(currentMousePosition.x - dragStartMousePosition.x) >= MIN_MOVEMENT_BEFORE_DRAG_START_PX || Math.abs(currentMousePosition.y - dragStartMousePosition.y) >= MIN_MOVEMENT_BEFORE_DRAG_START_PX) {
|
|
1878
|
-
removeMaybeListeners();
|
|
1879
1898
|
handleDragStart();
|
|
1880
1899
|
}
|
|
1881
1900
|
}
|
|
@@ -1894,9 +1913,9 @@
|
|
|
1894
1913
|
});
|
|
1895
1914
|
return;
|
|
1896
1915
|
}
|
|
1897
|
-
if (isWorkingOnPreviousDrag) {
|
|
1916
|
+
if (destroyed || isWorkingOnPreviousDrag || pendingDragOwner) {
|
|
1898
1917
|
printDebug(function () {
|
|
1899
|
-
return "cannot start a new drag before finalizing
|
|
1918
|
+
return "cannot start a new drag before finalizing the current drag or pending gesture";
|
|
1900
1919
|
});
|
|
1901
1920
|
return;
|
|
1902
1921
|
}
|
|
@@ -1906,6 +1925,7 @@
|
|
|
1906
1925
|
e.preventDefault();
|
|
1907
1926
|
}
|
|
1908
1927
|
e.stopPropagation();
|
|
1928
|
+
pendingDragOwner = node;
|
|
1909
1929
|
var c = isTouchStart ? e.touches[0] : e;
|
|
1910
1930
|
dragStartMousePosition = {
|
|
1911
1931
|
x: c.clientX,
|
|
@@ -1914,18 +1934,25 @@
|
|
|
1914
1934
|
currentMousePosition = _objectSpread2({}, dragStartMousePosition);
|
|
1915
1935
|
originalDragTarget = e.currentTarget;
|
|
1916
1936
|
if (useDelay) {
|
|
1937
|
+
var pendingTarget = originalDragTarget;
|
|
1917
1938
|
touchHoldElapsed = false;
|
|
1918
1939
|
touchDragHoldTimer = window.setTimeout(function () {
|
|
1919
|
-
// If the
|
|
1920
|
-
if (
|
|
1940
|
+
// If this action still owns the same pending gesture, transition it to a drag.
|
|
1941
|
+
if (destroyed || pendingDragOwner !== node || originalDragTarget !== pendingTarget) return;
|
|
1921
1942
|
touchHoldElapsed = true;
|
|
1922
|
-
removeMaybeListeners();
|
|
1923
1943
|
handleDragStart();
|
|
1924
1944
|
}, config.delayTouchStartMs);
|
|
1925
1945
|
}
|
|
1926
1946
|
addMaybeListeners();
|
|
1927
1947
|
}
|
|
1928
1948
|
function handleDragStart() {
|
|
1949
|
+
var _originalDragTarget;
|
|
1950
|
+
if (destroyed || pendingDragOwner !== node || isWorkingOnPreviousDrag || !((_originalDragTarget = originalDragTarget) !== null && _originalDragTarget !== void 0 && _originalDragTarget.parentElement)) {
|
|
1951
|
+
cancelPendingDrag();
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
removeMaybeListeners();
|
|
1955
|
+
pendingDragOwner = undefined;
|
|
1929
1956
|
printDebug(function () {
|
|
1930
1957
|
return ["drag start config: ".concat(toString(config)), originalDragTarget];
|
|
1931
1958
|
});
|
|
@@ -1953,11 +1980,10 @@
|
|
|
1953
1980
|
originDropZoneRoot.appendChild(draggedEl);
|
|
1954
1981
|
// We will keep the original dom node in the dom because touch events keep firing on it, we want to re-add it after the framework removes it
|
|
1955
1982
|
function keepOriginalElementInDom() {
|
|
1956
|
-
//
|
|
1957
|
-
// must not re-arm
|
|
1958
|
-
//
|
|
1959
|
-
|
|
1960
|
-
if (!draggedEl) return;
|
|
1983
|
+
// Once the drop starts finalizing, handleDrop has stopped observation and this loop
|
|
1984
|
+
// must not re-arm it during the settle animation. After cleanup, draggedEl is cleared
|
|
1985
|
+
// as an additional guard against the original element leaving the DOM much later.
|
|
1986
|
+
if (!draggedEl || finalizingPreviousDrag) return;
|
|
1961
1987
|
if (!originalDragTarget.parentElement) {
|
|
1962
1988
|
originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
|
|
1963
1989
|
originDropZoneRoot.appendChild(originalDragTarget);
|
|
@@ -2125,11 +2151,29 @@
|
|
|
2125
2151
|
configure(newOptions);
|
|
2126
2152
|
},
|
|
2127
2153
|
destroy: function destroy() {
|
|
2154
|
+
if (destroyed) return;
|
|
2155
|
+
destroyed = true;
|
|
2156
|
+
cancelPendingDrag();
|
|
2157
|
+
var _iterator3 = _createForOfIteratorHelper(node.children),
|
|
2158
|
+
_step3;
|
|
2159
|
+
try {
|
|
2160
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
2161
|
+
var draggableEl = _step3.value;
|
|
2162
|
+
draggableEl.removeEventListener("mousedown", elToMouseDownListener.get(draggableEl));
|
|
2163
|
+
draggableEl.removeEventListener("touchstart", elToMouseDownListener.get(draggableEl));
|
|
2164
|
+
}
|
|
2165
|
+
} catch (err) {
|
|
2166
|
+
_iterator3.e(err);
|
|
2167
|
+
} finally {
|
|
2168
|
+
_iterator3.f();
|
|
2169
|
+
}
|
|
2128
2170
|
function destroyDz() {
|
|
2129
2171
|
printDebug(function () {
|
|
2130
2172
|
return "pointer dndzone will destroy";
|
|
2131
2173
|
});
|
|
2132
|
-
|
|
2174
|
+
var registeredConfig = dzToConfig$1.get(node);
|
|
2175
|
+
if (!registeredConfig) return;
|
|
2176
|
+
unregisterDropZone$1(node, registeredConfig.type);
|
|
2133
2177
|
dzToConfig$1["delete"](node);
|
|
2134
2178
|
}
|
|
2135
2179
|
if (isWorkingOnPreviousDrag && !node.closest("[".concat(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, "]"))) {
|
|
@@ -2286,12 +2330,13 @@
|
|
|
2286
2330
|
printDebug(function () {
|
|
2287
2331
|
return "unregistering drop-zone";
|
|
2288
2332
|
});
|
|
2289
|
-
if (focusedDz === dropZoneEl) {
|
|
2333
|
+
if (isDragging && focusedDz === dropZoneEl) {
|
|
2290
2334
|
handleDrop();
|
|
2291
2335
|
}
|
|
2292
|
-
typeToDropZones.get(type)
|
|
2336
|
+
var dropZones = typeToDropZones.get(type);
|
|
2337
|
+
if (!dropZones || !dropZones["delete"](dropZoneEl)) return;
|
|
2293
2338
|
decrementActiveDropZoneCount();
|
|
2294
|
-
if (
|
|
2339
|
+
if (dropZones.size === 0) {
|
|
2295
2340
|
typeToDropZones["delete"](type);
|
|
2296
2341
|
}
|
|
2297
2342
|
if (typeToDropZones.size === 0) {
|
|
@@ -2353,17 +2398,20 @@
|
|
|
2353
2398
|
}
|
|
2354
2399
|
}
|
|
2355
2400
|
var dzFrom = focusedDz;
|
|
2401
|
+
var movedItemId = focusedItemId;
|
|
2402
|
+
focusedDz = newlyFocusedDz;
|
|
2356
2403
|
dispatchFinalizeEvent(dzFrom, originItems, {
|
|
2357
2404
|
trigger: TRIGGERS.DROPPED_INTO_ANOTHER,
|
|
2358
|
-
id:
|
|
2359
|
-
source: SOURCES.KEYBOARD
|
|
2360
|
-
});
|
|
2361
|
-
dispatchFinalizeEvent(newlyFocusedDz, targetItems, {
|
|
2362
|
-
trigger: TRIGGERS.DROPPED_INTO_ZONE,
|
|
2363
|
-
id: focusedItemId,
|
|
2405
|
+
id: movedItemId,
|
|
2364
2406
|
source: SOURCES.KEYBOARD
|
|
2365
2407
|
});
|
|
2366
|
-
|
|
2408
|
+
if (dzToConfig.has(newlyFocusedDz)) {
|
|
2409
|
+
dispatchFinalizeEvent(newlyFocusedDz, targetItems, {
|
|
2410
|
+
trigger: TRIGGERS.DROPPED_INTO_ZONE,
|
|
2411
|
+
id: movedItemId,
|
|
2412
|
+
source: SOURCES.KEYBOARD
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2367
2415
|
}
|
|
2368
2416
|
function triggerAllDzsUpdate() {
|
|
2369
2417
|
dzToHandles.forEach(function (_ref, dz) {
|
|
@@ -2373,27 +2421,23 @@
|
|
|
2373
2421
|
}
|
|
2374
2422
|
function handleDrop() {
|
|
2375
2423
|
var dispatchConsider = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
2424
|
+
if (!isDragging || !focusedDz) return;
|
|
2376
2425
|
printDebug(function () {
|
|
2377
2426
|
return "drop";
|
|
2378
2427
|
});
|
|
2379
|
-
|
|
2428
|
+
var droppedDz = focusedDz;
|
|
2429
|
+
var droppedConfig = dzToConfig.get(droppedDz);
|
|
2430
|
+
var droppedItemId = focusedItemId;
|
|
2431
|
+
var droppedItemType = draggedItemType;
|
|
2432
|
+
if (!droppedConfig) return;
|
|
2433
|
+
if (!droppedConfig.autoAriaDisabled) {
|
|
2380
2434
|
alertToScreenReader("Stopped dragging item ".concat(focusedItemLabel));
|
|
2381
2435
|
}
|
|
2382
2436
|
if (allDragTargets.has(document.activeElement)) {
|
|
2383
2437
|
document.activeElement.blur();
|
|
2384
2438
|
}
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
trigger: TRIGGERS.DRAG_STOPPED,
|
|
2388
|
-
id: focusedItemId,
|
|
2389
|
-
source: SOURCES.KEYBOARD
|
|
2390
|
-
});
|
|
2391
|
-
}
|
|
2392
|
-
styleInactiveDropZones(typeToDropZones.get(draggedItemType), function (dz) {
|
|
2393
|
-
return dzToConfig.get(dz).dropTargetStyle;
|
|
2394
|
-
}, function (dz) {
|
|
2395
|
-
return dzToConfig.get(dz).dropTargetClasses;
|
|
2396
|
-
});
|
|
2439
|
+
// Clear global drag state before dispatching. A synchronous handler may destroy the
|
|
2440
|
+
// focused zone, and unregisterDropZone must not recursively enter handleDrop.
|
|
2397
2441
|
focusedItem = null;
|
|
2398
2442
|
focusedItemId = null;
|
|
2399
2443
|
focusedItemLabel = "";
|
|
@@ -2401,10 +2445,26 @@
|
|
|
2401
2445
|
focusedDz = null;
|
|
2402
2446
|
focusedDzLabel = "";
|
|
2403
2447
|
isDragging = false;
|
|
2448
|
+
if (dispatchConsider) {
|
|
2449
|
+
dispatchConsiderEvent(droppedDz, droppedConfig.items, {
|
|
2450
|
+
trigger: TRIGGERS.DRAG_STOPPED,
|
|
2451
|
+
id: droppedItemId,
|
|
2452
|
+
source: SOURCES.KEYBOARD
|
|
2453
|
+
});
|
|
2454
|
+
}
|
|
2455
|
+
var dropZones = typeToDropZones.get(droppedItemType);
|
|
2456
|
+
if (dropZones) {
|
|
2457
|
+
styleInactiveDropZones(dropZones, function (dz) {
|
|
2458
|
+
return dzToConfig.get(dz).dropTargetStyle;
|
|
2459
|
+
}, function (dz) {
|
|
2460
|
+
return dzToConfig.get(dz).dropTargetClasses;
|
|
2461
|
+
});
|
|
2462
|
+
}
|
|
2404
2463
|
triggerAllDzsUpdate();
|
|
2405
2464
|
}
|
|
2406
2465
|
//////
|
|
2407
2466
|
function dndzone$1(node, options) {
|
|
2467
|
+
var destroyed = false;
|
|
2408
2468
|
var config = {
|
|
2409
2469
|
items: undefined,
|
|
2410
2470
|
type: undefined,
|
|
@@ -2629,9 +2689,25 @@
|
|
|
2629
2689
|
configure(newOptions);
|
|
2630
2690
|
},
|
|
2631
2691
|
destroy: function destroy() {
|
|
2692
|
+
if (destroyed) return;
|
|
2693
|
+
destroyed = true;
|
|
2632
2694
|
printDebug(function () {
|
|
2633
2695
|
return "keyboard dndzone will destroy";
|
|
2634
2696
|
});
|
|
2697
|
+
node.removeEventListener("focus", handleZoneFocus);
|
|
2698
|
+
var _iterator = _createForOfIteratorHelper(node.children),
|
|
2699
|
+
_step;
|
|
2700
|
+
try {
|
|
2701
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
2702
|
+
var draggableEl = _step.value;
|
|
2703
|
+
draggableEl.removeEventListener("keydown", elToKeyDownListeners.get(draggableEl));
|
|
2704
|
+
draggableEl.removeEventListener("click", elToFocusListeners.get(draggableEl));
|
|
2705
|
+
}
|
|
2706
|
+
} catch (err) {
|
|
2707
|
+
_iterator.e(err);
|
|
2708
|
+
} finally {
|
|
2709
|
+
_iterator.f();
|
|
2710
|
+
}
|
|
2635
2711
|
unregisterDropZone(node, config.type);
|
|
2636
2712
|
dzToConfig["delete"](node);
|
|
2637
2713
|
dzToHandles["delete"](node);
|
|
@@ -2840,6 +2916,8 @@
|
|
|
2840
2916
|
updateZone();
|
|
2841
2917
|
},
|
|
2842
2918
|
destroy: function destroy() {
|
|
2919
|
+
isItemsDragDisabled.set(true);
|
|
2920
|
+
zone.destroy();
|
|
2843
2921
|
node.removeEventListener("consider", consider);
|
|
2844
2922
|
node.removeEventListener("finalize", finalize);
|
|
2845
2923
|
isItemsDragDisabled.unsubscribe(updateZone);
|
package/dist/index.mjs
CHANGED
|
@@ -1407,6 +1407,8 @@ var multiScroller;
|
|
|
1407
1407
|
var touchDragHoldTimer;
|
|
1408
1408
|
var touchHoldElapsed = false;
|
|
1409
1409
|
var useCursorForDetectionActive = false;
|
|
1410
|
+
var pendingDragOwner;
|
|
1411
|
+
var watchedDropZones = new Set();
|
|
1410
1412
|
|
|
1411
1413
|
// a map from type to a set of drop-zones
|
|
1412
1414
|
var typeToDropZones$1 = new Map();
|
|
@@ -1429,9 +1431,10 @@ function registerDropZone$1(dropZoneEl, type) {
|
|
|
1429
1431
|
}
|
|
1430
1432
|
}
|
|
1431
1433
|
function unregisterDropZone$1(dropZoneEl, type) {
|
|
1432
|
-
typeToDropZones$1.get(type)
|
|
1434
|
+
var dropZones = typeToDropZones$1.get(type);
|
|
1435
|
+
if (!dropZones || !dropZones["delete"](dropZoneEl)) return;
|
|
1433
1436
|
decrementActiveDropZoneCount();
|
|
1434
|
-
if (
|
|
1437
|
+
if (dropZones.size === 0) {
|
|
1435
1438
|
typeToDropZones$1["delete"](type);
|
|
1436
1439
|
}
|
|
1437
1440
|
}
|
|
@@ -1442,7 +1445,10 @@ function watchDraggedElement() {
|
|
|
1442
1445
|
return "watching dragged element";
|
|
1443
1446
|
});
|
|
1444
1447
|
var dropZones = typeToDropZones$1.get(draggedElType);
|
|
1445
|
-
|
|
1448
|
+
if (!dropZones || dropZones.size === 0) return;
|
|
1449
|
+
if (watchedDropZones.size > 0) unWatchDraggedElement();
|
|
1450
|
+
watchedDropZones = new Set(dropZones);
|
|
1451
|
+
var _iterator = _createForOfIteratorHelper(watchedDropZones),
|
|
1446
1452
|
_step;
|
|
1447
1453
|
try {
|
|
1448
1454
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
@@ -1459,11 +1465,11 @@ function watchDraggedElement() {
|
|
|
1459
1465
|
window.addEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop$1);
|
|
1460
1466
|
|
|
1461
1467
|
// it is important that we don't have an interval that is faster than the flip duration because it can cause elements to jump bach and forth
|
|
1462
|
-
var setIntervalMs = Math.max.apply(Math, _toConsumableArray(Array.from(
|
|
1468
|
+
var setIntervalMs = Math.max.apply(Math, _toConsumableArray(Array.from(watchedDropZones).map(function (dz) {
|
|
1463
1469
|
return dzToConfig$1.get(dz).dropAnimationDurationMs;
|
|
1464
1470
|
})));
|
|
1465
1471
|
var observationIntervalMs = setIntervalMs === 0 ? DISABLED_OBSERVATION_INTERVAL_MS : Math.max(setIntervalMs, MIN_OBSERVATION_INTERVAL_MS); // if setIntervalMs is 0 it goes to 20, otherwise it is max between it and min observation.
|
|
1466
|
-
multiScroller = createMultiScroller(
|
|
1472
|
+
multiScroller = createMultiScroller(watchedDropZones, function () {
|
|
1467
1473
|
return currentMousePosition;
|
|
1468
1474
|
});
|
|
1469
1475
|
// Returns reference point in document coordinates - either cursor position or element center
|
|
@@ -1475,14 +1481,13 @@ function watchDraggedElement() {
|
|
|
1475
1481
|
} : function () {
|
|
1476
1482
|
return findCenterOfElement(draggedEl);
|
|
1477
1483
|
};
|
|
1478
|
-
observe(draggedEl,
|
|
1484
|
+
observe(draggedEl, watchedDropZones, observationIntervalMs * 1.07, multiScroller, getReferencePoint);
|
|
1479
1485
|
}
|
|
1480
1486
|
function unWatchDraggedElement() {
|
|
1481
1487
|
printDebug(function () {
|
|
1482
1488
|
return "unwatching dragged element";
|
|
1483
1489
|
});
|
|
1484
|
-
var
|
|
1485
|
-
var _iterator2 = _createForOfIteratorHelper(dropZones),
|
|
1490
|
+
var _iterator2 = _createForOfIteratorHelper(watchedDropZones),
|
|
1486
1491
|
_step2;
|
|
1487
1492
|
try {
|
|
1488
1493
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
@@ -1496,6 +1501,7 @@ function unWatchDraggedElement() {
|
|
|
1496
1501
|
} finally {
|
|
1497
1502
|
_iterator2.f();
|
|
1498
1503
|
}
|
|
1504
|
+
watchedDropZones = new Set();
|
|
1499
1505
|
window.removeEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop$1);
|
|
1500
1506
|
// ensuring multiScroller is not already destroyed before destroying
|
|
1501
1507
|
if (multiScroller) {
|
|
@@ -1681,6 +1687,9 @@ function handleDrop$1() {
|
|
|
1681
1687
|
return item[SHADOW_ITEM_MARKER_PROPERTY_NAME] ? draggedElData : item;
|
|
1682
1688
|
});
|
|
1683
1689
|
function finalizeWithinZone() {
|
|
1690
|
+
// The original-element rAF loop may have re-armed observation during the settle animation.
|
|
1691
|
+
// Cancel again before dispatching events that can update or destroy drop zones.
|
|
1692
|
+
unWatchDraggedElement();
|
|
1684
1693
|
unlockOriginDzMinDimensions();
|
|
1685
1694
|
dispatchFinalizeEvent(shadowElDropZone, items, {
|
|
1686
1695
|
trigger: isDraggedOutsideOfAnyDz ? TRIGGERS.DROPPED_OUTSIDE_OF_ANY : TRIGGERS.DROPPED_INTO_ZONE,
|
|
@@ -1724,11 +1733,13 @@ function animateDraggedToFinalPosition(shadowElIdx, callback) {
|
|
|
1724
1733
|
window.setTimeout(callback, dropAnimationDurationMs);
|
|
1725
1734
|
}
|
|
1726
1735
|
function scheduleDZForRemovalAfterDrop(dz, destroy) {
|
|
1727
|
-
|
|
1736
|
+
var scheduledRemoval = {
|
|
1728
1737
|
dz: dz,
|
|
1729
1738
|
destroy: destroy
|
|
1730
|
-
}
|
|
1739
|
+
};
|
|
1740
|
+
scheduledForRemovalAfterDrop.push(scheduledRemoval);
|
|
1731
1741
|
window.requestAnimationFrame(function () {
|
|
1742
|
+
if (!scheduledForRemovalAfterDrop.includes(scheduledRemoval)) return;
|
|
1732
1743
|
hideElement(dz);
|
|
1733
1744
|
document.body.appendChild(dz);
|
|
1734
1745
|
});
|
|
@@ -1762,6 +1773,7 @@ function cleanupPostDrop() {
|
|
|
1762
1773
|
touchDragHoldTimer = undefined;
|
|
1763
1774
|
touchHoldElapsed = false;
|
|
1764
1775
|
useCursorForDetectionActive = false;
|
|
1776
|
+
pendingDragOwner = undefined;
|
|
1765
1777
|
if (scheduledForRemovalAfterDrop.length) {
|
|
1766
1778
|
printDebug(function () {
|
|
1767
1779
|
return ["will destroy zones that were removed during drag", scheduledForRemovalAfterDrop];
|
|
@@ -1777,6 +1789,7 @@ function cleanupPostDrop() {
|
|
|
1777
1789
|
}
|
|
1778
1790
|
function dndzone$2(node, options) {
|
|
1779
1791
|
var initialized = false;
|
|
1792
|
+
var destroyed = false;
|
|
1780
1793
|
var config = {
|
|
1781
1794
|
items: undefined,
|
|
1782
1795
|
type: undefined,
|
|
@@ -1824,11 +1837,17 @@ function dndzone$2(node, options) {
|
|
|
1824
1837
|
touchHoldElapsed = false;
|
|
1825
1838
|
}
|
|
1826
1839
|
}
|
|
1827
|
-
function
|
|
1840
|
+
function cancelPendingDrag() {
|
|
1841
|
+
if (pendingDragOwner !== node) return;
|
|
1828
1842
|
removeMaybeListeners();
|
|
1843
|
+
pendingDragOwner = undefined;
|
|
1829
1844
|
originalDragTarget = undefined;
|
|
1830
1845
|
dragStartMousePosition = undefined;
|
|
1831
1846
|
currentMousePosition = undefined;
|
|
1847
|
+
}
|
|
1848
|
+
function handleFalseAlarm(e) {
|
|
1849
|
+
if (pendingDragOwner !== node) return;
|
|
1850
|
+
cancelPendingDrag();
|
|
1832
1851
|
|
|
1833
1852
|
// dragging initiated by touch events prevents onclick from initially firing
|
|
1834
1853
|
if (e.type === "touchend") {
|
|
@@ -1841,6 +1860,7 @@ function dndzone$2(node, options) {
|
|
|
1841
1860
|
}
|
|
1842
1861
|
}
|
|
1843
1862
|
function handleMouseMoveMaybeDragStart(e) {
|
|
1863
|
+
if (destroyed || pendingDragOwner !== node) return;
|
|
1844
1864
|
var isTouch = !!e.touches;
|
|
1845
1865
|
var c = isTouch ? e.touches[0] : e;
|
|
1846
1866
|
// If touch drag delay is configured and not elapsed yet, allow scrolling until either
|
|
@@ -1869,7 +1889,6 @@ function dndzone$2(node, options) {
|
|
|
1869
1889
|
y: c.clientY
|
|
1870
1890
|
};
|
|
1871
1891
|
if (Math.abs(currentMousePosition.x - dragStartMousePosition.x) >= MIN_MOVEMENT_BEFORE_DRAG_START_PX || Math.abs(currentMousePosition.y - dragStartMousePosition.y) >= MIN_MOVEMENT_BEFORE_DRAG_START_PX) {
|
|
1872
|
-
removeMaybeListeners();
|
|
1873
1892
|
handleDragStart();
|
|
1874
1893
|
}
|
|
1875
1894
|
}
|
|
@@ -1888,9 +1907,9 @@ function dndzone$2(node, options) {
|
|
|
1888
1907
|
});
|
|
1889
1908
|
return;
|
|
1890
1909
|
}
|
|
1891
|
-
if (isWorkingOnPreviousDrag) {
|
|
1910
|
+
if (destroyed || isWorkingOnPreviousDrag || pendingDragOwner) {
|
|
1892
1911
|
printDebug(function () {
|
|
1893
|
-
return "cannot start a new drag before finalizing
|
|
1912
|
+
return "cannot start a new drag before finalizing the current drag or pending gesture";
|
|
1894
1913
|
});
|
|
1895
1914
|
return;
|
|
1896
1915
|
}
|
|
@@ -1900,6 +1919,7 @@ function dndzone$2(node, options) {
|
|
|
1900
1919
|
e.preventDefault();
|
|
1901
1920
|
}
|
|
1902
1921
|
e.stopPropagation();
|
|
1922
|
+
pendingDragOwner = node;
|
|
1903
1923
|
var c = isTouchStart ? e.touches[0] : e;
|
|
1904
1924
|
dragStartMousePosition = {
|
|
1905
1925
|
x: c.clientX,
|
|
@@ -1908,18 +1928,25 @@ function dndzone$2(node, options) {
|
|
|
1908
1928
|
currentMousePosition = _objectSpread2({}, dragStartMousePosition);
|
|
1909
1929
|
originalDragTarget = e.currentTarget;
|
|
1910
1930
|
if (useDelay) {
|
|
1931
|
+
var pendingTarget = originalDragTarget;
|
|
1911
1932
|
touchHoldElapsed = false;
|
|
1912
1933
|
touchDragHoldTimer = window.setTimeout(function () {
|
|
1913
|
-
// If the
|
|
1914
|
-
if (
|
|
1934
|
+
// If this action still owns the same pending gesture, transition it to a drag.
|
|
1935
|
+
if (destroyed || pendingDragOwner !== node || originalDragTarget !== pendingTarget) return;
|
|
1915
1936
|
touchHoldElapsed = true;
|
|
1916
|
-
removeMaybeListeners();
|
|
1917
1937
|
handleDragStart();
|
|
1918
1938
|
}, config.delayTouchStartMs);
|
|
1919
1939
|
}
|
|
1920
1940
|
addMaybeListeners();
|
|
1921
1941
|
}
|
|
1922
1942
|
function handleDragStart() {
|
|
1943
|
+
var _originalDragTarget;
|
|
1944
|
+
if (destroyed || pendingDragOwner !== node || isWorkingOnPreviousDrag || !((_originalDragTarget = originalDragTarget) !== null && _originalDragTarget !== void 0 && _originalDragTarget.parentElement)) {
|
|
1945
|
+
cancelPendingDrag();
|
|
1946
|
+
return;
|
|
1947
|
+
}
|
|
1948
|
+
removeMaybeListeners();
|
|
1949
|
+
pendingDragOwner = undefined;
|
|
1923
1950
|
printDebug(function () {
|
|
1924
1951
|
return ["drag start config: ".concat(toString(config)), originalDragTarget];
|
|
1925
1952
|
});
|
|
@@ -1947,11 +1974,10 @@ function dndzone$2(node, options) {
|
|
|
1947
1974
|
originDropZoneRoot.appendChild(draggedEl);
|
|
1948
1975
|
// We will keep the original dom node in the dom because touch events keep firing on it, we want to re-add it after the framework removes it
|
|
1949
1976
|
function keepOriginalElementInDom() {
|
|
1950
|
-
//
|
|
1951
|
-
// must not re-arm
|
|
1952
|
-
//
|
|
1953
|
-
|
|
1954
|
-
if (!draggedEl) return;
|
|
1977
|
+
// Once the drop starts finalizing, handleDrop has stopped observation and this loop
|
|
1978
|
+
// must not re-arm it during the settle animation. After cleanup, draggedEl is cleared
|
|
1979
|
+
// as an additional guard against the original element leaving the DOM much later.
|
|
1980
|
+
if (!draggedEl || finalizingPreviousDrag) return;
|
|
1955
1981
|
if (!originalDragTarget.parentElement) {
|
|
1956
1982
|
originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
|
|
1957
1983
|
originDropZoneRoot.appendChild(originalDragTarget);
|
|
@@ -2119,11 +2145,29 @@ function dndzone$2(node, options) {
|
|
|
2119
2145
|
configure(newOptions);
|
|
2120
2146
|
},
|
|
2121
2147
|
destroy: function destroy() {
|
|
2148
|
+
if (destroyed) return;
|
|
2149
|
+
destroyed = true;
|
|
2150
|
+
cancelPendingDrag();
|
|
2151
|
+
var _iterator3 = _createForOfIteratorHelper(node.children),
|
|
2152
|
+
_step3;
|
|
2153
|
+
try {
|
|
2154
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
2155
|
+
var draggableEl = _step3.value;
|
|
2156
|
+
draggableEl.removeEventListener("mousedown", elToMouseDownListener.get(draggableEl));
|
|
2157
|
+
draggableEl.removeEventListener("touchstart", elToMouseDownListener.get(draggableEl));
|
|
2158
|
+
}
|
|
2159
|
+
} catch (err) {
|
|
2160
|
+
_iterator3.e(err);
|
|
2161
|
+
} finally {
|
|
2162
|
+
_iterator3.f();
|
|
2163
|
+
}
|
|
2122
2164
|
function destroyDz() {
|
|
2123
2165
|
printDebug(function () {
|
|
2124
2166
|
return "pointer dndzone will destroy";
|
|
2125
2167
|
});
|
|
2126
|
-
|
|
2168
|
+
var registeredConfig = dzToConfig$1.get(node);
|
|
2169
|
+
if (!registeredConfig) return;
|
|
2170
|
+
unregisterDropZone$1(node, registeredConfig.type);
|
|
2127
2171
|
dzToConfig$1["delete"](node);
|
|
2128
2172
|
}
|
|
2129
2173
|
if (isWorkingOnPreviousDrag && !node.closest("[".concat(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, "]"))) {
|
|
@@ -2280,12 +2324,13 @@ function unregisterDropZone(dropZoneEl, type) {
|
|
|
2280
2324
|
printDebug(function () {
|
|
2281
2325
|
return "unregistering drop-zone";
|
|
2282
2326
|
});
|
|
2283
|
-
if (focusedDz === dropZoneEl) {
|
|
2327
|
+
if (isDragging && focusedDz === dropZoneEl) {
|
|
2284
2328
|
handleDrop();
|
|
2285
2329
|
}
|
|
2286
|
-
typeToDropZones.get(type)
|
|
2330
|
+
var dropZones = typeToDropZones.get(type);
|
|
2331
|
+
if (!dropZones || !dropZones["delete"](dropZoneEl)) return;
|
|
2287
2332
|
decrementActiveDropZoneCount();
|
|
2288
|
-
if (
|
|
2333
|
+
if (dropZones.size === 0) {
|
|
2289
2334
|
typeToDropZones["delete"](type);
|
|
2290
2335
|
}
|
|
2291
2336
|
if (typeToDropZones.size === 0) {
|
|
@@ -2347,17 +2392,20 @@ function handleZoneFocus(e) {
|
|
|
2347
2392
|
}
|
|
2348
2393
|
}
|
|
2349
2394
|
var dzFrom = focusedDz;
|
|
2395
|
+
var movedItemId = focusedItemId;
|
|
2396
|
+
focusedDz = newlyFocusedDz;
|
|
2350
2397
|
dispatchFinalizeEvent(dzFrom, originItems, {
|
|
2351
2398
|
trigger: TRIGGERS.DROPPED_INTO_ANOTHER,
|
|
2352
|
-
id:
|
|
2353
|
-
source: SOURCES.KEYBOARD
|
|
2354
|
-
});
|
|
2355
|
-
dispatchFinalizeEvent(newlyFocusedDz, targetItems, {
|
|
2356
|
-
trigger: TRIGGERS.DROPPED_INTO_ZONE,
|
|
2357
|
-
id: focusedItemId,
|
|
2399
|
+
id: movedItemId,
|
|
2358
2400
|
source: SOURCES.KEYBOARD
|
|
2359
2401
|
});
|
|
2360
|
-
|
|
2402
|
+
if (dzToConfig.has(newlyFocusedDz)) {
|
|
2403
|
+
dispatchFinalizeEvent(newlyFocusedDz, targetItems, {
|
|
2404
|
+
trigger: TRIGGERS.DROPPED_INTO_ZONE,
|
|
2405
|
+
id: movedItemId,
|
|
2406
|
+
source: SOURCES.KEYBOARD
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2361
2409
|
}
|
|
2362
2410
|
function triggerAllDzsUpdate() {
|
|
2363
2411
|
dzToHandles.forEach(function (_ref, dz) {
|
|
@@ -2367,27 +2415,23 @@ function triggerAllDzsUpdate() {
|
|
|
2367
2415
|
}
|
|
2368
2416
|
function handleDrop() {
|
|
2369
2417
|
var dispatchConsider = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
2418
|
+
if (!isDragging || !focusedDz) return;
|
|
2370
2419
|
printDebug(function () {
|
|
2371
2420
|
return "drop";
|
|
2372
2421
|
});
|
|
2373
|
-
|
|
2422
|
+
var droppedDz = focusedDz;
|
|
2423
|
+
var droppedConfig = dzToConfig.get(droppedDz);
|
|
2424
|
+
var droppedItemId = focusedItemId;
|
|
2425
|
+
var droppedItemType = draggedItemType;
|
|
2426
|
+
if (!droppedConfig) return;
|
|
2427
|
+
if (!droppedConfig.autoAriaDisabled) {
|
|
2374
2428
|
alertToScreenReader("Stopped dragging item ".concat(focusedItemLabel));
|
|
2375
2429
|
}
|
|
2376
2430
|
if (allDragTargets.has(document.activeElement)) {
|
|
2377
2431
|
document.activeElement.blur();
|
|
2378
2432
|
}
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
trigger: TRIGGERS.DRAG_STOPPED,
|
|
2382
|
-
id: focusedItemId,
|
|
2383
|
-
source: SOURCES.KEYBOARD
|
|
2384
|
-
});
|
|
2385
|
-
}
|
|
2386
|
-
styleInactiveDropZones(typeToDropZones.get(draggedItemType), function (dz) {
|
|
2387
|
-
return dzToConfig.get(dz).dropTargetStyle;
|
|
2388
|
-
}, function (dz) {
|
|
2389
|
-
return dzToConfig.get(dz).dropTargetClasses;
|
|
2390
|
-
});
|
|
2433
|
+
// Clear global drag state before dispatching. A synchronous handler may destroy the
|
|
2434
|
+
// focused zone, and unregisterDropZone must not recursively enter handleDrop.
|
|
2391
2435
|
focusedItem = null;
|
|
2392
2436
|
focusedItemId = null;
|
|
2393
2437
|
focusedItemLabel = "";
|
|
@@ -2395,10 +2439,26 @@ function handleDrop() {
|
|
|
2395
2439
|
focusedDz = null;
|
|
2396
2440
|
focusedDzLabel = "";
|
|
2397
2441
|
isDragging = false;
|
|
2442
|
+
if (dispatchConsider) {
|
|
2443
|
+
dispatchConsiderEvent(droppedDz, droppedConfig.items, {
|
|
2444
|
+
trigger: TRIGGERS.DRAG_STOPPED,
|
|
2445
|
+
id: droppedItemId,
|
|
2446
|
+
source: SOURCES.KEYBOARD
|
|
2447
|
+
});
|
|
2448
|
+
}
|
|
2449
|
+
var dropZones = typeToDropZones.get(droppedItemType);
|
|
2450
|
+
if (dropZones) {
|
|
2451
|
+
styleInactiveDropZones(dropZones, function (dz) {
|
|
2452
|
+
return dzToConfig.get(dz).dropTargetStyle;
|
|
2453
|
+
}, function (dz) {
|
|
2454
|
+
return dzToConfig.get(dz).dropTargetClasses;
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2398
2457
|
triggerAllDzsUpdate();
|
|
2399
2458
|
}
|
|
2400
2459
|
//////
|
|
2401
2460
|
function dndzone$1(node, options) {
|
|
2461
|
+
var destroyed = false;
|
|
2402
2462
|
var config = {
|
|
2403
2463
|
items: undefined,
|
|
2404
2464
|
type: undefined,
|
|
@@ -2623,9 +2683,25 @@ function dndzone$1(node, options) {
|
|
|
2623
2683
|
configure(newOptions);
|
|
2624
2684
|
},
|
|
2625
2685
|
destroy: function destroy() {
|
|
2686
|
+
if (destroyed) return;
|
|
2687
|
+
destroyed = true;
|
|
2626
2688
|
printDebug(function () {
|
|
2627
2689
|
return "keyboard dndzone will destroy";
|
|
2628
2690
|
});
|
|
2691
|
+
node.removeEventListener("focus", handleZoneFocus);
|
|
2692
|
+
var _iterator = _createForOfIteratorHelper(node.children),
|
|
2693
|
+
_step;
|
|
2694
|
+
try {
|
|
2695
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
2696
|
+
var draggableEl = _step.value;
|
|
2697
|
+
draggableEl.removeEventListener("keydown", elToKeyDownListeners.get(draggableEl));
|
|
2698
|
+
draggableEl.removeEventListener("click", elToFocusListeners.get(draggableEl));
|
|
2699
|
+
}
|
|
2700
|
+
} catch (err) {
|
|
2701
|
+
_iterator.e(err);
|
|
2702
|
+
} finally {
|
|
2703
|
+
_iterator.f();
|
|
2704
|
+
}
|
|
2629
2705
|
unregisterDropZone(node, config.type);
|
|
2630
2706
|
dzToConfig["delete"](node);
|
|
2631
2707
|
dzToHandles["delete"](node);
|
|
@@ -2834,6 +2910,8 @@ function dragHandleZone(node, options) {
|
|
|
2834
2910
|
updateZone();
|
|
2835
2911
|
},
|
|
2836
2912
|
destroy: function destroy() {
|
|
2913
|
+
isItemsDragDisabled.set(true);
|
|
2914
|
+
zone.destroy();
|
|
2837
2915
|
node.removeEventListener("consider", consider);
|
|
2838
2916
|
node.removeEventListener("finalize", finalize);
|
|
2839
2917
|
isItemsDragDisabled.unsubscribe(updateZone);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-dnd-action",
|
|
3
3
|
"description": "*An awesome drag and drop library for Svelte 3 and 4 (not using the browser's built-in dnd, thanks god): Rich animations, nested containers, touch support and more *",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.72",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/isaacHagoel/svelte-dnd-action.git"
|
package/src/keyboardAction.js
CHANGED
|
@@ -50,12 +50,13 @@ function registerDropZone(dropZoneEl, type) {
|
|
|
50
50
|
}
|
|
51
51
|
function unregisterDropZone(dropZoneEl, type) {
|
|
52
52
|
printDebug(() => "unregistering drop-zone");
|
|
53
|
-
if (focusedDz === dropZoneEl) {
|
|
53
|
+
if (isDragging && focusedDz === dropZoneEl) {
|
|
54
54
|
handleDrop();
|
|
55
55
|
}
|
|
56
|
-
typeToDropZones.get(type)
|
|
56
|
+
const dropZones = typeToDropZones.get(type);
|
|
57
|
+
if (!dropZones || !dropZones.delete(dropZoneEl)) return;
|
|
57
58
|
decrementActiveDropZoneCount();
|
|
58
|
-
if (
|
|
59
|
+
if (dropZones.size === 0) {
|
|
59
60
|
typeToDropZones.delete(type);
|
|
60
61
|
}
|
|
61
62
|
if (typeToDropZones.size === 0) {
|
|
@@ -112,9 +113,12 @@ function handleZoneFocus(e) {
|
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
const dzFrom = focusedDz;
|
|
115
|
-
|
|
116
|
-
dispatchFinalizeEvent(newlyFocusedDz, targetItems, {trigger: TRIGGERS.DROPPED_INTO_ZONE, id: focusedItemId, source: SOURCES.KEYBOARD});
|
|
116
|
+
const movedItemId = focusedItemId;
|
|
117
117
|
focusedDz = newlyFocusedDz;
|
|
118
|
+
dispatchFinalizeEvent(dzFrom, originItems, {trigger: TRIGGERS.DROPPED_INTO_ANOTHER, id: movedItemId, source: SOURCES.KEYBOARD});
|
|
119
|
+
if (dzToConfig.has(newlyFocusedDz)) {
|
|
120
|
+
dispatchFinalizeEvent(newlyFocusedDz, targetItems, {trigger: TRIGGERS.DROPPED_INTO_ZONE, id: movedItemId, source: SOURCES.KEYBOARD});
|
|
121
|
+
}
|
|
118
122
|
}
|
|
119
123
|
|
|
120
124
|
function triggerAllDzsUpdate() {
|
|
@@ -122,25 +126,22 @@ function triggerAllDzsUpdate() {
|
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
function handleDrop(dispatchConsider = true) {
|
|
129
|
+
if (!isDragging || !focusedDz) return;
|
|
125
130
|
printDebug(() => "drop");
|
|
126
|
-
|
|
131
|
+
const droppedDz = focusedDz;
|
|
132
|
+
const droppedConfig = dzToConfig.get(droppedDz);
|
|
133
|
+
const droppedItemId = focusedItemId;
|
|
134
|
+
const droppedItemType = draggedItemType;
|
|
135
|
+
if (!droppedConfig) return;
|
|
136
|
+
|
|
137
|
+
if (!droppedConfig.autoAriaDisabled) {
|
|
127
138
|
alertToScreenReader(`Stopped dragging item ${focusedItemLabel}`);
|
|
128
139
|
}
|
|
129
140
|
if (allDragTargets.has(document.activeElement)) {
|
|
130
141
|
document.activeElement.blur();
|
|
131
142
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
trigger: TRIGGERS.DRAG_STOPPED,
|
|
135
|
-
id: focusedItemId,
|
|
136
|
-
source: SOURCES.KEYBOARD
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
styleInactiveDropZones(
|
|
140
|
-
typeToDropZones.get(draggedItemType),
|
|
141
|
-
dz => dzToConfig.get(dz).dropTargetStyle,
|
|
142
|
-
dz => dzToConfig.get(dz).dropTargetClasses
|
|
143
|
-
);
|
|
143
|
+
// Clear global drag state before dispatching. A synchronous handler may destroy the
|
|
144
|
+
// focused zone, and unregisterDropZone must not recursively enter handleDrop.
|
|
144
145
|
focusedItem = null;
|
|
145
146
|
focusedItemId = null;
|
|
146
147
|
focusedItemLabel = "";
|
|
@@ -148,10 +149,27 @@ function handleDrop(dispatchConsider = true) {
|
|
|
148
149
|
focusedDz = null;
|
|
149
150
|
focusedDzLabel = "";
|
|
150
151
|
isDragging = false;
|
|
152
|
+
|
|
153
|
+
if (dispatchConsider) {
|
|
154
|
+
dispatchConsiderEvent(droppedDz, droppedConfig.items, {
|
|
155
|
+
trigger: TRIGGERS.DRAG_STOPPED,
|
|
156
|
+
id: droppedItemId,
|
|
157
|
+
source: SOURCES.KEYBOARD
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
const dropZones = typeToDropZones.get(droppedItemType);
|
|
161
|
+
if (dropZones) {
|
|
162
|
+
styleInactiveDropZones(
|
|
163
|
+
dropZones,
|
|
164
|
+
dz => dzToConfig.get(dz).dropTargetStyle,
|
|
165
|
+
dz => dzToConfig.get(dz).dropTargetClasses
|
|
166
|
+
);
|
|
167
|
+
}
|
|
151
168
|
triggerAllDzsUpdate();
|
|
152
169
|
}
|
|
153
170
|
//////
|
|
154
171
|
export function dndzone(node, options) {
|
|
172
|
+
let destroyed = false;
|
|
155
173
|
const config = {
|
|
156
174
|
items: undefined,
|
|
157
175
|
type: undefined,
|
|
@@ -344,7 +362,14 @@ export function dndzone(node, options) {
|
|
|
344
362
|
configure(newOptions);
|
|
345
363
|
},
|
|
346
364
|
destroy: () => {
|
|
365
|
+
if (destroyed) return;
|
|
366
|
+
destroyed = true;
|
|
347
367
|
printDebug(() => "keyboard dndzone will destroy");
|
|
368
|
+
node.removeEventListener("focus", handleZoneFocus);
|
|
369
|
+
for (const draggableEl of node.children) {
|
|
370
|
+
draggableEl.removeEventListener("keydown", elToKeyDownListeners.get(draggableEl));
|
|
371
|
+
draggableEl.removeEventListener("click", elToFocusListeners.get(draggableEl));
|
|
372
|
+
}
|
|
348
373
|
unregisterDropZone(node, config.type);
|
|
349
374
|
dzToConfig.delete(node);
|
|
350
375
|
dzToHandles.delete(node);
|
package/src/pointerAction.js
CHANGED
|
@@ -64,6 +64,8 @@ let multiScroller;
|
|
|
64
64
|
let touchDragHoldTimer;
|
|
65
65
|
let touchHoldElapsed = false;
|
|
66
66
|
let useCursorForDetectionActive = false;
|
|
67
|
+
let pendingDragOwner;
|
|
68
|
+
let watchedDropZones = new Set();
|
|
67
69
|
|
|
68
70
|
// a map from type to a set of drop-zones
|
|
69
71
|
const typeToDropZones = new Map();
|
|
@@ -84,9 +86,10 @@ function registerDropZone(dropZoneEl, type) {
|
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
function unregisterDropZone(dropZoneEl, type) {
|
|
87
|
-
typeToDropZones.get(type)
|
|
89
|
+
const dropZones = typeToDropZones.get(type);
|
|
90
|
+
if (!dropZones || !dropZones.delete(dropZoneEl)) return;
|
|
88
91
|
decrementActiveDropZoneCount();
|
|
89
|
-
if (
|
|
92
|
+
if (dropZones.size === 0) {
|
|
90
93
|
typeToDropZones.delete(type);
|
|
91
94
|
}
|
|
92
95
|
}
|
|
@@ -95,8 +98,11 @@ function unregisterDropZone(dropZoneEl, type) {
|
|
|
95
98
|
function watchDraggedElement() {
|
|
96
99
|
printDebug(() => "watching dragged element");
|
|
97
100
|
const dropZones = typeToDropZones.get(draggedElType);
|
|
101
|
+
if (!dropZones || dropZones.size === 0) return;
|
|
102
|
+
if (watchedDropZones.size > 0) unWatchDraggedElement();
|
|
103
|
+
watchedDropZones = new Set(dropZones);
|
|
98
104
|
|
|
99
|
-
for (const dz of
|
|
105
|
+
for (const dz of watchedDropZones) {
|
|
100
106
|
dz.addEventListener(DRAGGED_ENTERED_EVENT_NAME, handleDraggedEntered);
|
|
101
107
|
dz.addEventListener(DRAGGED_LEFT_EVENT_NAME, handleDraggedLeft);
|
|
102
108
|
dz.addEventListener(DRAGGED_OVER_INDEX_EVENT_NAME, handleDraggedIsOverIndex);
|
|
@@ -104,9 +110,9 @@ function watchDraggedElement() {
|
|
|
104
110
|
window.addEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
|
|
105
111
|
|
|
106
112
|
// it is important that we don't have an interval that is faster than the flip duration because it can cause elements to jump bach and forth
|
|
107
|
-
const setIntervalMs = Math.max(...Array.from(
|
|
113
|
+
const setIntervalMs = Math.max(...Array.from(watchedDropZones).map(dz => dzToConfig.get(dz).dropAnimationDurationMs));
|
|
108
114
|
const observationIntervalMs = setIntervalMs === 0 ? DISABLED_OBSERVATION_INTERVAL_MS : Math.max(setIntervalMs, MIN_OBSERVATION_INTERVAL_MS); // if setIntervalMs is 0 it goes to 20, otherwise it is max between it and min observation.
|
|
109
|
-
multiScroller = createMultiScroller(
|
|
115
|
+
multiScroller = createMultiScroller(watchedDropZones, () => currentMousePosition);
|
|
110
116
|
// Returns reference point in document coordinates - either cursor position or element center
|
|
111
117
|
const getReferencePoint = useCursorForDetectionActive
|
|
112
118
|
? () => ({
|
|
@@ -114,16 +120,16 @@ function watchDraggedElement() {
|
|
|
114
120
|
y: currentMousePosition.y + window.scrollY
|
|
115
121
|
})
|
|
116
122
|
: () => findCenterOfElement(draggedEl);
|
|
117
|
-
observe(draggedEl,
|
|
123
|
+
observe(draggedEl, watchedDropZones, observationIntervalMs * 1.07, multiScroller, getReferencePoint);
|
|
118
124
|
}
|
|
119
125
|
function unWatchDraggedElement() {
|
|
120
126
|
printDebug(() => "unwatching dragged element");
|
|
121
|
-
const
|
|
122
|
-
for (const dz of dropZones) {
|
|
127
|
+
for (const dz of watchedDropZones) {
|
|
123
128
|
dz.removeEventListener(DRAGGED_ENTERED_EVENT_NAME, handleDraggedEntered);
|
|
124
129
|
dz.removeEventListener(DRAGGED_LEFT_EVENT_NAME, handleDraggedLeft);
|
|
125
130
|
dz.removeEventListener(DRAGGED_OVER_INDEX_EVENT_NAME, handleDraggedIsOverIndex);
|
|
126
131
|
}
|
|
132
|
+
watchedDropZones = new Set();
|
|
127
133
|
window.removeEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
|
|
128
134
|
// ensuring multiScroller is not already destroyed before destroying
|
|
129
135
|
if (multiScroller) {
|
|
@@ -268,6 +274,9 @@ function handleDrop() {
|
|
|
268
274
|
|
|
269
275
|
items = items.map(item => (item[SHADOW_ITEM_MARKER_PROPERTY_NAME] ? draggedElData : item));
|
|
270
276
|
function finalizeWithinZone() {
|
|
277
|
+
// The original-element rAF loop may have re-armed observation during the settle animation.
|
|
278
|
+
// Cancel again before dispatching events that can update or destroy drop zones.
|
|
279
|
+
unWatchDraggedElement();
|
|
271
280
|
unlockOriginDzMinDimensions();
|
|
272
281
|
dispatchFinalizeEvent(shadowElDropZone, items, {
|
|
273
282
|
trigger: isDraggedOutsideOfAnyDz ? TRIGGERS.DROPPED_OUTSIDE_OF_ANY : TRIGGERS.DROPPED_INTO_ZONE,
|
|
@@ -312,8 +321,10 @@ function animateDraggedToFinalPosition(shadowElIdx, callback) {
|
|
|
312
321
|
}
|
|
313
322
|
|
|
314
323
|
function scheduleDZForRemovalAfterDrop(dz, destroy) {
|
|
315
|
-
|
|
324
|
+
const scheduledRemoval = {dz, destroy};
|
|
325
|
+
scheduledForRemovalAfterDrop.push(scheduledRemoval);
|
|
316
326
|
window.requestAnimationFrame(() => {
|
|
327
|
+
if (!scheduledForRemovalAfterDrop.includes(scheduledRemoval)) return;
|
|
317
328
|
hideElement(dz);
|
|
318
329
|
document.body.appendChild(dz);
|
|
319
330
|
});
|
|
@@ -348,6 +359,7 @@ function cleanupPostDrop() {
|
|
|
348
359
|
touchDragHoldTimer = undefined;
|
|
349
360
|
touchHoldElapsed = false;
|
|
350
361
|
useCursorForDetectionActive = false;
|
|
362
|
+
pendingDragOwner = undefined;
|
|
351
363
|
if (scheduledForRemovalAfterDrop.length) {
|
|
352
364
|
printDebug(() => ["will destroy zones that were removed during drag", scheduledForRemovalAfterDrop]);
|
|
353
365
|
scheduledForRemovalAfterDrop.forEach(({dz, destroy}) => {
|
|
@@ -360,6 +372,7 @@ function cleanupPostDrop() {
|
|
|
360
372
|
|
|
361
373
|
export function dndzone(node, options) {
|
|
362
374
|
let initialized = false;
|
|
375
|
+
let destroyed = false;
|
|
363
376
|
const config = {
|
|
364
377
|
items: undefined,
|
|
365
378
|
type: undefined,
|
|
@@ -395,11 +408,17 @@ export function dndzone(node, options) {
|
|
|
395
408
|
touchHoldElapsed = false;
|
|
396
409
|
}
|
|
397
410
|
}
|
|
398
|
-
function
|
|
411
|
+
function cancelPendingDrag() {
|
|
412
|
+
if (pendingDragOwner !== node) return;
|
|
399
413
|
removeMaybeListeners();
|
|
414
|
+
pendingDragOwner = undefined;
|
|
400
415
|
originalDragTarget = undefined;
|
|
401
416
|
dragStartMousePosition = undefined;
|
|
402
417
|
currentMousePosition = undefined;
|
|
418
|
+
}
|
|
419
|
+
function handleFalseAlarm(e) {
|
|
420
|
+
if (pendingDragOwner !== node) return;
|
|
421
|
+
cancelPendingDrag();
|
|
403
422
|
|
|
404
423
|
// dragging initiated by touch events prevents onclick from initially firing
|
|
405
424
|
if (e.type === "touchend") {
|
|
@@ -413,6 +432,7 @@ export function dndzone(node, options) {
|
|
|
413
432
|
}
|
|
414
433
|
|
|
415
434
|
function handleMouseMoveMaybeDragStart(e) {
|
|
435
|
+
if (destroyed || pendingDragOwner !== node) return;
|
|
416
436
|
const isTouch = !!e.touches;
|
|
417
437
|
const c = isTouch ? e.touches[0] : e;
|
|
418
438
|
// If touch drag delay is configured and not elapsed yet, allow scrolling until either
|
|
@@ -442,7 +462,6 @@ export function dndzone(node, options) {
|
|
|
442
462
|
Math.abs(currentMousePosition.x - dragStartMousePosition.x) >= MIN_MOVEMENT_BEFORE_DRAG_START_PX ||
|
|
443
463
|
Math.abs(currentMousePosition.y - dragStartMousePosition.y) >= MIN_MOVEMENT_BEFORE_DRAG_START_PX
|
|
444
464
|
) {
|
|
445
|
-
removeMaybeListeners();
|
|
446
465
|
handleDragStart();
|
|
447
466
|
}
|
|
448
467
|
}
|
|
@@ -457,8 +476,8 @@ export function dndzone(node, options) {
|
|
|
457
476
|
printDebug(() => `ignoring none left click button: ${e.button}`);
|
|
458
477
|
return;
|
|
459
478
|
}
|
|
460
|
-
if (isWorkingOnPreviousDrag) {
|
|
461
|
-
printDebug(() => "cannot start a new drag before finalizing
|
|
479
|
+
if (destroyed || isWorkingOnPreviousDrag || pendingDragOwner) {
|
|
480
|
+
printDebug(() => "cannot start a new drag before finalizing the current drag or pending gesture");
|
|
462
481
|
return;
|
|
463
482
|
}
|
|
464
483
|
const isTouchStart = !!e.touches;
|
|
@@ -468,6 +487,7 @@ export function dndzone(node, options) {
|
|
|
468
487
|
e.preventDefault();
|
|
469
488
|
}
|
|
470
489
|
e.stopPropagation();
|
|
490
|
+
pendingDragOwner = node;
|
|
471
491
|
|
|
472
492
|
const c = isTouchStart ? e.touches[0] : e;
|
|
473
493
|
dragStartMousePosition = {x: c.clientX, y: c.clientY};
|
|
@@ -475,12 +495,12 @@ export function dndzone(node, options) {
|
|
|
475
495
|
originalDragTarget = e.currentTarget;
|
|
476
496
|
|
|
477
497
|
if (useDelay) {
|
|
498
|
+
const pendingTarget = originalDragTarget;
|
|
478
499
|
touchHoldElapsed = false;
|
|
479
500
|
touchDragHoldTimer = window.setTimeout(() => {
|
|
480
|
-
// If the
|
|
481
|
-
if (
|
|
501
|
+
// If this action still owns the same pending gesture, transition it to a drag.
|
|
502
|
+
if (destroyed || pendingDragOwner !== node || originalDragTarget !== pendingTarget) return;
|
|
482
503
|
touchHoldElapsed = true;
|
|
483
|
-
removeMaybeListeners();
|
|
484
504
|
handleDragStart();
|
|
485
505
|
}, config.delayTouchStartMs);
|
|
486
506
|
}
|
|
@@ -489,6 +509,12 @@ export function dndzone(node, options) {
|
|
|
489
509
|
}
|
|
490
510
|
|
|
491
511
|
function handleDragStart() {
|
|
512
|
+
if (destroyed || pendingDragOwner !== node || isWorkingOnPreviousDrag || !originalDragTarget?.parentElement) {
|
|
513
|
+
cancelPendingDrag();
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
removeMaybeListeners();
|
|
517
|
+
pendingDragOwner = undefined;
|
|
492
518
|
printDebug(() => [`drag start config: ${toString(config)}`, originalDragTarget]);
|
|
493
519
|
isWorkingOnPreviousDrag = true;
|
|
494
520
|
|
|
@@ -511,11 +537,10 @@ export function dndzone(node, options) {
|
|
|
511
537
|
originDropZoneRoot.appendChild(draggedEl);
|
|
512
538
|
// We will keep the original dom node in the dom because touch events keep firing on it, we want to re-add it after the framework removes it
|
|
513
539
|
function keepOriginalElementInDom() {
|
|
514
|
-
//
|
|
515
|
-
// must not re-arm
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
if (!draggedEl) return;
|
|
540
|
+
// Once the drop starts finalizing, handleDrop has stopped observation and this loop
|
|
541
|
+
// must not re-arm it during the settle animation. After cleanup, draggedEl is cleared
|
|
542
|
+
// as an additional guard against the original element leaving the DOM much later.
|
|
543
|
+
if (!draggedEl || finalizingPreviousDrag) return;
|
|
519
544
|
if (!originalDragTarget.parentElement) {
|
|
520
545
|
originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
|
|
521
546
|
originDropZoneRoot.appendChild(originalDragTarget);
|
|
@@ -668,9 +693,18 @@ export function dndzone(node, options) {
|
|
|
668
693
|
configure(newOptions);
|
|
669
694
|
},
|
|
670
695
|
destroy: () => {
|
|
696
|
+
if (destroyed) return;
|
|
697
|
+
destroyed = true;
|
|
698
|
+
cancelPendingDrag();
|
|
699
|
+
for (const draggableEl of node.children) {
|
|
700
|
+
draggableEl.removeEventListener("mousedown", elToMouseDownListener.get(draggableEl));
|
|
701
|
+
draggableEl.removeEventListener("touchstart", elToMouseDownListener.get(draggableEl));
|
|
702
|
+
}
|
|
671
703
|
function destroyDz() {
|
|
672
704
|
printDebug(() => "pointer dndzone will destroy");
|
|
673
|
-
|
|
705
|
+
const registeredConfig = dzToConfig.get(node);
|
|
706
|
+
if (!registeredConfig) return;
|
|
707
|
+
unregisterDropZone(node, registeredConfig.type);
|
|
674
708
|
dzToConfig.delete(node);
|
|
675
709
|
}
|
|
676
710
|
if (isWorkingOnPreviousDrag && !node.closest(`[${ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE}]`)) {
|
|
@@ -77,6 +77,8 @@ export function dragHandleZone(node, options) {
|
|
|
77
77
|
updateZone();
|
|
78
78
|
},
|
|
79
79
|
destroy: () => {
|
|
80
|
+
isItemsDragDisabled.set(true);
|
|
81
|
+
zone.destroy();
|
|
80
82
|
node.removeEventListener("consider", consider);
|
|
81
83
|
node.removeEventListener("finalize", finalize);
|
|
82
84
|
isItemsDragDisabled.unsubscribe(updateZone);
|