svelte-dnd-action 0.9.11 → 0.9.15

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
@@ -189,6 +189,7 @@ If you want to implement your own custom screen-reader alerts, roles and instruc
189
189
  - [Generic List Component (Alternative to Slots)](https://svelte.dev/repl/028674733f67409c94bd52995d5906f1?version=3.31.0)
190
190
  - [Maitaining internal scroll poisition on scrollable dragabble](https://svelte.dev/repl/eb2f5988bd2f46488810606c1fb13392?version=3.29.4)
191
191
  - [Scrabble like board using over a 100 single slot dnd-zones](https://svelte.dev/repl/ed2e138417094281be6db1aef23d7859?version=3.37.0)
192
+ - [Select multiple elements to drag (multi-drag) with mouse or keyboard](https://svelte.dev/repl/c4eb917bb8df42c4b17402a7dda54856?version=3.24.1)
192
193
 
193
194
  - [Fade in/out but without using Svelte transitions](https://svelte.dev/repl/3f1e68203ef140969a8240eba3475a8d?version=3.24.1)
194
195
  - [Nested fade in/out without using Svelte transitions](https://svelte.dev/repl/49b09aedfe0543b4bc8f575c8dbf9a53?version=3.24.1)
@@ -205,7 +206,7 @@ If you want to implement your own custom screen-reader alerts, roles and instruc
205
206
  - The host component must refresh the items that are passed in to the custom-action when receiving consider and finalize events (do not omit any handler).
206
207
  - FYI, the library assumes it is okay to add a temporary item to the items list in any of the dnd-zones while an element is dragged around.
207
208
  - If you want dragged items to be able to scroll the container, make sure the scroll-container (the element with overflow:scroll) is the dnd-zone (the element decorated with this custom action)
208
- - Svelte's built-in transitions might not play nice with this library. Luckily, it is an easy issue to work around. There are examples below.
209
+ - Svelte's built-in transitions might not play nice with this library. Luckily, it is an easy issue to work around. There are examples above.
209
210
 
210
211
  ### Overriding the item id key name
211
212
 
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ export interface Options {
27
27
  morphDisabled?: boolean;
28
28
  dropFromOthersDisabled?: boolean;
29
29
  zoneTabIndex?: number; // set the tabindex of the list container when not dragging
30
- dropTargetClasses?: [string];
30
+ dropTargetClasses?: string[];
31
31
  dropTargetStyle?: Record<string, string>;
32
32
  transformDraggedElement?: TransformDraggedElementFunction;
33
33
  autoAriaDisabled?: boolean;
package/dist/index.js CHANGED
@@ -599,6 +599,17 @@
599
599
  dzToShadowIndexToRect = new Map();
600
600
  }
601
601
  resetIndexesCache();
602
+ /**
603
+ * Resets the cache that allows for smarter "would be index" resolution for a specific dropzone, should be called after the zone was scrolled
604
+ * @param {HTMLElement} dz
605
+ */
606
+
607
+ function resetIndexesCacheForDz(dz) {
608
+ printDebug(function () {
609
+ return "resetting indexes cache for dz";
610
+ });
611
+ dzToShadowIndexToRect["delete"](dz);
612
+ }
602
613
  /**
603
614
  * Caches the coordinates of the shadow element when it's in a certain index in a certain dropzone.
604
615
  * Helpful in order to determine "would be index" more effectively
@@ -931,6 +942,7 @@
931
942
  try {
932
943
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
933
944
  var dz = _step.value;
945
+ if (scrolled) resetIndexesCacheForDz(lastDropZoneFound);
934
946
  var indexObj = findWouldBeIndex(draggedEl, dz);
935
947
 
936
948
  if (indexObj === null) {
@@ -1008,7 +1020,8 @@
1008
1020
 
1009
1021
  function loop() {
1010
1022
  if (mousePosition) {
1011
- scrollIfNeeded$1(mousePosition, document.documentElement);
1023
+ var scrolled = scrollIfNeeded$1(mousePosition, document.documentElement);
1024
+ if (scrolled) resetIndexesCache();
1012
1025
  }
1013
1026
 
1014
1027
  next$1 = window.setTimeout(loop, INTERVAL_MS$1);
@@ -1942,7 +1955,12 @@
1942
1955
  var alertsDiv;
1943
1956
 
1944
1957
  function initAriaOnBrowser() {
1945
- // setting the dynamic alerts
1958
+ if (alertsDiv) {
1959
+ // it is already initialized
1960
+ return;
1961
+ } // setting the dynamic alerts
1962
+
1963
+
1946
1964
  alertsDiv = document.createElement("div");
1947
1965
 
1948
1966
  (function initAlertsDiv() {
@@ -1986,6 +2004,20 @@
1986
2004
 
1987
2005
  return _objectSpread2({}, INSTRUCTION_IDs);
1988
2006
  }
2007
+ /**
2008
+ * Removes all the artifacts (dom elements) added by this module
2009
+ */
2010
+
2011
+ function destroyAria() {
2012
+ if (isOnServer || !alertsDiv) return;
2013
+ Object.keys(ID_TO_INSTRUCTION).forEach(function (id) {
2014
+ var _document$getElementB;
2015
+
2016
+ return (_document$getElementB = document.getElementById(id)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.remove();
2017
+ });
2018
+ alertsDiv.remove();
2019
+ alertsDiv = undefined;
2020
+ }
1989
2021
 
1990
2022
  function instructionToHiddenDiv(id, txt) {
1991
2023
  var div = document.createElement("div");
@@ -2003,6 +2035,12 @@
2003
2035
 
2004
2036
 
2005
2037
  function alertToScreenReader(txt) {
2038
+ if (isOnServer) return;
2039
+
2040
+ if (!alertsDiv) {
2041
+ initAriaOnBrowser();
2042
+ }
2043
+
2006
2044
  alertsDiv.innerHTML = "";
2007
2045
  var alertText = document.createTextNode(txt);
2008
2046
  alertsDiv.appendChild(alertText); // this is needed for Safari
@@ -2033,7 +2071,7 @@
2033
2071
  * maybe keep focus on the last dragged item upon drop?
2034
2072
  */
2035
2073
 
2036
- var INSTRUCTION_IDs$1 = initAria();
2074
+ var INSTRUCTION_IDs$1;
2037
2075
  /* drop-zones registration management */
2038
2076
 
2039
2077
  function registerDropZone$1(dropZoneEl, type) {
@@ -2045,6 +2083,7 @@
2045
2083
  printDebug(function () {
2046
2084
  return "adding global keydown and click handlers";
2047
2085
  });
2086
+ INSTRUCTION_IDs$1 = initAria();
2048
2087
  window.addEventListener("keydown", globalKeyDownHandler);
2049
2088
  window.addEventListener("click", globalClickHandler);
2050
2089
  }
@@ -2081,6 +2120,8 @@
2081
2120
  });
2082
2121
  window.removeEventListener("keydown", globalKeyDownHandler);
2083
2122
  window.removeEventListener("click", globalClickHandler);
2123
+ INSTRUCTION_IDs$1 = undefined;
2124
+ destroyAria();
2084
2125
  }
2085
2126
  }
2086
2127
 
@@ -2398,18 +2439,19 @@
2398
2439
  config.dropTargetClasses = dropTargetClasses;
2399
2440
  config.autoAriaDisabled = autoAriaDisabled;
2400
2441
 
2401
- if (!autoAriaDisabled) {
2402
- node.setAttribute("aria-disabled", dragDisabled);
2403
- node.setAttribute("role", "list");
2404
- node.setAttribute("aria-describedby", dragDisabled ? INSTRUCTION_IDs$1.DND_ZONE_DRAG_DISABLED : INSTRUCTION_IDs$1.DND_ZONE_ACTIVE);
2405
- }
2406
-
2407
2442
  if (config.type && newType !== config.type) {
2408
2443
  unregisterDropZone$1(node, config.type);
2409
2444
  }
2410
2445
 
2411
2446
  config.type = newType;
2412
2447
  registerDropZone$1(node, newType);
2448
+
2449
+ if (!autoAriaDisabled) {
2450
+ node.setAttribute("aria-disabled", dragDisabled);
2451
+ node.setAttribute("role", "list");
2452
+ node.setAttribute("aria-describedby", dragDisabled ? INSTRUCTION_IDs$1.DND_ZONE_DRAG_DISABLED : INSTRUCTION_IDs$1.DND_ZONE_ACTIVE);
2453
+ }
2454
+
2413
2455
  dzToConfig$1.set(node, config);
2414
2456
 
2415
2457
  if (isDragging) {
package/dist/index.mjs CHANGED
@@ -593,6 +593,17 @@ function resetIndexesCache() {
593
593
  dzToShadowIndexToRect = new Map();
594
594
  }
595
595
  resetIndexesCache();
596
+ /**
597
+ * Resets the cache that allows for smarter "would be index" resolution for a specific dropzone, should be called after the zone was scrolled
598
+ * @param {HTMLElement} dz
599
+ */
600
+
601
+ function resetIndexesCacheForDz(dz) {
602
+ printDebug(function () {
603
+ return "resetting indexes cache for dz";
604
+ });
605
+ dzToShadowIndexToRect["delete"](dz);
606
+ }
596
607
  /**
597
608
  * Caches the coordinates of the shadow element when it's in a certain index in a certain dropzone.
598
609
  * Helpful in order to determine "would be index" more effectively
@@ -925,6 +936,7 @@ function observe(draggedEl, dropZones) {
925
936
  try {
926
937
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
927
938
  var dz = _step.value;
939
+ if (scrolled) resetIndexesCacheForDz(lastDropZoneFound);
928
940
  var indexObj = findWouldBeIndex(draggedEl, dz);
929
941
 
930
942
  if (indexObj === null) {
@@ -1002,7 +1014,8 @@ var next$1;
1002
1014
 
1003
1015
  function loop() {
1004
1016
  if (mousePosition) {
1005
- scrollIfNeeded$1(mousePosition, document.documentElement);
1017
+ var scrolled = scrollIfNeeded$1(mousePosition, document.documentElement);
1018
+ if (scrolled) resetIndexesCache();
1006
1019
  }
1007
1020
 
1008
1021
  next$1 = window.setTimeout(loop, INTERVAL_MS$1);
@@ -1936,7 +1949,12 @@ var ALERT_DIV_ID = "dnd-action-aria-alert";
1936
1949
  var alertsDiv;
1937
1950
 
1938
1951
  function initAriaOnBrowser() {
1939
- // setting the dynamic alerts
1952
+ if (alertsDiv) {
1953
+ // it is already initialized
1954
+ return;
1955
+ } // setting the dynamic alerts
1956
+
1957
+
1940
1958
  alertsDiv = document.createElement("div");
1941
1959
 
1942
1960
  (function initAlertsDiv() {
@@ -1980,6 +1998,20 @@ function initAria() {
1980
1998
 
1981
1999
  return _objectSpread2({}, INSTRUCTION_IDs);
1982
2000
  }
2001
+ /**
2002
+ * Removes all the artifacts (dom elements) added by this module
2003
+ */
2004
+
2005
+ function destroyAria() {
2006
+ if (isOnServer || !alertsDiv) return;
2007
+ Object.keys(ID_TO_INSTRUCTION).forEach(function (id) {
2008
+ var _document$getElementB;
2009
+
2010
+ return (_document$getElementB = document.getElementById(id)) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.remove();
2011
+ });
2012
+ alertsDiv.remove();
2013
+ alertsDiv = undefined;
2014
+ }
1983
2015
 
1984
2016
  function instructionToHiddenDiv(id, txt) {
1985
2017
  var div = document.createElement("div");
@@ -1997,6 +2029,12 @@ function instructionToHiddenDiv(id, txt) {
1997
2029
 
1998
2030
 
1999
2031
  function alertToScreenReader(txt) {
2032
+ if (isOnServer) return;
2033
+
2034
+ if (!alertsDiv) {
2035
+ initAriaOnBrowser();
2036
+ }
2037
+
2000
2038
  alertsDiv.innerHTML = "";
2001
2039
  var alertText = document.createTextNode(txt);
2002
2040
  alertsDiv.appendChild(alertText); // this is needed for Safari
@@ -2027,7 +2065,7 @@ var typeToDropZones$1 = new Map();
2027
2065
  * maybe keep focus on the last dragged item upon drop?
2028
2066
  */
2029
2067
 
2030
- var INSTRUCTION_IDs$1 = initAria();
2068
+ var INSTRUCTION_IDs$1;
2031
2069
  /* drop-zones registration management */
2032
2070
 
2033
2071
  function registerDropZone$1(dropZoneEl, type) {
@@ -2039,6 +2077,7 @@ function registerDropZone$1(dropZoneEl, type) {
2039
2077
  printDebug(function () {
2040
2078
  return "adding global keydown and click handlers";
2041
2079
  });
2080
+ INSTRUCTION_IDs$1 = initAria();
2042
2081
  window.addEventListener("keydown", globalKeyDownHandler);
2043
2082
  window.addEventListener("click", globalClickHandler);
2044
2083
  }
@@ -2075,6 +2114,8 @@ function unregisterDropZone$1(dropZoneEl, type) {
2075
2114
  });
2076
2115
  window.removeEventListener("keydown", globalKeyDownHandler);
2077
2116
  window.removeEventListener("click", globalClickHandler);
2117
+ INSTRUCTION_IDs$1 = undefined;
2118
+ destroyAria();
2078
2119
  }
2079
2120
  }
2080
2121
 
@@ -2392,18 +2433,19 @@ function dndzone$1(node, options) {
2392
2433
  config.dropTargetClasses = dropTargetClasses;
2393
2434
  config.autoAriaDisabled = autoAriaDisabled;
2394
2435
 
2395
- if (!autoAriaDisabled) {
2396
- node.setAttribute("aria-disabled", dragDisabled);
2397
- node.setAttribute("role", "list");
2398
- node.setAttribute("aria-describedby", dragDisabled ? INSTRUCTION_IDs$1.DND_ZONE_DRAG_DISABLED : INSTRUCTION_IDs$1.DND_ZONE_ACTIVE);
2399
- }
2400
-
2401
2436
  if (config.type && newType !== config.type) {
2402
2437
  unregisterDropZone$1(node, config.type);
2403
2438
  }
2404
2439
 
2405
2440
  config.type = newType;
2406
2441
  registerDropZone$1(node, newType);
2442
+
2443
+ if (!autoAriaDisabled) {
2444
+ node.setAttribute("aria-disabled", dragDisabled);
2445
+ node.setAttribute("role", "list");
2446
+ node.setAttribute("aria-describedby", dragDisabled ? INSTRUCTION_IDs$1.DND_ZONE_DRAG_DISABLED : INSTRUCTION_IDs$1.DND_ZONE_ACTIVE);
2447
+ }
2448
+
2407
2449
  dzToConfig$1.set(node, config);
2408
2450
 
2409
2451
  if (isDragging) {
package/package.json CHANGED
@@ -40,7 +40,7 @@
40
40
  "dist"
41
41
  ],
42
42
  "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 *",
43
- "version": "0.9.11",
43
+ "version": "0.9.15",
44
44
  "repository": {
45
45
  "type": "git",
46
46
  "url": "git+https://github.com/isaacHagoel/svelte-dnd-action.git"
@@ -13,6 +13,10 @@ const ALERT_DIV_ID = "dnd-action-aria-alert";
13
13
  let alertsDiv;
14
14
 
15
15
  function initAriaOnBrowser() {
16
+ if (alertsDiv) {
17
+ // it is already initialized
18
+ return;
19
+ }
16
20
  // setting the dynamic alerts
17
21
  alertsDiv = document.createElement("div");
18
22
  (function initAlertsDiv() {
@@ -47,6 +51,17 @@ export function initAria() {
47
51
  }
48
52
  return {...INSTRUCTION_IDs};
49
53
  }
54
+
55
+ /**
56
+ * Removes all the artifacts (dom elements) added by this module
57
+ */
58
+ export function destroyAria() {
59
+ if (isOnServer || !alertsDiv) return;
60
+ Object.keys(ID_TO_INSTRUCTION).forEach(id => document.getElementById(id)?.remove());
61
+ alertsDiv.remove();
62
+ alertsDiv = undefined;
63
+ }
64
+
50
65
  function instructionToHiddenDiv(id, txt) {
51
66
  const div = document.createElement("div");
52
67
  div.id = id;
@@ -62,6 +77,10 @@ function instructionToHiddenDiv(id, txt) {
62
77
  * @param {string} txt
63
78
  */
64
79
  export function alertToScreenReader(txt) {
80
+ if (isOnServer) return;
81
+ if (!alertsDiv) {
82
+ initAriaOnBrowser();
83
+ }
65
84
  alertsDiv.innerHTML = "";
66
85
  const alertText = document.createTextNode(txt);
67
86
  alertsDiv.appendChild(alertText);
@@ -12,6 +12,15 @@ export function resetIndexesCache() {
12
12
  }
13
13
  resetIndexesCache();
14
14
 
15
+ /**
16
+ * Resets the cache that allows for smarter "would be index" resolution for a specific dropzone, should be called after the zone was scrolled
17
+ * @param {HTMLElement} dz
18
+ */
19
+ export function resetIndexesCacheForDz(dz) {
20
+ printDebug(() => "resetting indexes cache for dz");
21
+ dzToShadowIndexToRect.delete(dz);
22
+ }
23
+
15
24
  /**
16
25
  * Caches the coordinates of the shadow element when it's in a certain index in a certain dropzone.
17
26
  * Helpful in order to determine "would be index" more effectively
@@ -1,4 +1,4 @@
1
- import {findWouldBeIndex, resetIndexesCache} from "./listUtil";
1
+ import {findWouldBeIndex, resetIndexesCache, resetIndexesCacheForDz} from "./listUtil";
2
2
  import {findCenterOfElement, isElementOffDocument} from "./intersection";
3
3
  import {
4
4
  dispatchDraggedElementEnteredContainer,
@@ -57,6 +57,7 @@ export function observe(draggedEl, dropZones, intervalMs = INTERVAL_MS) {
57
57
  // this is a simple algorithm, potential improvement: first look at lastDropZoneFound
58
58
  let isDraggedInADropZone = false;
59
59
  for (const dz of dropZonesFromDeepToShallow) {
60
+ if (scrolled) resetIndexesCacheForDz(lastDropZoneFound);
60
61
  const indexObj = findWouldBeIndex(draggedEl, dz);
61
62
  if (indexObj === null) {
62
63
  // it is not inside
@@ -1,5 +1,6 @@
1
1
  import {makeScroller} from "./scroller";
2
2
  import {printDebug} from "../constants";
3
+ import {resetIndexesCache} from "./listUtil";
3
4
 
4
5
  const INTERVAL_MS = 300;
5
6
  let mousePosition;
@@ -18,7 +19,8 @@ let next;
18
19
 
19
20
  function loop() {
20
21
  if (mousePosition) {
21
- scrollIfNeeded(mousePosition, document.documentElement);
22
+ const scrolled = scrollIfNeeded(mousePosition, document.documentElement);
23
+ if (scrolled) resetIndexesCache();
22
24
  }
23
25
  next = window.setTimeout(loop, INTERVAL_MS);
24
26
  }
@@ -1,7 +1,7 @@
1
1
  import {decrementActiveDropZoneCount, incrementActiveDropZoneCount, ITEM_ID_KEY, SOURCES, TRIGGERS} from "./constants";
2
2
  import {styleActiveDropZones, styleInactiveDropZones} from "./helpers/styler";
3
3
  import {dispatchConsiderEvent, dispatchFinalizeEvent} from "./helpers/dispatcher";
4
- import {initAria, alertToScreenReader} from "./helpers/aria";
4
+ import {initAria, alertToScreenReader, destroyAria} from "./helpers/aria";
5
5
  import {toString} from "./helpers/util";
6
6
  import {printDebug} from "./constants";
7
7
 
@@ -29,13 +29,14 @@ const typeToDropZones = new Map();
29
29
  * maybe keep focus on the last dragged item upon drop?
30
30
  */
31
31
 
32
- const INSTRUCTION_IDs = initAria();
32
+ let INSTRUCTION_IDs;
33
33
 
34
34
  /* drop-zones registration management */
35
35
  function registerDropZone(dropZoneEl, type) {
36
36
  printDebug(() => "registering drop-zone if absent");
37
37
  if (typeToDropZones.size === 0) {
38
38
  printDebug(() => "adding global keydown and click handlers");
39
+ INSTRUCTION_IDs = initAria();
39
40
  window.addEventListener("keydown", globalKeyDownHandler);
40
41
  window.addEventListener("click", globalClickHandler);
41
42
  }
@@ -61,6 +62,8 @@ function unregisterDropZone(dropZoneEl, type) {
61
62
  printDebug(() => "removing global keydown and click handlers");
62
63
  window.removeEventListener("keydown", globalKeyDownHandler);
63
64
  window.removeEventListener("click", globalClickHandler);
65
+ INSTRUCTION_IDs = undefined;
66
+ destroyAria();
64
67
  }
65
68
  }
66
69
 
@@ -280,16 +283,16 @@ export function dndzone(node, options) {
280
283
  config.dropTargetStyle = dropTargetStyle;
281
284
  config.dropTargetClasses = dropTargetClasses;
282
285
  config.autoAriaDisabled = autoAriaDisabled;
283
- if (!autoAriaDisabled) {
284
- node.setAttribute("aria-disabled", dragDisabled);
285
- node.setAttribute("role", "list");
286
- node.setAttribute("aria-describedby", dragDisabled ? INSTRUCTION_IDs.DND_ZONE_DRAG_DISABLED : INSTRUCTION_IDs.DND_ZONE_ACTIVE);
287
- }
288
286
  if (config.type && newType !== config.type) {
289
287
  unregisterDropZone(node, config.type);
290
288
  }
291
289
  config.type = newType;
292
290
  registerDropZone(node, newType);
291
+ if (!autoAriaDisabled) {
292
+ node.setAttribute("aria-disabled", dragDisabled);
293
+ node.setAttribute("role", "list");
294
+ node.setAttribute("aria-describedby", dragDisabled ? INSTRUCTION_IDs.DND_ZONE_DRAG_DISABLED : INSTRUCTION_IDs.DND_ZONE_ACTIVE);
295
+ }
293
296
  dzToConfig.set(node, config);
294
297
 
295
298
  if (isDragging) {
@@ -298,8 +301,8 @@ export function dndzone(node, options) {
298
301
  focusedItem.contains(node) ||
299
302
  config.dropFromOthersDisabled ||
300
303
  (focusedDz && config.type !== dzToConfig.get(focusedDz).type)
301
- ? -1
302
- : 0;
304
+ ? -1
305
+ : 0;
303
306
  } else {
304
307
  node.tabIndex = config.zoneTabIndex;
305
308
  }