svelte-dnd-action
Advanced tools
Comparing version 0.9.28 to 0.9.29
@@ -81,2 +81,3 @@ /** | ||
export declare const DRAGGED_ELEMENT_ID: "dnd-action-dragged-el"; | ||
export declare const SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-hint"; | ||
@@ -83,0 +84,0 @@ /** |
@@ -45,4 +45,4 @@ { | ||
], | ||
"description": "*An awesome drag and drop library for Svelte 3 (not using the browser's built-in dnd, thanks god): Rich animations, nested containers, touch support and more *", | ||
"version": "0.9.28", | ||
"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 *", | ||
"version": "0.9.29", | ||
"repository": { | ||
@@ -49,0 +49,0 @@ "type": "git", |
@@ -350,2 +350,28 @@ # SVELTE DND ACTION [![Known Vulnerabilities](https://snyk.io/test/github/isaacHagoel/svelte-dnd-action/badge.svg?targetFile=package.json)](https://snyk.io/test/github/isaacHagoel/svelte-dnd-action?targetFile=package.json) | ||
### Nested Zones Optional Optimization (experimental) | ||
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. | ||
Specifically, it allows nested zones within the shadow element (the placeholder under the dragged element) to register and destroy. | ||
This is because Svelte calls nested actions before the parent action (opposite to the rendering order). | ||
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]} ` | ||
#### Simplified Example (just shows where to place the attribute): | ||
```html | ||
<script> | ||
import {dndzone, SHADOW_ITEM_MARKER_PROPERTY_NAME} from 'svelte-dnd-action'; | ||
let items = []; | ||
</script> | ||
<section> | ||
<div use:dndzone={{items}} on:consider={e => items = e.detail.items} on:finalize={e => items = e.detail.items}> | ||
{#each items as item (item.id)} | ||
<div data-is-dnd-shadow-item-hint={item[SHADOW_ITEM_MARKER_PROPERTY_NAME]}> | ||
<h1>{item.title}</h1> | ||
<!--more nested zones go here, can include the attribute on their items as demonstrated above--> | ||
</div> | ||
{/each} | ||
</div> | ||
</section> | ||
``` | ||
### Contributing [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/isaacHagoel/svelte-dnd-action/issues) | ||
@@ -352,0 +378,0 @@ |
import {dndzone as pointerDndZone} from "./pointerAction"; | ||
import {dndzone as keyboardDndZone} from "./keyboardAction"; | ||
import {ITEM_ID_KEY} from "./constants"; | ||
import {ITEM_ID_KEY, SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME} from "./constants"; | ||
import {toString} from "./helpers/util"; | ||
@@ -28,2 +28,8 @@ | ||
export function dndzone(node, options) { | ||
if (shouldIgnoreZone(node)) { | ||
return { | ||
update: () => {}, | ||
destroy: () => {} | ||
}; | ||
} | ||
validateOptions(options); | ||
@@ -45,2 +51,12 @@ const pointerZone = pointerDndZone(node, options); | ||
/** | ||
* If the user marked something in the ancestry of our node as shadow element, we can ignore it | ||
* We need the user to mark it for us because svelte updates the action from deep to shallow (but renders top down) | ||
* @param {HTMLElement} node | ||
* @return {boolean} | ||
*/ | ||
function shouldIgnoreZone(node) { | ||
return !!node.closest(`[${SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME}="true"]`); | ||
} | ||
function validateOptions(options) { | ||
@@ -47,0 +63,0 @@ /*eslint-disable*/ |
@@ -22,3 +22,4 @@ import {DRAGGED_ENTERED_EVENT_NAME, DRAGGED_LEFT_EVENT_NAME, DRAGGED_OVER_INDEX_EVENT_NAME} from "./helpers/dispatcher"; | ||
export const SHADOW_ITEM_MARKER_PROPERTY_NAME = "isDndShadowItem"; | ||
export const SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item"; | ||
export const SHADOW_ELEMENT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-internal"; | ||
export const SHADOW_ELEMENT_HINT_ATTRIBUTE_NAME = "data-is-dnd-shadow-item-hint"; | ||
export const SHADOW_PLACEHOLDER_ITEM_ID = "id:dnd-shadow-placeholder-0000"; | ||
@@ -25,0 +26,0 @@ export const DRAGGED_ELEMENT_ID = "dnd-action-dragged-el"; |
@@ -43,2 +43,3 @@ import { | ||
}; | ||
const ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE = "data-is-dnd-original-dragged-item"; | ||
@@ -118,9 +119,4 @@ let originalDragTarget; | ||
// finds the initial placeholder that is placed there on drag start | ||
function findShadowPlaceHolderIdx(items) { | ||
return items.findIndex(item => item[ITEM_ID_KEY] === SHADOW_PLACEHOLDER_ITEM_ID); | ||
} | ||
function findShadowElementIdx(items) { | ||
// checking that the id is not the placeholder's for Dragula like usecases | ||
return items.findIndex(item => !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME] && item[ITEM_ID_KEY] !== SHADOW_PLACEHOLDER_ITEM_ID); | ||
return items.findIndex(item => !!item[SHADOW_ITEM_MARKER_PROPERTY_NAME]); | ||
} | ||
@@ -149,11 +145,3 @@ | ||
}); | ||
} else { | ||
const shadowPlaceHolderIdx = findShadowPlaceHolderIdx(items); | ||
if (shadowPlaceHolderIdx !== -1) { | ||
// only happens right after drag start, on the first drag entered event | ||
printDebug(() => "removing placeholder item from origin dz"); | ||
items.splice(shadowPlaceHolderIdx, 1); | ||
} | ||
} | ||
const {index, isProximityBased} = e.detail.indexObj; | ||
@@ -251,2 +239,3 @@ const shadowElIdx = isProximityBased && index === e.currentTarget.children.length - 1 ? index + 1 : index; | ||
if (shadowElIdx === -1) shadowElIdx = originIndex; | ||
items = items.map(item => (item[SHADOW_ITEM_MARKER_PROPERTY_NAME] ? draggedElData : item)); | ||
@@ -408,8 +397,8 @@ function finalizeWithinZone() { | ||
draggedElType = type; | ||
shadowElData = {...draggedElData, [SHADOW_ITEM_MARKER_PROPERTY_NAME]: true}; | ||
// The initial shadow element. We need a different id at first in order to avoid conflicts and timing issues | ||
const placeHolderElData = {...shadowElData, [ITEM_ID_KEY]: SHADOW_PLACEHOLDER_ITEM_ID}; | ||
shadowElData = {...draggedElData, [SHADOW_ITEM_MARKER_PROPERTY_NAME]: true, [ITEM_ID_KEY]: SHADOW_PLACEHOLDER_ITEM_ID}; | ||
// creating the draggable element | ||
draggedEl = createDraggedElementFrom(originalDragTarget, centreDraggedOnCursor && currentMousePosition); | ||
originalDragTarget.setAttribute(ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE, true); | ||
// 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 | ||
@@ -437,3 +426,3 @@ function keepOriginalElementInDom() { | ||
// removing the original element by removing its data entry | ||
items.splice(currentIdx, 1, placeHolderElData); | ||
items.splice(currentIdx, 1, shadowElData); | ||
unlockOriginDzMinDimensions = preventShrinking(originDropZone); | ||
@@ -558,3 +547,3 @@ | ||
} | ||
if (isWorkingOnPreviousDrag) { | ||
if (isWorkingOnPreviousDrag && !node.closest(`[${ORIGINAL_DRAGGED_ITEM_MARKER_ATTRIBUTE}]`)) { | ||
printDebug(() => "pointer dndzone will be scheduled for destruction"); | ||
@@ -561,0 +550,0 @@ scheduleDZForRemovalAfterDrop(node, destroyDz); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
289724
6782
381