import type { FederatedPointerEvent } from 'pixi.js'; /** Longest gap between two presses that still reads as one double-click. */ const DOUBLE_MS = 400; /** How far the pointer may travel between them. */ const SLOP = 6; interface LastPress { key: unknown; button: number; time: number; x: number; y: number; count: number; } let last: LastPress = { key: null, button: -1, time: 0, x: 0, y: 0, count: 0 }; /** * How often `key` was pressed in a row with the same button – 2 on a double-click. Pixi counts * clicks only for the `click`/`pointertap` it synthesises and leaves `detail` at 0 on * `pointerdown`, so a press handler reading `e.detail` never sees a second click. * * `key` identifies what was hit and should survive a rebuild of the widget it belongs to: list * rows are thrown away and recreated whenever the list refreshes, which a selection – the first * click – can trigger. */ export function pressCount(e: FederatedPointerEvent, key: unknown): number { const gap = e.timeStamp - last.time; const repeat = key === last.key && e.button === last.button && gap >= 0 && gap <= DOUBLE_MS && Math.hypot(e.global.x - last.x, e.global.y - last.y) <= SLOP; const count = repeat ? last.count + 1 : 1; last = { key, button: e.button, time: e.timeStamp, x: e.global.x, y: e.global.y, // A finished double-click ends the run: folding a row open and shut again is two // double-clicks, and the second must count as one rather than as clicks three and four. count: count === 2 ? 0 : count, }; return count; }