🐛 Accept fractional gap and padding in plugin API layout setters

The flex and grid layout proxies validated `rowGap`, `columnGap` and the
four padding setters with `sm/valid-safe-int?`, so a fractional value
(e.g. `flex.rowGap = 10.5`) was rejected as invalid. The data model types
`:row-gap`/`:column-gap` and `:p1`-`:p4` as `::sm/safe-number`
(layout.cljc), and the sidebar accepts decimals, so the plugin API was
stricter than the model — the same class of defect as the merged #9780.

Switch those 16 gap/padding guards (8 in flex.cljs, 8 in grid.cljs) to
`sm/valid-safe-number?`, matching the model and the predicate already used
by the flex-element setters in the same file. Integer-only setters
(`zIndex`, grid track indices/counts and cell positions/spans) keep
`valid-safe-int?`. Also fixes a `:righPadding` typo in two grid
rightPadding error branches.

Adds a regression test asserting fractional gap/padding values are
accepted (with throwValidationErrors enabled) for both flex and grid.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
This commit is contained in:
Filip Sajdak 2026-06-22 23:46:13 +02:00 committed by Alonso Torres
parent 355f7acb66
commit c7ee54e849
3 changed files with 47 additions and 18 deletions

View File

@ -151,7 +151,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :rowGap value)
(not (r/check-permission plugin-id "content:write"))
@ -169,7 +169,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :columnGap value)
(not (r/check-permission plugin-id "content:write"))
@ -187,7 +187,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :verticalPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -205,7 +205,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :horizontalPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -223,7 +223,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :topPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -241,7 +241,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :rightPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -259,7 +259,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :bottomPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -277,7 +277,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :leftPadding value)
(not (r/check-permission plugin-id "content:write"))

View File

@ -141,7 +141,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :rowGap value)
(not (r/check-permission plugin-id "content:write"))
@ -159,7 +159,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :columnGap value)
(not (r/check-permission plugin-id "content:write"))
@ -177,7 +177,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :verticalPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -195,7 +195,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :horizontalPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -213,7 +213,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :topPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -231,14 +231,14 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :rightPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/not-valid plugin-id :righPadding "Plugin doesn't have 'content:write' permission")
(u/not-valid plugin-id :rightPadding "Plugin doesn't have 'content:write' permission")
(not (u/page-active? page-id))
(u/not-valid plugin-id :righPadding "Cannot modify a page that is not currently active")
(u/not-valid plugin-id :rightPadding "Cannot modify a page that is not currently active")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}}))))}
@ -249,7 +249,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :bottomPadding value)
(not (r/check-permission plugin-id "content:write"))
@ -267,7 +267,7 @@
:set
(fn [_ value]
(cond
(not (sm/valid-safe-int? value))
(not (sm/valid-safe-number? value))
(u/not-valid plugin-id :leftPadding value)
(not (r/check-permission plugin-id "content:write"))

View File

@ -269,3 +269,32 @@
(doseq [[label thunk] (setter-specs m)]
(t/is (not (throws? thunk)) (str label " must be allowed on the active page")))))))
(t/deftest test-layout-gap-padding-accepts-fractional-values
;; Regression: the flex/grid gap and padding setters validated with
;; `valid-safe-int?`, but the layout model types `:row-gap`/`:column-gap` and
;; `:p1`-`:p4` as `safe-number` (and the sidebar accepts decimals), so a
;; fractional value was wrongly rejected. With `throwValidationErrors` on (set
;; by `setup`) and page2 active, a fractional value must be accepted (no throw).
(thw/with-wasm-mocks*
(fn []
(let [{:keys [store page2-id ^js flex ^js grid]} (setup)]
(activate-page! store page2-id)
(doseq [[label thunk]
[["flex.rowGap" #(set! (.-rowGap flex) 10.5)]
["flex.columnGap" #(set! (.-columnGap flex) 3.25)]
["flex.verticalPadding" #(set! (.-verticalPadding flex) 4.5)]
["flex.horizontalPadding" #(set! (.-horizontalPadding flex) 4.5)]
["flex.topPadding" #(set! (.-topPadding flex) 1.5)]
["flex.rightPadding" #(set! (.-rightPadding flex) 1.5)]
["flex.bottomPadding" #(set! (.-bottomPadding flex) 1.5)]
["flex.leftPadding" #(set! (.-leftPadding flex) 1.5)]
["grid.rowGap" #(set! (.-rowGap grid) 7.5)]
["grid.columnGap" #(set! (.-columnGap grid) 2.25)]
["grid.verticalPadding" #(set! (.-verticalPadding grid) 4.5)]
["grid.horizontalPadding" #(set! (.-horizontalPadding grid) 4.5)]
["grid.topPadding" #(set! (.-topPadding grid) 1.5)]
["grid.rightPadding" #(set! (.-rightPadding grid) 1.5)]
["grid.bottomPadding" #(set! (.-bottomPadding grid) 1.5)]
["grid.leftPadding" #(set! (.-leftPadding grid) 1.5)]]]
(t/is (not (throws? thunk)) (str label " must accept a fractional value")))))))