🐛 Fix gap handle drag leaving a stuck preview in wasm

I found this when exploring performance around resizing of flex layouts, but
it's all still quite new to me so please let me know if I'm missing something!

There's this issue with the wasm renderer where if you resize the horizontal
gap amount via the handle and the number of rows ends up changing, then the
wasm renderer can stop updating.

It turns out each of the "gap-displays" are assigned an enumerated index as
their key, e.g.

```
<g.gaps>
  <gap-display key=F0  gap-type=row-gap>     block 0
  …
  <gap-display key=F6  gap-type=row-gap>     block 6
  <gap-display key=F7  gap-type=column-gap>  child 1   ← you press this one
  <gap-display key=F8  gap-type=column-gap>  child 2
  …
  <gap-display key=F105 gap-type=column-gap> child 99
</g.gaps>
```

But if a new row is added then it can end up taking the key of the column you
were resizing:

```
  …
  <gap-display key=F6  gap-type=row-gap>     block 6
  <gap-display key=F7  gap-type=row-gap>     block 7   ← NEW block took key F7
  <gap-display key=F8  gap-type=column-gap>  child 1   ← moved to F8
  <gap-display key=F9  gap-type=column-gap>  child 2
```

When this happens that element changes from a column -> row, so the
`lost-pointer-capture` handler gets confused and the wasm renderer gets out of
sync with whats reflected in the file.

This fixes it by using the shape's UUID as the key for children, and a separate
"block-IDX" key for the blocks, so the two types don't get mixed up.

AI-assisted-by: claude-sonnet-5-5
This commit is contained in:
Luke Lau committed 2026-11-03 19:21:53 +08:00
1 parent 8951c57ee6
commit 419513011c
1 file changed
+14 -10
+14 -10
View File
@@ -243,7 +243,8 @@
(+ (:x2 (:selrect shape)) (get-in shape [:layout-item-margin :m2])))
y (:y1 block)
h (- (:y2 block) (:y1 block))]
{:x x
{:key (str frame-id "-" (:id shape))
:x x
:y y
:height h
:width (:column-gap gap)
@@ -254,7 +255,7 @@
:gap-type (if is-col? :row-gap :column-gap)}))
create-cgdd-block
(fn [block]
(fn [index block]
(let [x (if flip-x
(- (:x1 block) (:column-gap gap))
(:x2 block))
@@ -262,7 +263,8 @@
(+ y1 (:p3 padding))
(+ y1 (:p1 padding)))
h (- height (+ (:p1 padding) (:p3 padding)))]
{:x x
{:key (str frame-id "-block-" index)
:x x
:y y
:width (:column-gap gap)
:height h
@@ -282,7 +284,8 @@
(:row-gap gap))
(+ (:y2 (:selrect shape)) (get-in shape [:layout-item-margin :m3])))
w (- (:x2 block) (:x1 block))]
{:x x
{:key (str frame-id "-" (:id shape))
:x x
:y y
:width w
:height (:row-gap gap)
@@ -293,7 +296,7 @@
:gap-type (if is-col? :row-gap :column-gap)}))
create-rgdd-block
(fn [block]
(fn [index block]
(let [x (if flip-x
(+ x1 (:p2 padding))
(+ x1 (:p4 padding)))
@@ -301,7 +304,8 @@
(- (:y1 block) (:row-gap gap))
(:y2 block))
w (- width (+ (:p2 padding) (:p4 padding)))]
{:x x
{:key (str frame-id "-block-" index)
:x x
:y y
:width w
:height (:row-gap gap)
@@ -313,9 +317,9 @@
display-blocks (if is-col?
(->> (drop-last wrap-blocks)
(map create-cgdd-block))
(map-indexed create-cgdd-block))
(->> (drop-last wrap-blocks)
(map create-rgdd-block)))
(map-indexed create-rgdd-block)))
display-children (if is-col?
(->> children-to-display
@@ -324,10 +328,10 @@
(map create-cgdd)))]
[:g.gaps {:pointer-events "visible"}
(for [[index display-item] (d/enumerate (concat display-blocks display-children))]
(for [display-item (concat display-blocks display-children)]
(let [gap-type (:gap-type display-item)]
[:> gap-display*
{:key (str frame-id index)
{:key (:key display-item)
:frame-id frame-id
:zoom zoom
:gap-type gap-type