From 49620ef26bbfa929d4de435955c4f21c2b0160e0 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Wed, 13 May 2026 05:10:29 +0300 Subject: [PATCH] fix(vue): distinguish layer child drops --- .../primitives/LayerTree/LayerTreeRoot.vue | 10 +++- .../src/primitives/LayerTree/useLayerDrag.ts | 30 +++++++--- src/components/LayerTree.vue | 13 ++++- tests/e2e/layers/reorder.spec.ts | 56 +++++++++++++++++-- 4 files changed, 91 insertions(+), 18 deletions(-) diff --git a/packages/vue/src/primitives/LayerTree/LayerTreeRoot.vue b/packages/vue/src/primitives/LayerTree/LayerTreeRoot.vue index 1d23fb8cd..d317afa4a 100644 --- a/packages/vue/src/primitives/LayerTree/LayerTreeRoot.vue +++ b/packages/vue/src/primitives/LayerTree/LayerTreeRoot.vue @@ -21,9 +21,15 @@ const emit = defineEmits<{ }>() const editor = useEditor() + +function expandNode(id: string) { + if (!expanded.value.includes(id)) expanded.value = [...expanded.value, id] +} + const { draggingId, instruction, instructionTargetId, setupItem } = useLayerDrag( editor, - indentPerLevel + indentPerLevel, + expandNode ) function buildTree(parentId: string): LayerNode[] { @@ -108,7 +114,7 @@ function toggleExpand(id: string) { emit('toggleExpand', id) const idx = expanded.value.indexOf(id) if (idx !== -1) expanded.value = expanded.value.filter((e) => e !== id) - else expanded.value = [...expanded.value, id] + else expandNode(id) } function getKey(node: LayerNode) { diff --git a/packages/vue/src/primitives/LayerTree/useLayerDrag.ts b/packages/vue/src/primitives/LayerTree/useLayerDrag.ts index acbb9be44..1646d5894 100644 --- a/packages/vue/src/primitives/LayerTree/useLayerDrag.ts +++ b/packages/vue/src/primitives/LayerTree/useLayerDrag.ts @@ -24,7 +24,11 @@ interface DragItem { type TreeInstruction = LayerDragInstruction -export function useLayerDrag(editor: Editor, indentPerLevel = 16) { +export function useLayerDrag( + editor: Editor, + indentPerLevel = 16, + onMakeChildDrop?: (targetId: string) => void +) { const draggingId = ref(null) const instruction = ref(null) const instructionTargetId = ref(null) @@ -36,6 +40,7 @@ export function useLayerDrag(editor: Editor, indentPerLevel = 16) { const data = item() + const isContainer = editor.graph.isContainer(data.id) const mode: ItemMode = data.hasChildren ? 'expanded' : 'standard' const cleanup = combine( @@ -60,14 +65,19 @@ export function useLayerDrag(editor: Editor, indentPerLevel = 16) { indentPerLevel, currentLevel: data.level, mode, - block: ['make-child', 'reparent'] + block: isContainer ? ['reparent'] : ['make-child', 'reparent'] } ), canDrop: ({ source }) => source.data.id !== data.id, onDrag: ({ self }) => { - const inst = extractInstruction(self.data) as TreeInstruction | null - instruction.value = inst - instructionTargetId.value = inst ? data.id : null + const inst = extractInstruction(self.data) + if (!inst || inst.type === 'instruction-blocked') { + instruction.value = null + instructionTargetId.value = null + return + } + instruction.value = inst as TreeInstruction + instructionTargetId.value = data.id }, onDragLeave: () => { instruction.value = null @@ -92,8 +102,10 @@ export function useLayerDrag(editor: Editor, indentPerLevel = 16) { const sourceId = source.data.id as string const targetId = target.data.id as string - const inst = extractInstruction(target.data) as TreeInstruction | null - if (!inst || !sourceId || !targetId) return + const rawInstruction = extractInstruction(target.data) + if (!rawInstruction || rawInstruction.type === 'instruction-blocked') return + const inst = rawInstruction as TreeInstruction + if (!sourceId || !targetId) return if (editor.graph.isDescendant(targetId, sourceId)) return @@ -110,7 +122,9 @@ export function useLayerDrag(editor: Editor, indentPerLevel = 16) { editor.reorderChildWithUndo(sourceId, targetParentId, targetIndex + 1) } else { const container = editor.graph.getNode(targetId) - editor.reorderChildWithUndo(sourceId, targetId, container?.childIds.length ?? 0) + if (!container || !editor.graph.isContainer(targetId)) return + editor.reorderChildWithUndo(sourceId, targetId, container.childIds.length) + onMakeChildDrop?.(targetId) } draggingId.value = null diff --git a/src/components/LayerTree.vue b/src/components/LayerTree.vue index d4204105f..4687aafb1 100644 --- a/src/components/LayerTree.vue +++ b/src/components/LayerTree.vue @@ -111,7 +111,7 @@ function onTreeSelect(e: CustomEvent, select: (additive: boolean) => void) { : 'bg-transparent text-surface hover:bg-hover', draggingId === node.id ? 'opacity-30' : '', instructionTargetId === node.id && instruction?.type === 'make-child' - ? 'ring-2 ring-accent ring-inset' + ? 'bg-accent/15 text-surface outline-2 outline-accent outline-offset-[-2px]' : '', !node.visible ? 'opacity-50' : '' ]" @@ -181,7 +181,16 @@ function onTreeSelect(e: CustomEvent, select: (additive: boolean) => void) { - +
+ +