1212 <div
1313 v-for =" node in rows"
1414 :key =" node.id"
15- :class =" rowClass(isRowSelected(node.id))"
15+ :class =" cn( rowClass(isRowSelected(node.id)), dropHintClass (node.id))"
1616 data-testid =" layer-panel-row"
17+ :draggable =" renamingId !== node.id"
1718 @click =" onRowClick(node.id, $event)"
19+ @dragstart =" onRowDragStart(node.id, $event)"
20+ @dragover =" onRowDragOver(node.id, $event)"
21+ @drop =" onRowDrop(node.id, $event)"
22+ @dragend =" endDrag"
1823 >
1924 <button
2025 :class =" eyeButtonClass(node.visible)"
3439 <input
3540 v-if =" renamingId === node.id"
3641 :ref =" focusInput"
37- class =" min-w-0 rounded-sm border border-border-default bg-base-background px-1 text-xs text-base-foreground"
42+ class =" min-w-0 rounded-sm border border-border-default bg-base-background px-1 text-xs text-base-foreground select-text "
3843 :value =" node.name"
3944 @blur =" commitRename(node.id, $event)"
4045 @keydown.enter =" commitRename(node.id, $event)"
@@ -115,6 +120,11 @@ import { computed, ref, watch } from 'vue'
115120import type { ComponentPublicInstance } from ' vue'
116121import { useI18n } from ' vue-i18n'
117122
123+ import type { LayerDropPos } from ' @/renderer/extensions/layerEditor/composables/layerPanelDnd'
124+ import {
125+ dropPositionFor ,
126+ reorderDropIndex
127+ } from ' @/renderer/extensions/layerEditor/composables/layerPanelDnd'
118128import { DEFAULT_BACKGROUND_COLOR } from ' @/renderer/extensions/layerEditor/composables/useLayerEditorSession'
119129import type { LayerEditorSession } from ' @/renderer/extensions/layerEditor/composables/useLayerEditorSession'
120130import type {
@@ -167,7 +177,7 @@ function isRowSelected(id: string): boolean {
167177
168178function rowClass(selected : boolean , extra ? : string ): string {
169179 return cn (
170- ' group flex cursor-pointer items-center gap-2 border-border-default px-2 py-1.5' ,
180+ ' group flex cursor-pointer items-center gap-2 border-border-default px-2 py-1.5 select-none ' ,
171181 ' hover:bg-secondary-background-hover' ,
172182 selected && ' bg-secondary-background-selected' ,
173183 extra
@@ -188,6 +198,60 @@ function eyeIconClass(visible: boolean): string {
188198 )
189199}
190200
201+ const dragId = ref <string | null >(null )
202+ const dropHint = ref <{ id: string ; pos: LayerDropPos } | null >(null )
203+
204+ function endDrag(): void {
205+ dragId .value = null
206+ dropHint .value = null
207+ }
208+
209+ function dropHintClass(id : string ): string {
210+ const hint = dropHint .value
211+ if (hint ?.id !== id ) return ' relative'
212+ return cn (
213+ ' relative' ,
214+ hint .pos === ' above'
215+ ? " before:absolute before:inset-x-0 before:top-0 before:h-0.5 before:bg-base-foreground before:content-['']"
216+ : " after:absolute after:inset-x-0 after:bottom-0 after:h-0.5 after:bg-base-foreground after:content-['']"
217+ )
218+ }
219+
220+ function onRowDragStart(id : string , e : DragEvent ): void {
221+ dragId .value = id
222+ if (e .dataTransfer ) {
223+ e .dataTransfer .effectAllowed = ' move'
224+ e .dataTransfer .setData (' text/plain' , id )
225+ }
226+ }
227+
228+ function onRowDragOver(id : string , e : DragEvent ): void {
229+ if (! dragId .value || dragId .value === id ) return
230+ e .preventDefault ()
231+ if (e .dataTransfer ) e .dataTransfer .dropEffect = ' move'
232+ const rect = (e .currentTarget as HTMLElement ).getBoundingClientRect ()
233+ const ratio = rect .height > 0 ? (e .clientY - rect .top ) / rect .height : 0.5
234+ const pos = dropPositionFor (ratio )
235+ if (dropHint .value ?.id !== id || dropHint .value ?.pos !== pos )
236+ dropHint .value = { id , pos }
237+ }
238+
239+ function onRowDrop(id : string , e : DragEvent ): void {
240+ e .preventDefault ()
241+ const dragged = dragId .value
242+ const hint = dropHint .value
243+ if (dragged && hint ?.id === id ) {
244+ const toIndex = reorderDropIndex (
245+ imageLayers .value .map ((n ) => n .id ),
246+ id ,
247+ hint .pos ,
248+ backgroundLayer .value ? 1 : 0
249+ )
250+ if (toIndex !== null ) session .moveLayerTo (dragged , toIndex )
251+ }
252+ endDrag ()
253+ }
254+
191255function onRowClick(id : string , e : MouseEvent ): void {
192256 if (e .ctrlKey || e .metaKey || e .shiftKey ) {
193257 const current = selectedNodeIds .value
0 commit comments