svelte-dnd-action 0.9.28 → 0.9.30

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 CHANGED
@@ -106,7 +106,7 @@ An options-object with the following attributes:
106
106
  | Name | Type | Required? | Default Value | Description |
107
107
  | ------------------------- | -------------- | ------------------------------------------------------------ | ------------------------------------------------- | ------------------------------------------------------------ |
108
108
  | `items` | Array<Object> | Yes. Each object in the array **has to have** an `id` property (key name can be overridden globally) with a unique value (within all dnd-zones of the same type) | N/A | The data array that is used to produce the list with the draggable items (the same thing you run your #each block on). The dndzone should not have children that don't originate in `items` |
109
- | `flipDurationMs` | Number | No | `0` | The same value you give the flip animation on the items (to make them animated as they "make space" for the dragged item). Set to zero or leave out if you don't want animations |
109
+ | `flipDurationMs` | Number | No | `0` | The same value you give the flip animation on the items (to make them animated as they "make space" for the dragged item). Set to zero if you dont want animations, if unset it defaults to 100ms |
110
110
  | `type` | String | No | Internal | dnd-zones that share the same type can have elements from one dragged into another. By default, all dnd-zones have the same type |
111
111
  | `dragDisabled` | Boolean | No | `false` | Setting it to true will make it impossible to drag elements out of the dnd-zone. You can change it at any time, and the zone will adjust on the fly |
112
112
  | `morphDisabled` | Boolean | No | `false` | By default, when dragging over a zone, the dragged element is morphed to look like it would if dropped. You can prevent it by setting this option. |
@@ -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 [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](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";
@@ -1225,10 +1226,12 @@
1225
1226
 
1226
1227
  var DEFAULT_DROP_ZONE_TYPE = "--any--";
1227
1228
  var MIN_OBSERVATION_INTERVAL_MS = 100;
1229
+ var DISABLED_OBSERVATION_INTERVAL_MS = 20;
1228
1230
  var MIN_MOVEMENT_BEFORE_DRAG_START_PX = 3;
1229
1231
  var DEFAULT_DROP_TARGET_STYLE = {
1230
1232
  outline: "rgba(255, 255, 102, 0.7) solid 2px"
1231
1233
  };
1234
+ var ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE = "data-is-dnd-original-dragged-item";
1232
1235
  var originalDragTarget;
1233
1236
  var draggedEl;
1234
1237
  var draggedElData;
@@ -1296,9 +1299,10 @@
1296
1299
  }
1297
1300
  window.addEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
1298
1301
  // 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
1299
- var observationIntervalMs = Math.max.apply(Math, [MIN_OBSERVATION_INTERVAL_MS].concat(_toConsumableArray(Array.from(dropZones.keys()).map(function (dz) {
1302
+ var setIntervalMs = Math.max.apply(Math, _toConsumableArray(Array.from(dropZones.keys()).map(function (dz) {
1300
1303
  return dzToConfig.get(dz).dropAnimationDurationMs;
1301
- }))));
1304
+ })));
1305
+ 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.
1302
1306
  observe(draggedEl, dropZones, observationIntervalMs * 1.07);
1303
1307
  }
1304
1308
  function unWatchDraggedElement() {
@@ -1324,17 +1328,9 @@
1324
1328
  window.removeEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
1325
1329
  unobserve();
1326
1330
  }
1327
-
1328
- // finds the initial placeholder that is placed there on drag start
1329
- function findShadowPlaceHolderIdx(items) {
1330
- return items.findIndex(function (item) {
1331
- return item[ITEM_ID_KEY] === SHADOW_PLACEHOLDER_ITEM_ID;
1332
- });
1333
- }
1334
1331
  function findShadowElementIdx(items) {
1335
- // checking that the id is not the placeholder's for Dragula like usecases
1336
1332
  return items.findIndex(function (item) {
1337
- return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME] && item[ITEM_ID_KEY] !== SHADOW_PLACEHOLDER_ITEM_ID;
1333
+ return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME];
1338
1334
  });
1339
1335
  }
1340
1336
 
@@ -1370,15 +1366,6 @@
1370
1366
  id: draggedElData[ITEM_ID_KEY],
1371
1367
  source: SOURCES.POINTER
1372
1368
  });
