🐛 Fix non-integer row/column values in grid cell position inputs (#8869)

* 🐛 Fix non-integer row/column values in grid cell position inputs

The numeric-input component allows Alt+arrow key increments of 0.1x the
step value, which could produce float values (e.g. 4.5, 0.5) when users
adjusted grid cell row/column/row-span/column-span positions. The schema
requires these fields to be integers, causing backend validation errors.

Round the input values to integers in the on-grid-coordinates callback
before passing them to update-grid-cell-position.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

* 🐛 Enforce integer-only values in grid cell numeric inputs

Add an `integer` prop to the legacy `numeric-input*` component that
rounds parsed values in `parse-value`, ensuring all input paths (typed
text, arrow keys, Alt+arrow, mouse wheel, expressions) produce integers.
Use it for all six row/column inputs in the grid cell options panel.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

---------

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
Andrey Antukh 2026-04-08 17:05:55 +02:00 committed by GitHub
parent c8675c5b7e
commit cb33fe417e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 3 deletions

View File

@ -7,6 +7,7 @@
(ns app.main.ui.components.numeric-input
(:require
[app.common.data :as d]
[app.common.math :as mth]
[app.common.schema :as sm]
[app.main.ui.formats :as fmt]
[app.main.ui.hooks :as h]
@ -43,6 +44,7 @@
step-value (d/parse-double step-value 1)
default (d/parse-double default (when-not nillable? 0))
integer? (unchecked-get props "integer")
select-on-focus? (d/nilv (unchecked-get props "selectOnFocus") true)
;; We need a ref pointing to the input dom element, but the user
@ -63,7 +65,7 @@
parse-value
(mf/use-fn
(mf/deps min-value max-value value nillable? default)
(mf/deps min-value max-value value nillable? default integer?)
(fn []
(when-let [node (mf/ref-val ref)]
(let [new-value (-> (dom/get-value node)
@ -72,6 +74,7 @@
(cond
(d/num? new-value)
(-> new-value
(cond-> integer? mth/round)
(d/max (/ sm/min-safe-int 2))
(d/min (/ sm/max-safe-int 2))
(cond-> (d/num? min-value)
@ -146,7 +149,8 @@
(and (d/num? max-value) (> new-value max-value))
max-value
:else new-value)]
:else new-value)
new-value (if integer? (mth/round new-value) new-value)]
(apply-value event new-value))))))
@ -227,6 +231,7 @@
props (-> (obj/clone props)
(obj/unset! "selectOnFocus")
(obj/unset! "nillable")
(obj/unset! "integer")
(obj/set! "value" mf/undefined)
(obj/set! "onChange" handle-change)
(obj/set! "className" class)

View File

@ -10,6 +10,7 @@
[app.common.attrs :as attrs]
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.math :as mth]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace :as dw]
[app.main.data.workspace.grid-layout.editor :as dwge]
@ -133,7 +134,10 @@
(mf/deps column row (:id shape) (:id cell))
(fn [field type value]
(when-not multiple?
(let [[property value]
(let [value (mth/round value)
column (mth/round column)
row (mth/round row)
[property value]
(cond
(and (= type :column) (or (= field :all) (= field :start)))
[:column value]
@ -216,6 +220,7 @@
:title "Column"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :column)
:integer true
:value column}]]]
[:div {:class (stl/css :grid-coord-group)}
@ -226,6 +231,7 @@
:title "Row"
:on-click #(dom/select-target %)
:on-change (partial on-grid-coordinates :all :row)
:integer true
:value row}]]]])
(when (and (not multiple?) (or (= :manual cell-mode) (= :area cell-mode)))
@ -237,12 +243,14 @@
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :column)
:integer true
:value column}]]
[:div {:class (stl/css :coord-input)}
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :column)
:integer true
:value column-end}]]]
[:div {:class (stl/css :grid-coord-group)}
@ -252,12 +260,14 @@
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :start :row)
:integer true
:value row}]]
[:div {:class (stl/css :coord-input)}
[:> numeric-input*
{:placeholder "--"
:on-pointer-down #(dom/select-target %)
:on-change (partial on-grid-coordinates :end :row)
:integer true
:value row-end}]]]])
[:div {:class (stl/css :row)}