diff --git a/frontend/src/components/routine/RoutineEditView.vue b/frontend/src/components/routine/RoutineEditView.vue index d6b77f3..a3a761e 100644 --- a/frontend/src/components/routine/RoutineEditView.vue +++ b/frontend/src/components/routine/RoutineEditView.vue @@ -28,13 +28,8 @@ class="item-row" :data-idx="idx" :class="{ 'drag-over': dragOverIdx === idx, dragging: draggingIdx === idx }" - draggable="true" - @dragstart="(e) => onDragStart(e, idx)" - @dragover.prevent="(e) => onDragOver(e, idx)" - @drop.prevent="onDrop(idx)" - @dragend="onDragEnd" > - +
{ + const handlePointerMove = (moveEvt: PointerEvent) => { moveEvt.preventDefault() - const touch = moveEvt.touches[0] - const el = document.elementFromPoint(touch.clientX, touch.clientY) as Element | null + const el = document.elementFromPoint(moveEvt.clientX, moveEvt.clientY) as Element | null if (!el) return const row = el.closest('[data-idx]') as HTMLElement | null if (!row) return @@ -381,29 +345,35 @@ function onTouchStart(e: TouchEvent, idx: number) { } } - const handleTouchEnd = (endEvt: TouchEvent) => { - const touch = endEvt.changedTouches[0] - const el = document.elementFromPoint(touch.clientX, touch.clientY) as Element | null - const fromIdx = draggingIdx.value - if (el && fromIdx !== null) { - const row = el.closest('[data-idx]') as HTMLElement | null - if (row) { - const toIdx = parseInt(row.dataset.idx ?? '-1') - if (toIdx !== -1 && toIdx !== fromIdx) { - const moved = items.value.splice(fromIdx, 1)[0] - items.value.splice(toIdx, 0, moved) - normalizeItemOrder() + const cleanup = (upEvt?: PointerEvent) => { + if (upEvt) { + const el = document.elementFromPoint(upEvt.clientX, upEvt.clientY) as Element | null + const fromIdx = draggingIdx.value + if (el && fromIdx !== null) { + const row = el.closest('[data-idx]') as HTMLElement | null + if (row) { + const toIdx = parseInt(row.dataset.idx ?? '-1') + if (toIdx !== -1 && toIdx !== fromIdx) { + const moved = items.value.splice(fromIdx, 1)[0] + items.value.splice(toIdx, 0, moved) + normalizeItemOrder() + } } } } draggingIdx.value = null dragOverIdx.value = null - document.removeEventListener('touchmove', handleTouchMove) - document.removeEventListener('touchend', handleTouchEnd) + document.removeEventListener('pointermove', handlePointerMove) + document.removeEventListener('pointerup', handlePointerUp) + document.removeEventListener('pointercancel', handlePointerCancel) } - document.addEventListener('touchmove', handleTouchMove, { passive: false }) - document.addEventListener('touchend', handleTouchEnd) + const handlePointerUp = (upEvt: PointerEvent) => cleanup(upEvt) + const handlePointerCancel = () => cleanup() + + document.addEventListener('pointermove', handlePointerMove, { passive: false }) + document.addEventListener('pointerup', handlePointerUp) + document.addEventListener('pointercancel', handlePointerCancel) } async function uploadImage(file: File): Promise { @@ -575,8 +545,9 @@ function handleCancel() { cursor: grab; color: var(--form-label, #aaa); font-size: 1.15rem; - padding-right: 0.45rem; + padding: 0.4rem 0.45rem 0.4rem 0; user-select: none; + touch-action: none; flex-shrink: 0; } @@ -584,13 +555,6 @@ function handleCancel() { cursor: grabbing; } -@media (hover: none) { - .drag-handle { - padding: 0.5rem 0.6rem; - font-size: 1.4rem; - } -} - .item-left { display: flex; align-items: center;