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"
>
- onTouchStart(e, idx)">⠿
+ onPointerDown(e, idx)">⠿
![]()
{
+ 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;