1373
- } else {
1374
- var shadowPlaceHolderIdx = findShadowPlaceHolderIdx(items);
1375
- if (shadowPlaceHolderIdx !== -1) {
1376
- // only happens right after drag start, on the first drag entered event
1377
- printDebug(function () {
1378
- return "removing placeholder item from origin dz";
1379
- });
1380
- items.splice(shadowPlaceHolderIdx, 1);
1381
- }
1382
1369
  }
1383
1370
  var _e$detail$indexObj = e.detail.indexObj,
1384
1371
  index = _e$detail$indexObj.index,
@@ -1671,6 +1658,7 @@
1671
1658
  addMaybeListeners();
1672
1659
  }
1673
1660
  function handleDragStart() {
1661
+ var _objectSpread2$1;
1674
1662
  printDebug(function () {
1675
1663
  return ["drag start config: ".concat(toString(config)), originalDragTarget];
1676
1664
  });
@@ -1688,12 +1676,12 @@
1688
1676
  centreDraggedOnCursor = config.centreDraggedOnCursor;
1689
1677
  draggedElData = _objectSpread2({}, items[currentIdx]);
1690
1678
  draggedElType = type;
1691
- shadowElData = _objectSpread2(_objectSpread2({}, draggedElData), {}, _defineProperty({}, SHADOW_ITEM_MARKER_PROPERTY_NAME, true));
1692
- // The initial shadow element. We need a different id at first in order to avoid conflicts and timing issues
1693
- var placeHolderElData = _objectSpread2(_objectSpread2({}, shadowElData), {}, _defineProperty({}, ITEM_ID_KEY, SHADOW_PLACEHOLDER_ITEM_ID));
1679
+ 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));
1694
1680
 
1695
1681
  // creating the draggable element
1696
1682
  draggedEl = createDraggedElementFrom(originalDragTarget, centreDraggedOnCursor && currentMousePosition);
1683
+ originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
1684
+
1697
1685
  // 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
1698
1686
  function keepOriginalElementInDom() {
1699
1687
  if (!draggedEl.parentElement) {
@@ -1717,7 +1705,7 @@
1717
1705
  });
1718
1706
 
1719
1707
  // removing the original element by removing its data entry
1720
- items.splice(currentIdx, 1, placeHolderElData);
1708
+ items.splice(currentIdx, 1, shadowElData);
1721
1709
  unlockOriginDzMinDimensions = preventShrinking(originDropZone);
