Fix stuck gestures and scene graph races; honour commitVelocity
Gestures - Cancel a captured gesture on lostpointercapture, on a new primary pointer-down, and when its component unmounts, so operations are never left stuck mid-transition. Bindings gain onLostpointercapture. - Warn (console.warn) when navigate() fails or the scene rejects an operation; stay quiet when two recognizers race for one origin. - OriginGesture and OriginGestureSurface props are reactive. Changes apply from the next pointer-down; recognizers are kept per list position so re-renders never interrupt a drag. - Remove the legacy direction/edge/threshold/action gesture form (OriginGestureOptions, legacy OriginGesture props, MaybeOriginAction). Scene - Honour choreography commitVelocity (default 0.3, as before). - Scene errors are OriginSceneError with a stable code. - update() during settling now really catches an operation: the spring stops, and only the latest finish() decides the outcome. - Fix graph corruption found by the new property tests, all present on main: replacements escaping a cancelled push, edges left dangling when their current target differs from the original one, revealed targets keeping operations after their back is cancelled, history pointing at removed entries after replace, visual cycles from back through an undecided replace, exposed nodes reactivated as active, and a cancel cascade that could empty the whole scene. Tests - Add property tests checking structural invariants after every step of random operation sequences and pointer streams (PROPERTY_SEEDS). - Add recognizer tests for stuck gestures, warnings, reactive props, and commitVelocity. Drop the main-comparison suites; keep benchmarks. Also fix the origins demo's two pre-existing type errors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Faarh2Ts6StJPcz2mRiHiR
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useOriginGesture } from "../gesture/recognizer";
|
||||
import type { OriginGestureProps } from "../gesture/definition";
|
||||
import { useOriginGesture } from "../gesture/recognizer";
|
||||
|
||||
defineOptions({ name: "OriginGesture", inheritAttrs: false });
|
||||
|
||||
@@ -11,17 +11,10 @@ const props = withDefaults(defineProps<OriginGestureProps>(), {
|
||||
/*
|
||||
* This convenience component makes the declaration live exactly where the
|
||||
* developer writes it. `useOriginGesture()` is also public for components that
|
||||
* cannot accept an extra wrapper element. Props are read once, at setup; the
|
||||
* legacy `action` prop is read lazily so it may change.
|
||||
* cannot accept an extra wrapper element. A new `gesture` prop applies from
|
||||
* the next pointer-down.
|
||||
*/
|
||||
const gesture = useOriginGesture(
|
||||
props.gesture ?? {
|
||||
direction: props.direction,
|
||||
edge: props.edge,
|
||||
threshold: props.threshold,
|
||||
action: (context) => props.action?.(context),
|
||||
},
|
||||
);
|
||||
const gesture = useOriginGesture(() => props.gesture);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -34,6 +27,7 @@ const gesture = useOriginGesture(
|
||||
@pointermove="gesture.onPointermove"
|
||||
@pointerup="gesture.onPointerup"
|
||||
@pointercancel="gesture.onPointercancel"
|
||||
@lostpointercapture="gesture.onLostpointercapture"
|
||||
>
|
||||
<slot />
|
||||
</component>
|
||||
|
||||
Reference in New Issue
Block a user