🐛 Fix hover bugs in wasm guides

This commit is contained in:
Belén Albeza 2026-06-19 11:47:33 +02:00
parent 2a5c29421f
commit 2fbff5816c

View File

@ -752,6 +752,12 @@
(drops the edit without committing)." (drops the edit without committing)."
[{:keys [wasm-guides zoom wasm-guides? disabled-guides? on-guide-change [{:keys [wasm-guides zoom wasm-guides? disabled-guides? on-guide-change
on-guide-drag on-guide-hover get-hover-frame focus]}] on-guide-drag on-guide-hover get-hover-frame focus]}]
;; NOTE: Some of the refs below are live mirrors of state, needed for DOM
;; listeners registered via `mf/with-effect`. Reading the state might return
;; a stale value or an invalid one (triggered right after a re-render)
;; Reading the ref instead gives the current, real value, so hover detection
;; and other pointer events ompares against the real guide data.
(let [dragging-ref (mf/use-ref false) (let [dragging-ref (mf/use-ref false)
moved-ref (mf/use-ref false) moved-ref (mf/use-ref false)
editing-ref (mf/use-ref false) editing-ref (mf/use-ref false)
@ -762,6 +768,7 @@
hover-axis-ref (mf/use-ref nil) hover-axis-ref (mf/use-ref nil)
hover-guide-id-ref (mf/use-ref nil) hover-guide-id-ref (mf/use-ref nil)
state (mf/use-state nil) state (mf/use-state nil)
state-ref (mf/use-ref nil)
snap-pixel? snap-pixel?
(mf/deref refs/snap-pixel?) (mf/deref refs/snap-pixel?)
@ -769,6 +776,13 @@
read-only? read-only?
(mf/use-ctx ctx/workspace-read-only?) (mf/use-ctx ctx/workspace-read-only?)
;; Always mutate the overlay state through this so `state-ref` stays in
;; sync with the `use-state` value the renderer derefs.
set-state
(fn [value]
(mf/set-ref-val! state-ref value)
(reset! state value))
;; The handlers are defined here so they close directly over the refs and ;; The handlers are defined here so they close directly over the refs and
;; the current render's props (guides, zoom, ...). The pointerdown / ;; the current render's props (guides, zoom, ...). The pointerdown /
;; dblclick listeners are re-registered by the effect below whenever those ;; dblclick listeners are re-registered by the effect below whenever those
@ -819,7 +833,7 @@
(on-guide-drag nil)) (on-guide-drag nil))
(emit-hover-axis nil) (emit-hover-axis nil)
(emit-hover-guide-id nil) (emit-hover-guide-id nil)
(reset! state nil)) (set-state nil))
finish-drag finish-drag
(fn [event] (fn [event]
@ -873,7 +887,7 @@
(when (some? on-guide-drag) (when (some? on-guide-drag)
(on-guide-drag (:id guide)))) (on-guide-drag (:id guide))))
(mf/set-ref-val! pending-ref pending) (mf/set-ref-val! pending-ref pending)
(reset! state pending))))))) (set-state pending)))))))
editing? editing?
(fn [] (mf/ref-val editing-ref)) (fn [] (mf/ref-val editing-ref))
@ -905,7 +919,7 @@
(not (editing?)) (not (editing?))
(not (mf/ref-val dragging-ref))) (not (mf/ref-val dragging-ref)))
(let [guide (visible-guide-at-event event) (let [guide (visible-guide-at-event event)
current-state @state current-state (mf/ref-val state-ref)
current-hover-id (when (= :hover (:mode current-state)) current-hover-id (when (= :hover (:mode current-state))
(-> current-state :guide :id))] (-> current-state :guide :id))]
(emit-hover-axis (:axis guide)) (emit-hover-axis (:axis guide))
@ -914,20 +928,20 @@
(and (some? guide) (and (some? guide)
(not= (:id guide) current-hover-id)) (not= (:id guide) current-hover-id))
(let [frame (some-> (:frame-id guide) refs/object-by-id deref)] (let [frame (some-> (:frame-id guide) refs/object-by-id deref)]
(reset! state {:guide guide (set-state {:guide guide
:new-position (:position guide) :new-position (:position guide)
:frame-offset (guide-frame-offset guide) :frame-offset (guide-frame-offset guide)
;; Only root, non-rotated frames get the ;; Only root, non-rotated frames get the
;; segmented line (matching the SVG renderer), ;; segmented line (matching the SVG renderer),
;; so we only overlay dotted extensions there. ;; so we only overlay dotted extensions there.
:frame (when (and frame :frame (when (and frame
(cfh/root-frame? frame) (cfh/root-frame? frame)
(not (ctst/rotated-frame? frame))) (not (ctst/rotated-frame? frame)))
frame) frame)
:mode :hover})) :mode :hover}))
(and (nil? guide) (some? current-hover-id)) (and (nil? guide) (some? current-hover-id))
(reset! state nil))))) (set-state nil)))))
pointer-down pointer-down
(fn [event] (fn [event]
@ -983,16 +997,16 @@
offset (if frame offset (if frame
(if (= :x axis) (:x frame) (:y frame)) (if (= :x axis) (:x frame) (:y frame))
0)] 0)]
(reset! state {:guide guide (set-state {:guide guide
:new-position position :new-position position
:new-frame-id frame-id :new-frame-id frame-id
:frame-offset offset :frame-offset offset
:mode :edit})))))) :mode :edit}))))))
commit-edit commit-edit
(fn [raw-value] (fn [raw-value]
(when (editing?) (when (editing?)
(let [{:keys [guide new-frame-id frame-offset]} @state (let [{:keys [guide new-frame-id frame-offset]} (mf/ref-val state-ref)
parsed (some-> raw-value str/trim d/parse-double)] parsed (some-> raw-value str/trim d/parse-double)]
(when (and (some? parsed) (some? on-guide-change)) (when (and (some? parsed) (some? on-guide-change))
(on-guide-change (assoc guide (on-guide-change (assoc guide