svelte-dnd-action 0.9.27 → 0.9.29
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/README.md +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -28
- package/dist/index.mjs +26 -28
- package/package.json +2 -2
- package/src/action.js +17 -1
- package/src/constants.js +2 -1
- package/src/pointerAction.js +8 -23
package/README.md
CHANGED
|
@@ -347,6 +347,32 @@ You can use generics to set the type of `items` you are expecting in `DndEvent`.
|
|
|
347
347
|
</script>
|
|
348
348
|
```
|
|
349
349
|
|
|
350
|
+
### Nested Zones Optional Optimization (experimental)
|
|
351
|
+
|
|
352
|
+
This is an experimental feature added in version 0.9.29. If you have multiple levels of nesting, the lib might do unnecessary work when dragging an element that has nested zones inside.
|
|
353
|
+
Specifically, it allows nested zones within the shadow element (the placeholder under the dragged element) to register and destroy.
|
|
354
|
+
This is because Svelte calls nested actions before the parent action (opposite to the rendering order).
|
|
355
|
+
You can use a data attribute **on the items** to help the lib prevent this: `data-is-dnd-shadow-item-hint={item[SHADOW_ITEM_MARKER_PROPERTY_NAME]} `
|
|
356
|
+
|
|
357
|
+
#### Simplified Example (just shows where to place the attribute):
|
|
358
|
+
|
|
359
|
+
```html
|
|
360
|
+
<script>
|
|
361
|
+
import {dndzone, SHADOW_ITEM_MARKER_PROPERTY_NAME} from 'svelte-dnd-action';
|
|
362
|
+
let items = [];
|
|
363
|
+
</script>
|
|
364
|
+
<section>
|
|
365
|
+
<div use:dndzone={{items}} on:consider={e => items = e.detail.items} on:finalize={e => items = e.detail.items}>
|
|
366
|
+
{#each items as item (item.id)}
|
|
367
|
+
<div data-is-dnd-shadow-item-hint={item[SHADOW_ITEM_MARKER_PROPERTY_NAME]}>
|
|
368
|
+
<h1>{item.title}</h1>
|
|
369
|
+
<!--more nested zones go here, can include the attribute on their items as demonstrated above-->
|
|
370
|
+
</div>
|
|
371
|
+
{/each}
|
|
372
|
+
</div>
|
|
373
|
+
</section>
|
|
374
|
+
```
|
|
375
|
+
|
|
350
376
|
### Contributing [](https://github.com/isaacHagoel/svelte-dnd-action/issues)
|
|
351
377
|
|
|
352
378
|
There is still quite a lot to do. If you'd like to contribute please get in touch (raise an issue or comment on an existing one).
|
package/dist/index.d.ts
CHANGED
|
@@ -78,6 +78,7 @@ export type DndEvent<T = Item> = {
|
|
|
78
78
|
export declare const SHADOW_ITEM_MARKER_PROPERTY_NAME: "isDndShadowItem";
|
|
79
79
|
export declare const SHADOW_PLACEHOLDER_ITEM_ID: "id:dnd-shadow-placeholder-0000";
|
|
80
80
|
export declare const DRAGGED_ELEMENT_ID: "dnd-action-dragged-el";
|
|
81
|
+
export declare const SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-hint";
|
|
81
82
|
|
|
82
83
|
/**
|
|
83
84
|
* Allows the user to show/hide console debug output
|
package/dist/index.js
CHANGED
|
@@ -294,7 +294,8 @@
|
|
|
294
294
|
KEYBOARD: "keyboard"
|
|
295
295
|
};
|
|
296
296
|
var SHADOW_ITEM_MARKER_PROPERTY_NAME = "isDndShadowItem";
|
|
297
|
-
var SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item";
|
|
297
|
+
var SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-internal";
|
|
298
|
+
var SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-hint";
|
|
298
299
|
var SHADOW_PLACEHOLDER_ITEM_ID = "id:dnd-shadow-placeholder-0000";
|
|
299
300
|
var DRAGGED_ELEMENT_ID = "dnd-action-dragged-el";
|
|
300
301
|
var ITEM_ID_KEY = "id";
|
|
@@ -1229,6 +1230,7 @@
|
|
|
1229
1230
|
var DEFAULT_DROP_TARGET_STYLE = {
|
|
1230
1231
|
outline: "rgba(255, 255, 102, 0.7) solid 2px"
|
|
1231
1232
|
};
|
|
1233
|
+
var ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE = "data-is-dnd-original-dragged-item";
|
|
1232
1234
|
var originalDragTarget;
|
|
1233
1235
|
var draggedEl;
|
|
1234
1236
|
var draggedElData;
|
|
@@ -1263,10 +1265,6 @@
|
|
|
1263
1265
|
if (!typeToDropZones.get(type).has(dropZoneEl)) {
|
|
1264
1266
|
typeToDropZones.get(type).add(dropZoneEl);
|
|
1265
1267
|
incrementActiveDropZoneCount();
|
|
1266
|
-
if (isWorkingOnPreviousDrag) {
|
|
1267
|
-
unWatchDraggedElement();
|
|
1268
|
-
watchDraggedElement();
|
|
1269
|
-
}
|
|
1270
1268
|
}
|
|
1271
1269
|
}
|
|
1272
1270
|
function unregisterDropZone(dropZoneEl, type) {
|
|
@@ -1328,17 +1326,9 @@
|
|
|
1328
1326
|
window.removeEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
|
|
1329
1327
|
unobserve();
|
|
1330
1328
|
}
|
|
1331
|
-
|
|
1332
|
-
// finds the initial placeholder that is placed there on drag start
|
|
1333
|
-
function findShadowPlaceHolderIdx(items) {
|
|
1334
|
-
return items.findIndex(function (item) {
|
|
1335
|
-
return item[ITEM_ID_KEY] === SHADOW_PLACEHOLDER_ITEM_ID;
|
|
1336
|
-
});
|
|
1337
|
-
}
|
|
1338
1329
|
function findShadowElementIdx(items) {
|
|
1339
|
-
// checking that the id is not the placeholder's for Dragula like usecases
|
|
1340
1330
|
return items.findIndex(function (item) {
|
|
1341
|
-
return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME]
|
|
1331
|
+
return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME];
|
|
1342
1332
|
});
|
|
1343
1333
|
}
|
|
1344
1334
|
|
|
@@ -1374,15 +1364,6 @@
|
|
|
1374
1364
|
id: draggedElData[ITEM_ID_KEY],
|
|
1375
1365
|
source: SOURCES.POINTER
|
|
1376
1366
|
});
|
|
1377
|
-
} else {
|
|
1378
|
-
var shadowPlaceHolderIdx = findShadowPlaceHolderIdx(items);
|
|
1379
|
-
if (shadowPlaceHolderIdx !== -1) {
|
|
1380
|
-
// only happens right after drag start, on the first drag entered event
|
|
1381
|
-
printDebug(function () {
|
|
1382
|
-
return "removing placeholder item from origin dz";
|
|
1383
|
-
});
|
|
1384
|
-
items.splice(shadowPlaceHolderIdx, 1);
|
|
1385
|
-
}
|
|
1386
1367
|
}
|
|
1387
1368
|
var _e$detail$indexObj = e.detail.indexObj,
|
|
1388
1369
|
index = _e$detail$indexObj.index,
|
|
@@ -1675,6 +1656,7 @@
|
|
|
1675
1656
|
addMaybeListeners();
|
|
1676
1657
|
}
|
|
1677
1658
|
function handleDragStart() {
|
|
1659
|
+
var _objectSpread2$1;
|
|
1678
1660
|
printDebug(function () {
|
|
1679
1661
|
return ["drag start config: ".concat(toString(config)), originalDragTarget];
|
|
1680
1662
|
});
|
|
@@ -1692,12 +1674,12 @@
|
|
|
1692
1674
|
centreDraggedOnCursor = config.centreDraggedOnCursor;
|
|
1693
1675
|
draggedElData = _objectSpread2({}, items[currentIdx]);
|
|
1694
1676
|
draggedElType = type;
|
|
1695
|
-
shadowElData = _objectSpread2(_objectSpread2({}, draggedElData), {},
|
|
1696
|
-
// The initial shadow element. We need a different id at first in order to avoid conflicts and timing issues
|
|
1697
|
-
var placeHolderElData = _objectSpread2(_objectSpread2({}, shadowElData), {}, _defineProperty({}, ITEM_ID_KEY, SHADOW_PLACEHOLDER_ITEM_ID));
|
|
1677
|
+
shadowElData = _objectSpread2(_objectSpread2({}, draggedElData), {}, (_objectSpread2$1 = {}, _defineProperty(_objectSpread2$1, SHADOW_ITEM_MARKER_PROPERTY_NAME, true), _defineProperty(_objectSpread2$1, ITEM_ID_KEY, SHADOW_PLACEHOLDER_ITEM_ID), _objectSpread2$1));
|
|
1698
1678
|
|
|
1699
1679
|
// creating the draggable element
|
|
1700
1680
|
draggedEl = createDraggedElementFrom(originalDragTarget, centreDraggedOnCursor && currentMousePosition);
|
|
1681
|
+
originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
|
|
1682
|
+
|
|
1701
1683
|
// 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
|
|
1702
1684
|
function keepOriginalElementInDom() {
|
|
1703
1685
|
if (!draggedEl.parentElement) {
|
|
@@ -1721,7 +1703,7 @@
|
|
|
1721
1703
|
});
|
|
1722
1704
|
|
|
1723
1705
|
// removing the original element by removing its data entry
|
|
1724
|
-
items.splice(currentIdx, 1,
|
|
1706
|
+
items.splice(currentIdx, 1, shadowElData);
|
|
1725
1707
|
unlockOriginDzMinDimensions = preventShrinking(originDropZone);
|
|
1726
1708
|
dispatchConsiderEvent(originDropZone, items, {
|
|
1727
1709
|
trigger: TRIGGERS.DRAG_STARTED,
|
|
@@ -1856,7 +1838,7 @@
|
|
|
1856
1838
|
unregisterDropZone(node, dzToConfig.get(node).type);
|
|
1857
1839
|
dzToConfig["delete"](node);
|
|
1858
1840
|
}
|
|
1859
|
-
if (isWorkingOnPreviousDrag) {
|
|
1841
|
+
if (isWorkingOnPreviousDrag && !node.closest("[".concat(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, "]"))) {
|
|
1860
1842
|
printDebug(function () {
|
|
1861
1843
|
return "pointer dndzone will be scheduled for destruction";
|
|
1862
1844
|
});
|
|
@@ -2386,6 +2368,12 @@
|
|
|
2386
2368
|
* @return {{update: function, destroy: function}}
|
|
2387
2369
|
*/
|
|
2388
2370
|
function dndzone$2(node, options) {
|
|
2371
|
+
if (shouldIgnoreZone(node)) {
|
|
2372
|
+
return {
|
|
2373
|
+
update: function update() {},
|
|
2374
|
+
destroy: function destroy() {}
|
|
2375
|
+
};
|
|
2376
|
+
}
|
|
2389
2377
|
validateOptions(options);
|
|
2390
2378
|
var pointerZone = dndzone(node, options);
|
|
2391
2379
|
var keyboardZone = dndzone$1(node, options);
|
|
@@ -2401,6 +2389,16 @@
|
|
|
2401
2389
|
}
|
|
2402
2390
|
};
|
|
2403
2391
|
}
|
|
2392
|
+
|
|
2393
|
+
/**
|
|
2394
|
+
* If the user marked something in the ancestry of our node as shadow element, we can ignore it
|
|
2395
|
+
* We need the user to mark it for us because svelte updates the action from deep to shallow (but renders top down)
|
|
2396
|
+
* @param {HTMLElement} node
|
|
2397
|
+
* @return {boolean}
|
|
2398
|
+
*/
|
|
2399
|
+
function shouldIgnoreZone(node) {
|
|
2400
|
+
return !!node.closest("[".concat(SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME, "=\"true\"]"));
|
|
2401
|
+
}
|
|
2404
2402
|
function validateOptions(options) {
|
|
2405
2403
|
/*eslint-disable*/
|
|
2406
2404
|
var items = options.items,
|
package/dist/index.mjs
CHANGED
|
@@ -288,7 +288,8 @@ var SOURCES = {
|
|
|
288
288
|
KEYBOARD: "keyboard"
|
|
289
289
|
};
|
|
290
290
|
var SHADOW_ITEM_MARKER_PROPERTY_NAME = "isDndShadowItem";
|
|
291
|
-
var SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item";
|
|
291
|
+
var SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-internal";
|
|
292
|
+
var SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-hint";
|
|
292
293
|
var SHADOW_PLACEHOLDER_ITEM_ID = "id:dnd-shadow-placeholder-0000";
|
|
293
294
|
var DRAGGED_ELEMENT_ID = "dnd-action-dragged-el";
|
|
294
295
|
var ITEM_ID_KEY = "id";
|
|
@@ -1223,6 +1224,7 @@ var MIN_MOVEMENT_BEFORE_DRAG_START_PX = 3;
|
|
|
1223
1224
|
var DEFAULT_DROP_TARGET_STYLE = {
|
|
1224
1225
|
outline: "rgba(255, 255, 102, 0.7) solid 2px"
|
|
1225
1226
|
};
|
|
1227
|
+
var ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE = "data-is-dnd-original-dragged-item";
|
|
1226
1228
|
var originalDragTarget;
|
|
1227
1229
|
var draggedEl;
|
|
1228
1230
|
var draggedElData;
|
|
@@ -1257,10 +1259,6 @@ function registerDropZone(dropZoneEl, type) {
|
|
|
1257
1259
|
if (!typeToDropZones.get(type).has(dropZoneEl)) {
|
|
1258
1260
|
typeToDropZones.get(type).add(dropZoneEl);
|
|
1259
1261
|
incrementActiveDropZoneCount();
|
|
1260
|
-
if (isWorkingOnPreviousDrag) {
|
|
1261
|
-
unWatchDraggedElement();
|
|
1262
|
-
watchDraggedElement();
|
|
1263
|
-
}
|
|
1264
1262
|
}
|
|
1265
1263
|
}
|
|
1266
1264
|
function unregisterDropZone(dropZoneEl, type) {
|
|
@@ -1322,17 +1320,9 @@ function unWatchDraggedElement() {
|
|
|
1322
1320
|
window.removeEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
|
|
1323
1321
|
unobserve();
|
|
1324
1322
|
}
|
|
1325
|
-
|
|
1326
|
-
// finds the initial placeholder that is placed there on drag start
|
|
1327
|
-
function findShadowPlaceHolderIdx(items) {
|
|
1328
|
-
return items.findIndex(function (item) {
|
|
1329
|
-
return item[ITEM_ID_KEY] === SHADOW_PLACEHOLDER_ITEM_ID;
|
|
1330
|
-
});
|
|
1331
|
-
}
|
|
1332
1323
|
function findShadowElementIdx(items) {
|
|
1333
|
-
// checking that the id is not the placeholder's for Dragula like usecases
|
|
1334
1324
|
return items.findIndex(function (item) {
|
|
1335
|
-
return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME]
|
|
1325
|
+
return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME];
|
|
1336
1326
|
});
|
|
1337
1327
|
}
|
|
1338
1328
|
|
|
@@ -1368,15 +1358,6 @@ function handleDraggedEntered(e) {
|
|
|
1368
1358
|
id: draggedElData[ITEM_ID_KEY],
|
|
1369
1359
|
source: SOURCES.POINTER
|
|
1370
1360
|
});
|
|
1371
|
-
} else {
|
|
1372
|
-
var shadowPlaceHolderIdx = findShadowPlaceHolderIdx(items);
|
|
1373
|
-
if (shadowPlaceHolderIdx !== -1) {
|
|
1374
|
-
// only happens right after drag start, on the first drag entered event
|
|
1375
|
-
printDebug(function () {
|
|
1376
|
-
return "removing placeholder item from origin dz";
|
|
1377
|
-
});
|
|
1378
|
-
items.splice(shadowPlaceHolderIdx, 1);
|
|
1379
|
-
}
|
|
1380
1361
|
}
|
|
1381
1362
|
var _e$detail$indexObj = e.detail.indexObj,
|
|
1382
1363
|
index = _e$detail$indexObj.index,
|
|
@@ -1669,6 +1650,7 @@ function dndzone(node, options) {
|
|
|
1669
1650
|
addMaybeListeners();
|
|
1670
1651
|
}
|
|
1671
1652
|
function handleDragStart() {
|
|
1653
|
+
var _objectSpread2$1;
|
|
1672
1654
|
printDebug(function () {
|
|
1673
1655
|
return ["drag start config: ".concat(toString(config)), originalDragTarget];
|
|
1674
1656
|
});
|
|
@@ -1686,12 +1668,12 @@ function dndzone(node, options) {
|
|
|
1686
1668
|
centreDraggedOnCursor = config.centreDraggedOnCursor;
|
|
1687
1669
|
draggedElData = _objectSpread2({}, items[currentIdx]);
|
|
1688
1670
|
draggedElType = type;
|
|
1689
|
-
shadowElData = _objectSpread2(_objectSpread2({}, draggedElData), {},
|
|
1690
|
-
// The initial shadow element. We need a different id at first in order to avoid conflicts and timing issues
|
|
1691
|
-
var placeHolderElData = _objectSpread2(_objectSpread2({}, shadowElData), {}, _defineProperty({}, ITEM_ID_KEY, SHADOW_PLACEHOLDER_ITEM_ID));
|
|
1671
|
+
shadowElData = _objectSpread2(_objectSpread2({}, draggedElData), {}, (_objectSpread2$1 = {}, _defineProperty(_objectSpread2$1, SHADOW_ITEM_MARKER_PROPERTY_NAME, true), _defineProperty(_objectSpread2$1, ITEM_ID_KEY, SHADOW_PLACEHOLDER_ITEM_ID), _objectSpread2$1));
|
|
1692
1672
|
|
|
1693
1673
|
// creating the draggable element
|
|
1694
1674
|
draggedEl = createDraggedElementFrom(originalDragTarget, centreDraggedOnCursor && currentMousePosition);
|
|
1675
|
+
originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
|
|
1676
|
+
|
|
1695
1677
|
// 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
|
|
1696
1678
|
function keepOriginalElementInDom() {
|
|
1697
1679
|
if (!draggedEl.parentElement) {
|
|
@@ -1715,7 +1697,7 @@ function dndzone(node, options) {
|
|
|
1715
1697
|
});
|
|
1716
1698
|
|
|
1717
1699
|
// removing the original element by removing its data entry
|
|
1718
|
-
items.splice(currentIdx, 1,
|
|
1700
|
+
items.splice(currentIdx, 1, shadowElData);
|
|
1719
1701
|
unlockOriginDzMinDimensions = preventShrinking(originDropZone);
|
|
1720
1702
|
dispatchConsiderEvent(originDropZone, items, {
|
|
1721
1703
|
trigger: TRIGGERS.DRAG_STARTED,
|
|
@@ -1850,7 +1832,7 @@ function dndzone(node, options) {
|
|
|
1850
1832
|
unregisterDropZone(node, dzToConfig.get(node).type);
|
|
1851
1833
|
dzToConfig["delete"](node);
|
|
1852
1834
|
}
|
|
1853
|
-
if (isWorkingOnPreviousDrag) {
|
|
1835
|
+
if (isWorkingOnPreviousDrag && !node.closest("[".concat(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, "]"))) {
|
|
1854
1836
|
printDebug(function () {
|
|
1855
1837
|
return "pointer dndzone will be scheduled for destruction";
|
|
1856
1838
|
});
|
|
@@ -2380,6 +2362,12 @@ var _excluded = ["items", "flipDurationMs", "type", "dragDisabled", "morphDisabl
|
|
|
2380
2362
|
* @return {{update: function, destroy: function}}
|
|
2381
2363
|
*/
|
|
2382
2364
|
function dndzone$2(node, options) {
|
|
2365
|
+
if (shouldIgnoreZone(node)) {
|
|
2366
|
+
return {
|
|
2367
|
+
update: function update() {},
|
|
2368
|
+
destroy: function destroy() {}
|
|
2369
|
+
};
|
|
2370
|
+
}
|
|
2383
2371
|
validateOptions(options);
|
|
2384
2372
|
var pointerZone = dndzone(node, options);
|
|
2385
2373
|
var keyboardZone = dndzone$1(node, options);
|
|
@@ -2395,6 +2383,16 @@ function dndzone$2(node, options) {
|
|
|
2395
2383
|
}
|
|
2396
2384
|
};
|
|
2397
2385
|
}
|
|
2386
|
+
|
|
2387
|
+
/**
|
|
2388
|
+
* If the user marked something in the ancestry of our node as shadow element, we can ignore it
|
|
2389
|
+
* We need the user to mark it for us because svelte updates the action from deep to shallow (but renders top down)
|
|
2390
|
+
* @param {HTMLElement} node
|
|
2391
|
+
* @return {boolean}
|
|
2392
|
+
*/
|
|
2393
|
+
function shouldIgnoreZone(node) {
|
|
2394
|
+
return !!node.closest("[".concat(SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME, "=\"true\"]"));
|
|
2395
|
+
}
|
|
2398
2396
|
function validateOptions(options) {
|
|
2399
2397
|
/*eslint-disable*/
|
|
2400
2398
|
var items = options.items,
|
package/package.json
CHANGED
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"src",
|
|
43
43
|
"dist"
|
|
44
44
|
],
|
|
45
|
-
"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 *",
|
|
46
|
-
"version": "0.9.
|
|
45
|
+
"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 *",
|
|
46
|
+
"version": "0.9.29",
|
|
47
47
|
"repository": {
|
|
48
48
|
"type": "git",
|
|
49
49
|
"url": "git+https://github.com/isaacHagoel/svelte-dnd-action.git"
|
package/src/action.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {dndzone as pointerDndZone} from "./pointerAction";
|
|
2
2
|
import {dndzone as keyboardDndZone} from "./keyboardAction";
|
|
3
|
-
import {ITEM_ID_KEY} from "./constants";
|
|
3
|
+
import {ITEM_ID_KEY, SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME} from "./constants";
|
|
4
4
|
import {toString} from "./helpers/util";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -25,6 +25,12 @@ import {toString} from "./helpers/util";
|
|
|
25
25
|
* @return {{update: function, destroy: function}}
|
|
26
26
|
*/
|
|
27
27
|
export function dndzone(node, options) {
|
|
28
|
+
if (shouldIgnoreZone(node)) {
|
|
29
|
+
return {
|
|
30
|
+
update: () => {},
|
|
31
|
+
destroy: () => {}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
28
34
|
validateOptions(options);
|
|
29
35
|
const pointerZone = pointerDndZone(node, options);
|
|
30
36
|
const keyboardZone = keyboardDndZone(node, options);
|
|
@@ -41,6 +47,16 @@ export function dndzone(node, options) {
|
|
|
41
47
|
};
|
|
42
48
|
}
|
|
43
49
|
|
|
50
|
+
/**
|
|
51
|
+
* If the user marked something in the ancestry of our node as shadow element, we can ignore it
|
|
52
|
+
* We need the user to mark it for us because svelte updates the action from deep to shallow (but renders top down)
|
|
53
|
+
* @param {HTMLElement} node
|
|
54
|
+
* @return {boolean}
|
|
55
|
+
*/
|
|
56
|
+
function shouldIgnoreZone(node) {
|
|
57
|
+
return !!node.closest(`[${SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME}="true"]`);
|
|
58
|
+
}
|
|
59
|
+
|
|
44
60
|
function validateOptions(options) {
|
|
45
61
|
/*eslint-disable*/
|
|
46
62
|
const {
|
package/src/constants.js
CHANGED
|
@@ -19,7 +19,8 @@ export const SOURCES = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
export const SHADOW_ITEM_MARKER_PROPERTY_NAME = "isDndShadowItem";
|
|
22
|
-
export const SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item";
|
|
22
|
+
export const SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-internal";
|
|
23
|
+
export const SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-hint";
|
|
23
24
|
export const SHADOW_PLACEHOLDER_ITEM_ID = "id:dnd-shadow-placeholder-0000";
|
|
24
25
|
export const DRAGGED_ELEMENT_ID = "dnd-action-dragged-el";
|
|
25
26
|
|
package/src/pointerAction.js
CHANGED
|
@@ -40,6 +40,7 @@ const MIN_MOVEMENT_BEFORE_DRAG_START_PX = 3;
|
|
|
40
40
|
const DEFAULT_DROP_TARGET_STYLE = {
|
|
41
41
|
outline: "rgba(255, 255, 102, 0.7) solid 2px"
|
|
42
42
|
};
|
|
43
|
+
const ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE = "data-is-dnd-original-dragged-item";
|
|
43
44
|
|
|
44
45
|
let originalDragTarget;
|
|
45
46
|
let draggedEl;
|
|
@@ -73,10 +74,6 @@ function registerDropZone(dropZoneEl, type) {
|
|
|
73
74
|
if (!typeToDropZones.get(type).has(dropZoneEl)) {
|
|
74
75
|
typeToDropZones.get(type).add(dropZoneEl);
|
|
75
76
|
incrementActiveDropZoneCount();
|
|
76
|
-
if (isWorkingOnPreviousDrag) {
|
|
77
|
-
unWatchDraggedElement();
|
|
78
|
-
watchDraggedElement();
|
|
79
|
-
}
|
|
80
77
|
}
|
|
81
78
|
}
|
|
82
79
|
function unregisterDropZone(dropZoneEl, type) {
|
|
@@ -118,13 +115,8 @@ function unWatchDraggedElement() {
|
|
|
118
115
|
unobserve();
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
// finds the initial placeholder that is placed there on drag start
|
|
122
|
-
function findShadowPlaceHolderIdx(items) {
|
|
123
|
-
return items.findIndex(item => item[ITEM_ID_KEY] === SHADOW_PLACEHOLDER_ITEM_ID);
|
|
124
|
-
}
|
|
125
118
|
function findShadowElementIdx(items) {
|
|
126
|
-
|
|
127
|
-
return items.findIndex(item => !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME] && item[ITEM_ID_KEY] !== SHADOW_PLACEHOLDER_ITEM_ID);
|
|
119
|
+
return items.findIndex(item => !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME]);
|
|
128
120
|
}
|
|
129
121
|
|
|
130
122
|
/* custom drag-events handlers */
|
|
@@ -148,15 +140,7 @@ function handleDraggedEntered(e) {
|
|
|
148
140
|
id: draggedElData[ITEM_ID_KEY],
|
|
149
141
|
source: SOURCES.POINTER
|
|
150
142
|
});
|
|
151
|
-
} else {
|
|
152
|
-
const shadowPlaceHolderIdx = findShadowPlaceHolderIdx(items);
|
|
153
|
-
if (shadowPlaceHolderIdx !== -1) {
|
|
154
|
-
// only happens right after drag start, on the first drag entered event
|
|
155
|
-
printDebug(() => "removing placeholder item from origin dz");
|
|
156
|
-
items.splice(shadowPlaceHolderIdx, 1);
|
|
157
|
-
}
|
|
158
143
|
}
|
|
159
|
-
|
|
160
144
|
const {index, isProximityBased} = e.detail.indexObj;
|
|
161
145
|
const shadowElIdx = isProximityBased && index === e.currentTarget.children.length - 1 ? index + 1 : index;
|
|
162
146
|
shadowElDropZone = e.currentTarget;
|
|
@@ -249,6 +233,7 @@ function handleDrop() {
|
|
|
249
233
|
let shadowElIdx = findShadowElementIdx(items);
|
|
250
234
|
// the handler might remove the shadow element, ex: dragula like copy on drag
|
|
251
235
|
if (shadowElIdx === -1) shadowElIdx = originIndex;
|
|
236
|
+
|
|
252
237
|
items = items.map(item => (item[SHADOW_ITEM_MARKER_PROPERTY_NAME] ? draggedElData : item));
|
|
253
238
|
function finalizeWithinZone() {
|
|
254
239
|
unlockOriginDzMinDimensions();
|
|
@@ -405,12 +390,12 @@ export function dndzone(node, options) {
|
|
|
405
390
|
const {items, type, centreDraggedOnCursor} = config;
|
|
406
391
|
draggedElData = {...items[currentIdx]};
|
|
407
392
|
draggedElType = type;
|
|
408
|
-
shadowElData = {...draggedElData, [SHADOW_ITEM_MARKER_PROPERTY_NAME]: true};
|
|
409
|
-
// The initial shadow element. We need a different id at first in order to avoid conflicts and timing issues
|
|
410
|
-
const placeHolderElData = {...shadowElData, [ITEM_ID_KEY]: SHADOW_PLACEHOLDER_ITEM_ID};
|
|
393
|
+
shadowElData = {...draggedElData, [SHADOW_ITEM_MARKER_PROPERTY_NAME]: true, [ITEM_ID_KEY]: SHADOW_PLACEHOLDER_ITEM_ID};
|
|
411
394
|
|
|
412
395
|
// creating the draggable element
|
|
413
396
|
draggedEl = createDraggedElementFrom(originalDragTarget, centreDraggedOnCursor && currentMousePosition);
|
|
397
|
+
originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
|
|
398
|
+
|
|
414
399
|
// 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
|
|
415
400
|
function keepOriginalElementInDom() {
|
|
416
401
|
if (!draggedEl.parentElement) {
|
|
@@ -433,7 +418,7 @@ export function dndzone(node, options) {
|
|
|
433
418
|
);
|
|
434
419
|
|
|
435
420
|
// removing the original element by removing its data entry
|
|
436
|
-
items.splice(currentIdx, 1,
|
|
421
|
+
items.splice(currentIdx, 1, shadowElData);
|
|
437
422
|
unlockOriginDzMinDimensions = preventShrinking(originDropZone);
|
|
438
423
|
|
|
439
424
|
dispatchConsiderEvent(originDropZone, items, {trigger: TRIGGERS.DRAG_STARTED, id: draggedElData[ITEM_ID_KEY], source: SOURCES.POINTER});
|
|
@@ -553,7 +538,7 @@ export function dndzone(node, options) {
|
|
|
553
538
|
unregisterDropZone(node, dzToConfig.get(node).type);
|
|
554
539
|
dzToConfig.delete(node);
|
|
555
540
|
}
|
|
556
|
-
if (isWorkingOnPreviousDrag) {
|
|
541
|
+
if (isWorkingOnPreviousDrag && !node.closest(`[${ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE}]`)) {
|
|
557
542
|
printDebug(() => "pointer dndzone will be scheduled for destruction");
|
|
558
543
|
scheduleDZForRemovalAfterDrop(node, destroyDz);
|
|
559
544
|
} else {
|