diff --git a/mixins/tree-dnd.js b/mixins/tree-dnd.js index bc318c4..3d2b308 100644 --- a/mixins/tree-dnd.js +++ b/mixins/tree-dnd.js @@ -22,6 +22,7 @@ export const TreeDnDMixin = (superClass) => class TreeDnDMixin extends superClas _onDragEnd(item, e) { this._dragSource = null; + this._clearAllDragClasses(); } _onDragOver(item, e) { @@ -66,7 +67,7 @@ export const TreeDnDMixin = (superClass) => class TreeDnDMixin extends superClas e.dataTransfer.dropEffect = 'move'; - this._clearDragClasses(row); + this._clearAllDragClasses(); row.classList.add(`drag-over-${position}`); if (dragDepth !== undefined) { row.style.setProperty('--drag-depth', dragDepth); @@ -99,7 +100,7 @@ export const TreeDnDMixin = (superClass) => class TreeDnDMixin extends superClas return; } - const { target: logicalTarget, position: logicalPosition } = this._resolveDropTarget(item, position, e); + const { target: logicalTarget, position: logicalPosition, depth: logicalDepth } = this._resolveDropTarget(item, position, e); if (this._isNoOp(this._dragSource, logicalTarget, logicalPosition)) { return; @@ -114,6 +115,7 @@ export const TreeDnDMixin = (superClass) => class TreeDnDMixin extends superClas source: this._dragSource, target: logicalTarget, position: logicalPosition, + depth: logicalDepth, originalEvent: e }, bubbles: true, @@ -127,6 +129,9 @@ export const TreeDnDMixin = (superClass) => class TreeDnDMixin extends superClas if (!source || !target) return true; if (source.key === target.key) return true; + // Prevent dropping a node into its own subtree (would create a cycle). + if (target.key.startsWith(source.key + '/')) return true; + const srcPathStr = source.path.slice(0, -1).join('/'); const tgtPathStr = target.path.slice(0, -1).join('/'); @@ -174,7 +179,7 @@ export const TreeDnDMixin = (superClass) => class TreeDnDMixin extends superClas if (position === 'after' && e) { const nextItem = this._flatItems[index + 1]; const currentDepth = currentItem.depth; - const nextDepth = nextItem ? nextItem.depth : -1; + const nextDepth = nextItem ? nextItem.depth : 0; if (nextDepth < currentDepth) { const row = e.currentTarget; @@ -211,4 +216,11 @@ export const TreeDnDMixin = (superClass) => class TreeDnDMixin extends superClas row.classList.remove('drag-over-inside', 'drag-over-before', 'drag-over-after'); row.style.removeProperty('--drag-depth'); } + + _clearAllDragClasses() { + const rows = this.shadowRoot?.querySelectorAll('.drag-over-inside, .drag-over-before, .drag-over-after'); + if (rows) { + rows.forEach((row) => this._clearDragClasses(row)); + } + } };