mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 22:09:37 +00:00
## Summary Extract duplicated click-vs-drag detection logic into a shared `useClickDragGuard` composable and `exceedsClickThreshold` pure utility function. ## Changes - **What**: New `useClickDragGuard(threshold)` composable in `src/composables/useClickDragGuard.ts` that stores pointer start position and checks squared distance against a threshold. Also exports `exceedsClickThreshold` for non-Vue contexts. - Migrated `DropZone.vue`, `useNodePointerInteractions.ts`, and `Load3d.ts` to use the shared utility - `CanvasPointer.ts` left as-is (LiteGraph internal) - All consumers now use squared-distance comparison (no `Math.sqrt` or per-axis `Math.abs`) ## Review Focus - The composable uses plain `let` state instead of `ref` since reactivity is not needed for the start position - `Load3d.ts` uses the pure `exceedsClickThreshold` function directly since it is a class, not a Vue component - Threshold values preserved per-consumer: DropZone=5, useNodePointerInteractions=3, Load3d=5 Fixes #10356 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10357-refactor-extract-shared-click-vs-drag-guard-utility-32a6d73d3650816e83f5cb89872fb184) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Alexander Brown <drjkl@comfy.org>
66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
exceedsClickThreshold,
|
|
useClickDragGuard
|
|
} from '@/composables/useClickDragGuard'
|
|
|
|
describe('exceedsClickThreshold', () => {
|
|
it('returns false when distance is within threshold', () => {
|
|
expect(exceedsClickThreshold({ x: 0, y: 0 }, { x: 2, y: 2 }, 5)).toBe(false)
|
|
})
|
|
|
|
it('returns true when distance exceeds threshold', () => {
|
|
expect(exceedsClickThreshold({ x: 0, y: 0 }, { x: 3, y: 5 }, 5)).toBe(true)
|
|
})
|
|
|
|
it('returns false when distance exactly equals threshold', () => {
|
|
expect(exceedsClickThreshold({ x: 0, y: 0 }, { x: 3, y: 4 }, 5)).toBe(false)
|
|
})
|
|
|
|
it('handles negative deltas', () => {
|
|
expect(exceedsClickThreshold({ x: 10, y: 10 }, { x: 4, y: 2 }, 5)).toBe(
|
|
true
|
|
)
|
|
})
|
|
})
|
|
|
|
describe('useClickDragGuard', () => {
|
|
it('reports no drag when pointer has not moved', () => {
|
|
const guard = useClickDragGuard(5)
|
|
guard.recordStart({ clientX: 100, clientY: 200 })
|
|
expect(guard.wasDragged({ clientX: 100, clientY: 200 })).toBe(false)
|
|
})
|
|
|
|
it('reports no drag when movement is within threshold', () => {
|
|
const guard = useClickDragGuard(5)
|
|
guard.recordStart({ clientX: 100, clientY: 200 })
|
|
expect(guard.wasDragged({ clientX: 103, clientY: 204 })).toBe(false)
|
|
})
|
|
|
|
it('reports drag when movement exceeds threshold', () => {
|
|
const guard = useClickDragGuard(5)
|
|
guard.recordStart({ clientX: 100, clientY: 200 })
|
|
expect(guard.wasDragged({ clientX: 106, clientY: 200 })).toBe(true)
|
|
})
|
|
|
|
it('returns false when no start has been recorded', () => {
|
|
const guard = useClickDragGuard(5)
|
|
expect(guard.wasDragged({ clientX: 100, clientY: 200 })).toBe(false)
|
|
})
|
|
|
|
it('returns false after reset', () => {
|
|
const guard = useClickDragGuard(5)
|
|
guard.recordStart({ clientX: 100, clientY: 200 })
|
|
guard.reset()
|
|
expect(guard.wasDragged({ clientX: 200, clientY: 300 })).toBe(false)
|
|
})
|
|
|
|
it('respects custom threshold', () => {
|
|
const guard = useClickDragGuard(3)
|
|
guard.recordStart({ clientX: 0, clientY: 0 })
|
|
expect(guard.wasDragged({ clientX: 3, clientY: 0 })).toBe(false)
|
|
expect(guard.wasDragged({ clientX: 4, clientY: 0 })).toBe(true)
|
|
})
|
|
})
|