diff --git a/src/lib/layout/EditableGrid.svelte b/src/lib/layout/EditableGrid.svelte index ee10ee2..7ac9711 100644 --- a/src/lib/layout/EditableGrid.svelte +++ b/src/lib/layout/EditableGrid.svelte @@ -100,7 +100,6 @@ dragState.mouseDeltaX = rect.left - e.clientX; dragState.mouseDeltaY = rect.top - e.clientY; - // Do NOT preventDefault — allow scroll on touch document.addEventListener('pointermove', handlePointerMove); document.addEventListener('pointerup', handlePointerUp); document.addEventListener('pointercancel', handlePointerCancel); @@ -271,6 +270,15 @@ }; }); + // For touch: register non-passive touchstart to prevent scroll when touching selected card + $effect(() => { + if (!container || !selectedCardId) return; + container.addEventListener('touchstart', handleTouchStart, { passive: false }); + return () => { + container?.removeEventListener('touchstart', handleTouchStart); + }; + }); + // For touch: register non-passive touchmove to prevent scroll during active drag $effect(() => { if (phase !== 'active' || !container) return; @@ -290,6 +298,18 @@ } } + function handleTouchStart(e: TouchEvent) { + // On touch, prevent scrolling when touching the selected card + // This must happen on touchstart (not pointerdown) to claim the gesture + const cardEl = (e.target as HTMLElement)?.closest?.('.card') as HTMLElement | null; + if (cardEl && cardEl.id === selectedCardId) { + const item = items.find((i) => i.id === cardEl.id); + if (item && !item.cardData?.locked) { + e.preventDefault(); + } + } + } + // --- File drop handlers --- function hasImageFile(dt: DataTransfer): boolean {