mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 22:10:34 +00:00
🐛 Handle empty flex layouts when calculating line positions
Skip per-line stretch division and baseline placement when a flex layout has no lines. Removing a component's final child then resizing a copy could divide by zero on the JVM (F169). The public layout regression fails four assertions before the fix. It covers row and column layouts with six content alignments. Fresh flex, swap and variant suites pass 125 tests and 596 assertions, and the shrunk structure program passes. Pure goldens match all 1149 assertions. AI-assisted-by: GPT-6
This commit is contained in:
parent
5ad0744d0e
commit
3e36275f96
@ -5,6 +5,13 @@
|
||||
- Layout container data and child layout-item data are removed by different helpers. Do not assume clearing a layout frame also clears all child layout metadata.
|
||||
- Layout data can affect both container attrs and immediate child attrs; validate behavior for both sides when changing cleanup or propagation.
|
||||
|
||||
## Empty flex layouts
|
||||
|
||||
- No children means no layout lines. Skip stretch-per-line division and
|
||||
baseline placement when the line count is zero. Both row and column
|
||||
layouts can become empty after component sync; resizing them must still
|
||||
return valid layout data (F169).
|
||||
|
||||
## Grid assignment
|
||||
|
||||
- Grid `assign-cells` ensures at least one column and row, skips absolute-position children, creates non-tracked rows/cols when children exceed tracked cells, and asserts that assigned cells do not overlap.
|
||||
@ -13,4 +20,4 @@
|
||||
- The `:reorder-children` change it emits is refused on parents inside component copies unless `allow-altering-copies` (same rule as `:mov-objects`); `pcb/reorder-grid-children` also skips copy grids producer-side. Copy child order is owned by the component sync engine.
|
||||
- Grid deassignment removes cells for shapes that are no longer direct children or have become absolute-positioned.
|
||||
- Auto-positioning is not just sorting: some auto cells are converted to manual when empty/manual/span state would break the auto sequence, then auto single-span items can be compacted.
|
||||
- `fix-overlaps` is marked dev-only and removes one overlapping cell, preferring empty cells first. Avoid depending on it as normal production repair.
|
||||
- `fix-overlaps` is marked dev-only and removes one overlapping cell, preferring empty cells first. Avoid depending on it as normal production repair.
|
||||
|
||||
@ -224,12 +224,12 @@
|
||||
|
||||
;; When align-items is stretch we need to adjust the main axis size to grow for the full content
|
||||
stretch-width-fix
|
||||
(if (and col? (ctl/content-stretch? parent) (not auto-width?))
|
||||
(if (and (pos? num-lines) col? (ctl/content-stretch? parent) (not auto-width?))
|
||||
(/ (- layout-width (* layout-gap-col (dec num-lines)) total-max-width) num-lines)
|
||||
0)
|
||||
|
||||
stretch-height-fix
|
||||
(if (and row? (ctl/content-stretch? parent) (not auto-height?))
|
||||
(if (and (pos? num-lines) row? (ctl/content-stretch? parent) (not auto-height?))
|
||||
(/ (- layout-height (* layout-gap-row (dec num-lines)) total-max-height) num-lines)
|
||||
0)
|
||||
|
||||
@ -300,7 +300,8 @@
|
||||
|
||||
[total-width total-height] (->> layout-lines (reduce add-lines [0 0]))
|
||||
|
||||
base-p (flp/get-base-line parent layout-bounds total-width total-height num-lines)]
|
||||
base-p (when (pos? num-lines)
|
||||
(flp/get-base-line parent layout-bounds total-width total-height num-lines))]
|
||||
|
||||
(->> layout-lines
|
||||
(reduce (partial add-starts total-width total-height num-lines) [(transient []) base-p])
|
||||
|
||||
@ -34,6 +34,16 @@
|
||||
[rect]
|
||||
(grc/rect->points rect))
|
||||
|
||||
(t/deftest empty-wrapped-layout-has-no-lines
|
||||
(doseq [direction [:row :column]
|
||||
alignment [:stretch :space-around :space-evenly :space-between :center :end]]
|
||||
(let [frame (make-col-frame :layout-flex-dir direction
|
||||
:layout-align-content alignment
|
||||
:layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}
|
||||
:layout-padding-type :simple)
|
||||
bounds (rect->bounds (grc/make-rect 0 0 200 200))]
|
||||
(t/is (= [] (:layout-lines (fld/calc-layout-data frame bounds [] {} {})))))))
|
||||
|
||||
;; ---- get-base-line (around? branch) ----
|
||||
;;
|
||||
;; Bug: in positions.cljc the col? + around? branch had a mis-parenthesised
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user