diff --git a/frontend/src/components/panels/Layers.svelte b/frontend/src/components/panels/Layers.svelte index 82c8a5f068..a048a7bf8c 100644 --- a/frontend/src/components/panels/Layers.svelte +++ b/frontend/src/components/panels/Layers.svelte @@ -291,7 +291,7 @@ editor.handle.deselectAllLayers(); } - function calculateDragIndex(tree: LayoutCol, clientY: number, select?: () => void): DraggingData { + function calculateDragIndex(tree: LayoutCol, clientY: number, dataIndex: number, select?: () => void): DraggingData | undefined { const treeChildren = tree.div()?.children; const treeOffset = tree.div()?.getBoundingClientRect().top; @@ -307,17 +307,47 @@ let markerHeight = 0; const layerPanel = document.querySelector("[data-layer-panel]"); // Selects the element with the data-layer-panel attribute + let isInvalidDrag = false; + if (layerPanel !== null && treeChildren !== undefined && treeOffset !== undefined) { + const lastLayerDepth = layers[layers.length - 1]?.entry?.depth; + const draggingLayerDepth = layers[dataIndex]?.entry?.depth; + + if (clientY > treeChildren[layers.length - 1].getBoundingClientRect().bottom - 10) { + if (lastLayerDepth === 1 && draggingLayerDepth > 1) isInvalidDrag = true; + } + let layerPanelTop = layerPanel.getBoundingClientRect().top; - Array.from(treeChildren).forEach((treeChild) => { - const indexAttribute = treeChild.getAttribute("data-index"); - if (!indexAttribute) return; - const { folderIndex, entry: layer } = layers[parseInt(indexAttribute, 10)]; + + for (const treeChild of Array.from(treeChildren)) { + if (isInvalidDrag) break; + const indexAttribute = parseInt(treeChild.getAttribute("data-index") ?? "0", 10); + if (!indexAttribute) continue; + const { folderIndex, entry: layer } = layers[indexAttribute]; const rect = treeChild.getBoundingClientRect(); if (rect.top > clientY || rect.bottom < clientY) { - return; + continue; + } + if (draggingLayerDepth > 1) { + const prevLayer = layers[indexAttribute]; + const nextLayer = layers[indexAttribute + 1]; + if (prevLayer?.entry?.depth === 1) { + const prevRectTop = treeChildren?.[indexAttribute].getBoundingClientRect().top; + if (prevLayer?.entry?.depth === 1 && prevRectTop + 10 > clientY) { + isInvalidDrag = true; + break; + } + } + + const isDraggingBtnArtBoards = nextLayer?.entry?.depth === 1 && prevLayer?.entry?.depth === 1; + + if (isDraggingBtnArtBoards) { + isInvalidDrag = true; + break; + } } + const pointerPercentage = (clientY - rect.top) / rect.height; if (layer.childrenAllowed) { if (pointerPercentage < 0.25) { @@ -349,7 +379,8 @@ markerHeight = rect.bottom - layerPanelTop; } } - }); + break; + } // Dragging to the empty space below all layers let lastLayer = treeChildren[treeChildren.length - 1]; if (lastLayer.getBoundingClientRect().bottom < clientY) { @@ -359,6 +390,7 @@ insertIndex = numberRootLayers; markerHeight = lastLayer.getBoundingClientRect().bottom - layerPanelTop; } + if (isInvalidDrag) return; } return { @@ -384,7 +416,11 @@ const target = (event.target instanceof HTMLElement && event.target) || undefined; const closest = target?.closest("[data-layer]") || undefined; const draggingELement = (closest instanceof HTMLElement && closest) || undefined; - if (draggingELement) beginDraggingElement(draggingELement); + if (draggingELement) { + beginDraggingElement(draggingELement); + // Store the index of the layer being dragged + draggedLayerIndex = parseInt(draggingELement.getAttribute("data-index") ?? "0", 10); + } // Set style of cursor for drag if (event.dataTransfer) { @@ -392,9 +428,13 @@ event.dataTransfer.effectAllowed = "move"; } - if (list) draggingData = calculateDragIndex(list, event.clientY, select); + if (list && draggedLayerIndex !== undefined) { + draggingData = calculateDragIndex(list, event.clientY, draggedLayerIndex, select); + } } + let draggedLayerIndex: number | undefined; + function updateInsertLine(event: DragEvent) { if (!draggable) return; @@ -402,7 +442,10 @@ event.preventDefault(); dragInPanel = true; - if (list) draggingData = calculateDragIndex(list, event.clientY, draggingData?.select); + // Use the stored index from dragStart + if (list && draggedLayerIndex !== undefined) { + draggingData = calculateDragIndex(list, event.clientY, draggedLayerIndex, draggingData?.select); + } } function drop(e: DragEvent) { @@ -452,6 +495,7 @@ draggingData = undefined; fakeHighlightOfNotYetSelectedLayerBeingDragged = undefined; dragInPanel = false; + draggedLayerIndex = undefined; } function rebuildLayerHierarchy(updateDocumentLayerStructure: DocumentLayerStructure) {