1722
1710
  dispatchConsiderEvent(originDropZone, items, {
1723
1711
  trigger: TRIGGERS.DRAG_STARTED,
@@ -1852,7 +1840,7 @@
1852
1840
  unregisterDropZone(node, dzToConfig.get(node).type);
1853
1841
  dzToConfig["delete"](node);
1854
1842
  }
1855
- if (isWorkingOnPreviousDrag) {
1843
+ if (isWorkingOnPreviousDrag && !node.closest("[".concat(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, "]"))) {
1856
1844
  printDebug(function () {
1857
1845
  return "pointer dndzone will be scheduled for destruction";
1858
1846
  });
@@ -2382,6 +2370,12 @@
2382
2370
  * @return {{update: function, destroy: function}}
2383
2371
  */
2384
2372
  function dndzone$2(node, options) {
2373
+ if (shouldIgnoreZone(node)) {
2374
+ return {
2375
+ update: function update() {},
2376
+ destroy: function destroy() {}
2377
+ };
2378
+ }
2385
2379
  validateOptions(options);
2386
2380
  var pointerZone = dndzone(node, options);
2387
2381
  var keyboardZone = dndzone$1(node, options);
@@ -2397,6 +2391,16 @@
2397
2391
  }
2398
2392
  };
2399
2393
  }
2394
+
2395
+ /**
2396
+ * If the user marked something in the ancestry of our node as shadow element, we can ignore it
2397
+ * We need the user to mark it for us because svelte updates the action from deep to shallow (but renders top down)
2398
+ * @param {HTMLElement} node
2399
+ * @return {boolean}
2400
+ */
2401
+ function shouldIgnoreZone(node) {
2402
+ return !!node.closest("[".concat(SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME, "=\"true\"]"));
2403
+ }
2400
2404
  function validateOptions(options) {
2401
2405
  /*eslint-disable*/
2402
2406
  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";
@@ -1219,10 +1220,12 @@ function preventShrinking(el) {
1219
1220
 
1220
1221
  var DEFAULT_DROP_ZONE_TYPE = "--any--";
1221
1222
  var MIN_OBSERVATION_INTERVAL_MS = 100;
1223
+ var DISABLED_OBSERVATION_INTERVAL_MS = 20;
1222
1224
  var MIN_MOVEMENT_BEFORE_DRAG_START_PX = 3;
1223
1225
  var DEFAULT_DROP_TARGET_STYLE = {
1224
1226
  outline: "rgba(255, 255, 102, 0.7) solid 2px"
1225
1227
  };
1228
+ var ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE = "data-is-dnd-original-dragged-item";
1226
1229
  var originalDragTarget;
1227
1230
  var draggedEl;
1228
1231
  var draggedElData;
@@ -1290,9 +1293,10 @@ function watchDraggedElement() {
1290
1293
  }
1291
1294
  window.addEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
1292
1295
  // 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
1293
- var observationIntervalMs = Math.max.apply(Math, [MIN_OBSERVATION_INTERVAL_MS].concat(_toConsumableArray(Array.from(dropZones.keys()).map(function (dz) {
1296
+ var setIntervalMs = Math.max.apply(Math, _toConsumableArray(Array.from(dropZones.keys()).map(function (dz) {
1294
1297
  return dzToConfig.get(dz).dropAnimationDurationMs;
1295
- }))));
1298
+ })));
1299
+ 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.
1296
1300
  observe(draggedEl, dropZones, observationIntervalMs * 1.07);
1297
1301
  }
1298
1302
  function unWatchDraggedElement() {
@@ -1318,17 +1322,9 @@ function unWatchDraggedElement() {
1318
1322
  window.removeEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
1319
1323
  unobserve();
1320
1324
  }
1321
-
1322
- // finds the initial placeholder that is placed there on drag start
1323
- function findShadowPlaceHolderIdx(items) {
1324
- return items.findIndex(function (item) {
1325
- return item[ITEM_ID_KEY] === SHADOW_PLACEHOLDER_ITEM_ID;
1326
- });
1327
- }
1328
1325
  function findShadowElementIdx(items) {
1329
- // checking that the id is not the placeholder's for Dragula like usecases
1330
1326
  return items.findIndex(function (item) {
1331
- return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME] && item[ITEM_ID_KEY] !== SHADOW_PLACEHOLDER_ITEM_ID;
1327
+ return !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME];
1332
1328
  });
1333
1329
  }
1334
1330
 
@@ -1364,15 +1360,6 @@ function handleDraggedEntered(e) {
1364
1360
  id: draggedElData[ITEM_ID_KEY],
1365
1361
  source: SOURCES.POINTER
1366
1362
  });
1367
- } else {
1368
- var shadowPlaceHolderIdx = findShadowPlaceHolderIdx(items);
1369
- if (shadowPlaceHolderIdx !== -1) {
1370
- // only happens right after drag start, on the first drag entered event
1371
- printDebug(function () {
1372
- return "removing placeholder item from origin dz";
1373
- });
1374
- items.splice(shadowPlaceHolderIdx, 1);
1375
- }
1376
1363
  }
1377
1364
  var _e$detail$indexObj = e.detail.indexObj,
1378
1365
  index = _e$detail$indexObj.index,
@@ -1665,6 +1652,7 @@ function dndzone(node, options) {
1665
1652
  addMaybeListeners();
1666
1653
  }
1667
1654
  function handleDragStart() {
1655
+ var _objectSpread2$1;
1668
1656
  printDebug(function () {
1669
1657
  return ["drag start config: ".concat(toString(config)), originalDragTarget];
1670
1658
  });
@@ -1682,12 +1670,12 @@ function dndzone(node, options) {
1682
1670
  centreDraggedOnCursor = config.centreDraggedOnCursor;
1683
1671
  draggedElData = _objectSpread2({}, items[currentIdx]);
1684
1672
  draggedElType = type;
1685
- shadowElData = _objectSpread2(_objectSpread2({}, draggedElData), {}, _defineProperty({}, SHADOW_ITEM_MARKER_PROPERTY_NAME, true));
1686
- // The initial shadow element. We need a different id at first in order to avoid conflicts and timing issues
1687
- var placeHolderElData = _objectSpread2(_objectSpread2({}, shadowElData), {}, _defineProperty({}, ITEM_ID_KEY, SHADOW_PLACEHOLDER_ITEM_ID));
1673
+ 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));
1688
1674
 
1689
1675
  // creating the draggable element
