diff --git a/docs/superpowers/plans/2026-05-18-table-fidelity-features.md b/docs/superpowers/plans/2026-05-18-table-fidelity-features.md index 343a8c3..3890cdd 100644 --- a/docs/superpowers/plans/2026-05-18-table-fidelity-features.md +++ b/docs/superpowers/plans/2026-05-18-table-fidelity-features.md @@ -873,6 +873,12 @@ function makeDrag() { let suppressClickOn: Square | null = null; const THRESHOLD = 6; + function detach() { + window.removeEventListener('pointermove', onMove); + window.removeEventListener('pointerup', onUp); + window.removeEventListener('pointercancel', onCancel); + } + function onMove(e: PointerEvent) { if (!state.active) return; state.x = e.clientX; @@ -882,15 +888,23 @@ function makeDrag() { } } + // pointercancel fires instead of pointerup when the browser/OS takes over + // the gesture (common on touch). Abort the drag: clean up, drop nothing. + function onCancel() { + detach(); + state.active = null; + state.moved = false; + } + function onUp(e: PointerEvent) { - window.removeEventListener('pointermove', onMove); - window.removeEventListener('pointerup', onUp); + detach(); const src = state.active; const wasDrag = state.moved; state.active = null; state.moved = false; if (!src || !wasDrag) return; // a tap — the board click handler deals with it + // elementFromPoint returns null off-viewport — treated as an off-board drop. const el = document.elementFromPoint(e.clientX, e.clientY); const sqEl = el?.closest('[data-square]') as HTMLElement | null; const target = sqEl?.dataset.square as Square | undefined; @@ -907,6 +921,7 @@ function makeDrag() { } function start(src: DragSource, e: PointerEvent) { + detach(); // idempotency — drop any listeners from an unfinished prior drag suppressClickOn = null; state.active = src; state.x = startX = e.clientX; @@ -914,6 +929,7 @@ function makeDrag() { state.moved = false; window.addEventListener('pointermove', onMove); window.addEventListener('pointerup', onUp); + window.addEventListener('pointercancel', onCancel); } /** The board calls this first in its square-click handler. */ @@ -1095,11 +1111,11 @@ Create `packages/client/src/lib/PhantomPalette.svelte`: Drag onto your board — your guess of where the opponent is.