1690
1676
  draggedEl = createDraggedElementFrom(originalDragTarget, centreDraggedOnCursor && currentMousePosition);
1677
+ originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
1678
+
1691
1679
  // 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
1692
1680
  function keepOriginalElementInDom() {
1693
1681
  if (!draggedEl.parentElement) {
@@ -1711,7 +1699,7 @@ function dndzone(node, options) {
1711
1699
  });
1712
1700
 
1713
1701
  // removing the original element by removing its data entry
1714
- items.splice(currentIdx, 1, placeHolderElData);
1702
+ items.splice(currentIdx, 1, shadowElData);
1715
1703
  unlockOriginDzMinDimensions = preventShrinking(originDropZone);
1716
1704
  dispatchConsiderEvent(originDropZone, items, {
1717
1705
  trigger: TRIGGERS.DRAG_STARTED,
@@ -1846,7 +1834,7 @@ function dndzone(node, options) {
1846
1834
  unregisterDropZone(node, dzToConfig.get(node).type);
1847
1835
  dzToConfig["delete"](node);
1848
1836
  }
1849
- if (isWorkingOnPreviousDrag) {
1837
+ if (isWorkingOnPreviousDrag && !node.closest("[".concat(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, "]"))) {
1850
1838
  printDebug(function () {
1851
1839
  return "pointer dndzone will be scheduled for destruction";
1852
1840
  });
@@ -2376,6 +2364,12 @@ var _excluded = ["items", "flipDurationMs", "type", "dragDisabled", "morphDisabl
2376
2364
  * @return {{update: function, destroy: function}}
2377
2365
  */
2378
2366
  function dndzone$2(node, options) {
2367
+ if (shouldIgnoreZone(node)) {
2368
+ return {
2369
+ update: function update() {},
2370
+ destroy: function destroy() {}
2371
+ };
2372
+ }
2379
2373
  validateOptions(options);
2380
2374
  var pointerZone = dndzone(node, options);
2381
2375
  var keyboardZone = dndzone$1(node, options);
@@ -2391,6 +2385,16 @@ function dndzone$2(node, options) {
2391
2385
  }
2392
2386
  };
2393
2387
  }
2388
+
2389
+ /**
2390
+ * If the user marked something in the ancestry of our node as shadow element, we can ignore it
2391
+ * We need the user to mark it for us because svelte updates the action from deep to shallow (but renders top down)
2392
+ * @param {HTMLElement} node
2393
+ * @return {boolean}
2394
+ */
2395
+ function shouldIgnoreZone(node) {
2396
+ return !!node.closest("[".concat(SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME, "=\"true\"]"));
2397
+ }
2394
2398
  function validateOptions(options) {
2395
2399
  /*eslint-disable*/
2396
2400
  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.28",
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.30",
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
 
@@ -36,10 +36,12 @@ import {getBoundingRectNoTransforms} from "./helpers/intersection";
36
36
 
37
37
  const DEFAULT_DROP_ZONE_TYPE = "--any--";
38
38
  const MIN_OBSERVATION_INTERVAL_MS = 100;
39
+ const DISABLED_OBSERVATION_INTERVAL_MS = 20;
39
40
  const MIN_MOVEMENT_BEFORE_DRAG_START_PX = 3;
40
41
  const DEFAULT_DROP_TARGET_STYLE = {
41
42
  outline: "rgba(255, 255, 102, 0.7) solid 2px"
42
43
  };
44
+ const ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE = "data-is-dnd-original-dragged-item";
43
45
 
44
46
  let originalDragTarget;
45
47
  let draggedEl;
@@ -95,10 +97,8 @@ function watchDraggedElement() {
95
97
  }
96
98
  window.addEventListener(DRAGGED_LEFT_DOCUMENT_EVENT_NAME, handleDrop);
97
99
  // 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
98
- const observationIntervalMs = Math.max(
99
- MIN_OBSERVATION_INTERVAL_MS,
100
- ...Array.from(dropZones.keys()).map(dz => dzToConfig.get(dz).dropAnimationDurationMs)
101
- );
100
+ const setIntervalMs = Math.max(...Array.from(dropZones.keys()).map(dz => dzToConfig.get(dz).dropAnimationDurationMs));
101
+ 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.
102
102
  observe(draggedEl, dropZones, observationIntervalMs * 1.07);
103
103
  }
104
104
  function unWatchDraggedElement() {
@@ -114,13 +114,8 @@ function unWatchDraggedElement() {
114
114
  unobserve();
115
115
  }
116
116
 
117
- // finds the initial placeholder that is placed there on drag start
118
- function findShadowPlaceHolderIdx(items) {
119
- return items.findIndex(item => item[ITEM_ID_KEY] === SHADOW_PLACEHOLDER_ITEM_ID);
120
- }
121
117
  function findShadowElementIdx(items) {
122
- // checking that the id is not the placeholder's for Dragula like usecases
123
- return items.findIndex(item => !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME] && item[ITEM_ID_KEY] !== SHADOW_PLACEHOLDER_ITEM_ID);
118
+ return items.findIndex(item => !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME]);
124
119
  }
125
120
 
126
121
  /* custom drag-events handlers */
@@ -144,15 +139,7 @@ function handleDraggedEntered(e) {
144
139
  id: draggedElData[ITEM_ID_KEY],
145
140
  source: SOURCES.POINTER
146
141
  });
147
- } else {
148
- const shadowPlaceHolderIdx = findShadowPlaceHolderIdx(items);
149
- if (shadowPlaceHolderIdx !== -1) {
150
- // only happens right after drag start, on the first drag entered event
151
- printDebug(() => "removing placeholder item from origin dz");
152
- items.splice(shadowPlaceHolderIdx, 1);
153
- }
154
142
  }
155
-
156
143
  const {index, isProximityBased} = e.detail.indexObj;
157
144
  const shadowElIdx = isProximityBased && index === e.currentTarget.children.length - 1 ? index + 1 : index;
158
145
  shadowElDropZone = e.currentTarget;
@@ -245,6 +232,7 @@ function handleDrop() {
245
232
  let shadowElIdx = findShadowElementIdx(items);
246
233
  // the handler might remove the shadow element, ex: dragula like copy on drag
247
234
  if (shadowElIdx === -1) shadowElIdx = originIndex;
235
+
248
236
  items = items.map(item => (item[SHADOW_ITEM_MARKER_PROPERTY_NAME] ? draggedElData : item));
249
237
  function finalizeWithinZone() {
250
238
  unlockOriginDzMinDimensions();
@@ -401,12 +389,12 @@ export function dndzone(node, options) {
401
389
  const {items, type, centreDraggedOnCursor} = config;
402
390
  draggedElData = {...items[currentIdx]};
403
391
  draggedElType = type;
404
- shadowElData = {...draggedElData, [SHADOW_ITEM_MARKER_PROPERTY_NAME]: true};
405
- // The initial shadow element. We need a different id at first in order to avoid conflicts and timing issues
406
- const placeHolderElData = {...shadowElData, [ITEM_ID_KEY]: SHADOW_PLACEHOLDER_ITEM_ID};
392
+ shadowElData = {...draggedElData, [SHADOW_ITEM_MARKER_PROPERTY_NAME]: true, [ITEM_ID_KEY]: SHADOW_PLACEHOLDER_ITEM_ID};
407
393
 
408
394
  // creating the draggable element
409
395
  draggedEl = createDraggedElementFrom(originalDragTarget, centreDraggedOnCursor && currentMousePosition);
396
+ originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true);
397
+
410
398
  // 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
411
399
  function keepOriginalElementInDom() {
412
400
  if (!draggedEl.parentElement) {
@@ -429,7 +417,7 @@ export function dndzone(node, options) {
429
417
  );
430
418
 
431
419
  // removing the original element by removing its data entry
432
- items.splice(currentIdx, 1, placeHolderElData);
420
+ items.splice(currentIdx, 1, shadowElData);
433
421
  unlockOriginDzMinDimensions = preventShrinking(originDropZone);
434
422
 
435
423
  dispatchConsiderEvent(originDropZone, items, {trigger: TRIGGERS.DRAG_STARTED, id: draggedElData[ITEM_ID_KEY], source: SOURCES.POINTER});
@@ -549,7 +537,7 @@ export function dndzone(node, options) {
549
537
  unregisterDropZone(node, dzToConfig.get(node).type);
550
538
  dzToConfig.delete(node);
551
539
  }
552
- if (isWorkingOnPreviousDrag) {
540
+ if (isWorkingOnPreviousDrag && !node.closest(`[${ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE}]`)) {
553
541
  printDebug(() => "pointer dndzone will be scheduled for destruction");
554
542
  scheduleDZForRemovalAfterDrop(node, destroyDz);
555
543
  } else {