🐛 Fixes issues with empty input in options

This commit is contained in:
alonso.torres 2020-12-22 18:05:37 +01:00
parent 84007e6ad1
commit e1923468a4
10 changed files with 181 additions and 130 deletions

View file

@ -13,36 +13,110 @@
[app.main.ui.keyboard :as kbd] [app.main.ui.keyboard :as kbd]
[app.common.data :as d] [app.common.data :as d]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.object :as obj])) [app.util.object :as obj]
[app.common.math :as math]))
(mf/defc numeric-input (mf/defc numeric-input
{::mf/wrap-props false {::mf/wrap-props false
::mf/forward-ref true} ::mf/forward-ref true}
[props ref] [props ref]
(let [on-key-down (let [value (obj/get props "value")
on-change (obj/get props "onChange")
min-val (obj/get props "min")
max-val (obj/get props "max")
wrap-value? (obj/get props "data-wrap")
stored-val (mf/use-var value)
local-ref (mf/use-ref nil)
ref (or ref local-ref)
min-val (cond-> min-val
(string? min-val) (d/parse-integer nil))
max-val (cond-> max-val
(string? max-val) (d/parse-integer nil))
num? (fn [value] (and (number? value)
(not (math/nan? value))
(math/finite? value)))
parse-value (fn [event]
(let [value (-> (dom/get-target-val event) (d/parse-integer nil))]
(when (num? value)
(cond-> value
(num? min-val) (cljs.core/max min-val)
(num? max-val) (cljs.core/min max-val)))))
handle-change
(mf/use-callback (mf/use-callback
(fn [event] (mf/deps on-change)
(when (and (or (kbd/up-arrow? event) (kbd/down-arrow? event)) (fn [event]
(kbd/shift? event)) (let [value (parse-value event)]
(let [increment (if (kbd/up-arrow? event) 9 -9) ; this is added to the (when (and on-change (num? value))
target (dom/get-target event) ; default 1 or -1 step (on-change value)))))
min-value (-> (dom/get-attribute target "min")
(d/parse-integer ##-Inf))
max-value (-> (dom/get-attribute target "max")
(d/parse-integer ##Inf))
new-value (-> target
(dom/get-value)
(d/parse-integer 0)
(+ increment)
(cljs.core/min max-value)
(cljs.core/max min-value))]
(dom/set-value! target new-value)))))
props (-> props set-delta
(obj/set! "className" "input-text") (mf/use-callback
(obj/set! "type" "number") (mf/deps on-change wrap-value? min-val max-val)
(obj/set! "ref" ref) (fn [event up? down?]
(obj/set! "onKeyDown" on-key-down))] (let [value (parse-value event)
increment (if up? 9 -9)]
(when (and (or up? down?) (num? value))
(cond
(kbd/shift? event)
(let [new-value (+ value increment)
new-value (cond
(and wrap-value? (num? max-val) (num? min-val) (> new-value max-val) up?)
(+ min-val (- max-val new-value))
(and wrap-value? (num? min-val) (num? max-val) (< new-value min-val) down?)
(- max-val (- new-value min-val))
(and (num? min-val) (< new-value min-val)) min-val
(and (num? max-val) (> new-value max-val)) max-val
:else new-value)]
(dom/set-value! (dom/get-target event) new-value))
(and wrap-value? (num? max-val) (num? min-val) (= value max-val) up?)
(dom/set-value! (dom/get-target event) min-val)
(and wrap-value? (num? min-val) (num? max-val) (= value min-val) down?)
(dom/set-value! (dom/get-target event) max-val))))))
handle-key-down
(mf/use-callback
(mf/deps set-delta)
(fn [event]
(set-delta event (kbd/up-arrow? event) (kbd/down-arrow? event))))
handle-mouse-wheel
(mf/use-callback
(mf/deps set-delta)
(fn [event]
(set-delta event (< (.-deltaY event) 0) (> (.-deltaY event) 0))))
handle-blur
(fn [event]
(when-let [input-node (and ref (mf/ref-val ref))]
(dom/set-value! input-node @stored-val)))
props (-> props
(obj/without ["value" "onChange"])
(obj/set! "className" "input-text")
(obj/set! "type" "number")
(obj/set! "ref" ref)
(obj/set! "defaultValue" value)
(obj/set! "onWheel" handle-mouse-wheel)
(obj/set! "onKeyDown" handle-key-down)
(obj/set! "onChange" handle-change)
(obj/set! "onBlur" handle-blur))]
(mf/use-effect
(mf/deps value)
(fn []
(when-let [input-node (and ref (mf/ref-val ref))]
(if-not (dom/active? input-node)
(dom/set-value! input-node value)
(reset! stored-val value)))))
[:> :input props])) [:> :input props]))

View file

@ -49,24 +49,16 @@
(udw/update-dimensions [(:id shape)] :height new-height)))) (udw/update-dimensions [(:id shape)] :height new-height))))
on-size-change on-size-change
(fn [event attr] (fn [value attr]
(let [value (-> (dom/get-target event) (st/emit! (udw/update-dimensions [(:id shape)] attr value)))
(dom/get-value)
(d/parse-integer 1))]
(st/emit! (udw/update-dimensions [(:id shape)] attr value))))
on-proportion-lock-change on-proportion-lock-change
(fn [event] (fn [event]
(st/emit! (udw/set-shape-proportion-lock (:id shape) (not (:proportion-lock shape))))) (st/emit! (udw/set-shape-proportion-lock (:id shape) (not (:proportion-lock shape)))))
on-position-change on-position-change
(fn [event attr] (fn [value attr]
(let [cval (-> (dom/get-target event) (st/emit! (udw/update-position (:id shape) {attr value})))
(dom/get-value)
(d/parse-integer 0))]
;; TODO: Change so not apply the modifiers until blur
(when cval
(st/emit! (udw/update-position (:id shape) {attr cval})))))
on-width-change #(on-size-change % :width) on-width-change #(on-size-change % :width)
on-height-change #(on-size-change % :height) on-height-change #(on-size-change % :height)
@ -105,7 +97,7 @@
i/lock i/lock
i/unlock)] i/unlock)]
[:div.input-element.pixels [:div.input-element.pixels
[:> numeric-input {:min "1" [:> numeric-input {:min 1
:on-click select-all :on-click select-all
:on-change on-width-change :on-change on-width-change
:value (-> (:width shape) :value (-> (:width shape)
@ -114,7 +106,7 @@
[:div.input-element.pixels [:div.input-element.pixels
[:> numeric-input {:min "1" [:> numeric-input {:min 1
:on-click select-all :on-click select-all
:on-change on-height-change :on-change on-height-change
:value (-> (:height shape) :value (-> (:height shape)

View file

@ -74,12 +74,6 @@
(fn [value] (fn [value]
(emit-changes! #(assoc-in % keys value)))) (emit-changes! #(assoc-in % keys value))))
handle-change-event
(fn [& keys]
(fn [event]
(let [change-fn (apply handle-change keys)]
(-> event dom/get-target dom/get-value parse-integer change-fn))))
handle-change-size handle-change-size
(fn [size] (fn [size]
(let [grid (d/deep-merge grid (:changes @state)) (let [grid (d/deep-merge grid (:changes @state))
@ -136,10 +130,10 @@
(if (= type :square) (if (= type :square)
[:div.input-element.pixels [:div.input-element.pixels
[:> numeric-input {:min "1" [:> numeric-input {:min 1
:no-validate true :no-validate true
:value (:size params) :value (:size params)
:on-change (handle-change-event :params :size)}]] :on-change (handle-change :params :size)}]]
[:& editable-select {:value (:size params) [:& editable-select {:value (:size params)
:type (when (number? (:size params)) "number" ) :type (when (number? (:size params)) "number" )
:class "input-option" :class "input-option"

View file

@ -54,57 +54,54 @@
(not= (:x values) :multiple) (assoc :x x) (not= (:x values) :multiple) (assoc :x x)
(not= (:y values) :multiple) (assoc :y y))) (not= (:y values) :multiple) (assoc :y y)))
values (let [{:keys [width height]} (-> shapes first :selrect)]
(cond-> values
(not= (:width values) :multiple) (assoc :width width)
(not= (:height values) :multiple) (assoc :height height)))
proportion-lock (:proportion-lock values) proportion-lock (:proportion-lock values)
on-size-change on-size-change
(fn [event attr] (mf/use-callback
(let [value (-> (dom/get-target event) (mf/deps ids)
(dom/get-value) (fn [value attr]
(d/parse-integer 1))] (st/emit! (udw/update-dimensions ids attr value))))
(st/emit! (udw/update-dimensions ids attr value))))
on-proportion-lock-change on-proportion-lock-change
(fn [event] (mf/use-callback
(let [new-lock (if (= proportion-lock :multiple) true (not proportion-lock))] (mf/deps ids)
(run! #(st/emit! (udw/set-shape-proportion-lock % new-lock)) ids))) (fn [event]
(let [new-lock (if (= proportion-lock :multiple) true (not proportion-lock))]
(run! #(st/emit! (udw/set-shape-proportion-lock % new-lock)) ids))))
do-position-change do-position-change
(fn [shape' frame' value attr] (mf/use-callback
(let [from (-> shape' :points gsh/points->selrect attr) (mf/deps ids)
to (+ value (attr frame')) (fn [shape' frame' value attr]
target (+ (attr shape') (- to from))] (let [to (+ value (attr frame'))]
(st/emit! (udw/update-position (:id shape') {attr target})))) (st/emit! (udw/update-position (:id shape') { attr to })))))
on-position-change on-position-change
(fn [event attr] (mf/use-callback
(let [value (-> (dom/get-target event) (mf/deps ids)
(dom/get-value) (fn [value attr]
(d/parse-integer 0))] (doall (map #(do-position-change %1 %2 value attr) shapes frames))))
(when value
(doall (map #(do-position-change %1 %2 value attr) shapes frames)))))
do-rotation-change
(fn [shape' old-shape' value]
(st/emit! (udw/set-rotation (- value (:rotation shape')) [old-shape'])
(udw/apply-modifiers #{(:id shape')})))
on-rotation-change on-rotation-change
(fn [event] (mf/use-callback
(let [value (-> (dom/get-target event) (mf/deps ids)
(dom/get-value) (fn [value]
(d/parse-integer 0))] (st/emit! (udw/increase-rotation ids value))))
(doall (map #(do-rotation-change %1 %2 value) shapes old-shapes))))
on-radius-change on-radius-change
(fn [event] (mf/use-callback
(let [value (-> (dom/get-target event) (mf/deps ids)
(dom/get-value) (fn [value]
(d/parse-integer 0))] (let [radius-update
(st/emit! (dwc/update-shapes (fn [shape]
ids-with-children (cond-> shape
#(if (:rx %) (:rx shape) (assoc :rx value :ry value)))]
(assoc % :rx value :ry value) (st/emit! (dwc/update-shapes ids-with-children radius-update)))))
%)))))
on-width-change #(on-size-change % :width) on-width-change #(on-size-change % :width)
on-height-change #(on-size-change % :height) on-height-change #(on-size-change % :height)
@ -120,7 +117,7 @@
[:div.row-flex [:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.size")] [:span.element-set-subtitle (t locale "workspace.options.size")]
[:div.input-element.width [:div.input-element.width
[:> numeric-input {:min "1" [:> numeric-input {:min 1
:no-validate true :no-validate true
:placeholder "--" :placeholder "--"
:on-click select-all :on-click select-all
@ -128,7 +125,7 @@
:value (attr->string :width values)}]] :value (attr->string :width values)}]]
[:div.input-element.height [:div.input-element.height
[:> numeric-input {:min "1" [:> numeric-input {:min 1
:no-validate true :no-validate true
:placeholder "--" :placeholder "--"
:on-click select-all :on-click select-all
@ -167,8 +164,9 @@
[:div.input-element.degrees [:div.input-element.degrees
[:> numeric-input [:> numeric-input
{:no-validate true {:no-validate true
:min "0" :min 0
:max "359" :max 359
:data-wrap true
:placeholder "--" :placeholder "--"
:on-click select-all :on-click select-all
:on-change on-rotation-change :on-change on-rotation-change
@ -189,7 +187,7 @@
[:div.input-element.pixels [:div.input-element.pixels
[:> numeric-input [:> numeric-input
{:placeholder "--" {:placeholder "--"
:min "0" :min 0
:on-click select-all :on-click select-all
:on-change on-radius-change :on-change on-radius-change
:value (attr->string :rx values)}]] :value (attr->string :rx values)}]]

View file

@ -11,6 +11,7 @@
(:require (:require
[rumext.alpha :as mf] [rumext.alpha :as mf]
[app.common.data :as d] [app.common.data :as d]
[app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
[app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
[app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
[app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]]
@ -20,8 +21,12 @@
[{:keys [shape] :as props}] [{:keys [shape] :as props}]
(let [ids [(:id shape)] (let [ids [(:id shape)]
type (:type shape) type (:type shape)
measure-values (select-keys shape measure-attrs)
stroke-values (select-keys shape stroke-attrs)] stroke-values (select-keys shape stroke-attrs)]
[:* [:*
[:& measures-menu {:ids ids
:type type
:values measure-values}]
[:& fill-menu {:ids ids [:& fill-menu {:ids ids
:type type :type type
:values (select-keys shape fill-attrs)}] :values (select-keys shape fill-attrs)}]

View file

@ -55,11 +55,6 @@
(* 100) (* 100)
(math/round))))) (math/round)))))
(defn string->opacity [opacity-str]
(-> opacity-str
(d/parse-integer 1)
(/ 100)))
(defn remove-multiple [v] (defn remove-multiple [v]
(if (= v :multiple) nil v)) (if (= v :multiple) nil v))
@ -103,13 +98,8 @@
append-hash append-hash
change-value)))) change-value))))
handle-opacity-change (fn [event] handle-opacity-change (fn [value]
(let [target (dom/get-target event)] (change-opacity (/ value 100)))
(when (dom/valid? target)
(-> target
dom/get-value
string->opacity
change-opacity))))
select-all (fn [event] select-all (fn [event]
(dom/select-text! (dom/get-target event))) (dom/select-text! (dom/get-target event)))
@ -171,6 +161,6 @@
:placeholder (tr "settings.multiple") :placeholder (tr "settings.multiple")
:on-click select-all :on-click select-all
:on-change handle-opacity-change :on-change handle-opacity-change
:min "0" :min 0
:max "100"}]])])])) :max 100}]])])]))

View file

@ -36,16 +36,9 @@
:placeholder placeholder :placeholder placeholder
:on-change on-change}] :on-change on-change}]
(let [handle-change [:> numeric-input {:placeholder placeholder
(fn [event] :min min
(let [value (-> event dom/get-target dom/get-value d/parse-integer)] :max max
(when (and (not (nil? on-change)) :on-change on-change
(or (not min) (>= value min)) :value (or value "")}])]])
(or (not max) (<= value max)))
(on-change value))))]
[:> numeric-input {:placeholder placeholder
:min (when min (str min))
:max (when max (str max))
:on-change handle-change
:value (or value "")}]))]])

View file

@ -70,13 +70,10 @@
(update-attr index attr valid? nil)) (update-attr index attr valid? nil))
([index attr valid? update-ref] ([index attr valid? update-ref]
(fn [event] (fn [value]
(let [value (dom/get-value (dom/get-target event))] (when (or (not valid?) (valid? value))
(when (or (not valid?) (valid? value)) (do (st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index attr] value)))
(do (when update-ref (dom/set-value! (mf/ref-val update-ref) value)))))))
(when update-ref
(dom/set-value! (mf/ref-val update-ref) value))
(st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index attr] (js/parseInt value 10))))))))))
update-color update-color
(fn [index] (fn [index]
@ -101,16 +98,16 @@
[:> numeric-input {:ref basic-offset-x-ref [:> numeric-input {:ref basic-offset-x-ref
:on-change (update-attr index :offset-x valid-number?) :on-change (update-attr index :offset-x valid-number?)
:on-click (select-text basic-offset-x-ref) :on-click (select-text basic-offset-x-ref)
:default-value (:offset-x value)}] :value (:offset-x value)}]
[:> numeric-input {:ref basic-offset-y-ref [:> numeric-input {:ref basic-offset-y-ref
:on-change (update-attr index :offset-y valid-number?) :on-change (update-attr index :offset-y valid-number?)
:on-click (select-text basic-offset-y-ref) :on-click (select-text basic-offset-y-ref)
:default-value (:offset-y value)}] :value (:offset-y value)}]
[:> numeric-input {:ref basic-blur-ref [:> numeric-input {:ref basic-blur-ref
:on-click (select-text basic-blur-ref) :on-click (select-text basic-blur-ref)
:on-change (update-attr index :blur valid-number?) :on-change (update-attr index :blur valid-number?)
:min 0 :min 0
:default-value (:blur value)}] :value (:blur value)}]
[:div.element-set-actions [:div.element-set-actions
[:div.element-set-actions-button {:on-click (toggle-visibility index)} [:div.element-set-actions-button {:on-click (toggle-visibility index)}
@ -136,7 +133,7 @@
:placeholder "--" :placeholder "--"
:on-click (select-text adv-offset-x-ref) :on-click (select-text adv-offset-x-ref)
:on-change (update-attr index :offset-x valid-number? basic-offset-x-ref) :on-change (update-attr index :offset-x valid-number? basic-offset-x-ref)
:default-value (:offset-x value)}] :value (:offset-x value)}]
[:span.after (t locale "workspace.options.shadow-options.offsetx")]] [:span.after (t locale "workspace.options.shadow-options.offsetx")]]
[:div.input-element [:div.input-element
@ -145,7 +142,7 @@
:placeholder "--" :placeholder "--"
:on-click (select-text adv-offset-y-ref) :on-click (select-text adv-offset-y-ref)
:on-change (update-attr index :offset-y valid-number? basic-offset-y-ref) :on-change (update-attr index :offset-y valid-number? basic-offset-y-ref)
:default-value (:offset-y value)}] :value (:offset-y value)}]
[:span.after (t locale "workspace.options.shadow-options.offsety")]]] [:span.after (t locale "workspace.options.shadow-options.offsety")]]]
[:div.row-grid-2 [:div.row-grid-2
@ -156,7 +153,7 @@
:on-click (select-text adv-blur-ref) :on-click (select-text adv-blur-ref)
:on-change (update-attr index :blur valid-number? basic-blur-ref) :on-change (update-attr index :blur valid-number? basic-blur-ref)
:min 0 :min 0
:default-value (:blur value)}] :value (:blur value)}]
[:span.after (t locale "workspace.options.shadow-options.blur")]] [:span.after (t locale "workspace.options.shadow-options.blur")]]
[:div.input-element [:div.input-element
@ -166,7 +163,7 @@
:on-click (select-text adv-spread-ref) :on-click (select-text adv-spread-ref)
:on-change (update-attr index :spread valid-number?) :on-change (update-attr index :spread valid-number?)
:min 0 :min 0
:default-value (:spread value)}] :value (:spread value)}]
[:span.after (t locale "workspace.options.shadow-options.spread")]]] [:span.after (t locale "workspace.options.shadow-options.spread")]]]
[:div.color-row-wrap [:div.color-row-wrap

View file

@ -134,9 +134,11 @@
(let [objects (unchecked-get props "objects") (let [objects (unchecked-get props "objects")
selected (or (unchecked-get props "selected") #{}) selected (or (unchecked-get props "selected") #{})
hover (or (unchecked-get props "hover") #{}) hover (or (unchecked-get props "hover") #{})
edition (unchecked-get props "edition")
outline? (set/union selected hover) outline? (set/union selected hover)
show-outline? (fn [shape] (and (not (:hidden shape)) show-outline? (fn [shape] (and (not (:hidden shape))
(not (:blocked shape)) (not (:blocked shape))
(not= edition (:id shape))
(outline? (:id shape)))) (outline? (:id shape))))
shapes (->> (vals objects) (filter show-outline?)) shapes (->> (vals objects) (filter show-outline?))
transform (mf/deref refs/current-transform) transform (mf/deref refs/current-transform)
@ -158,6 +160,7 @@
selected (unchecked-get props "selected") selected (unchecked-get props "selected")
ids (unchecked-get props "ids") ids (unchecked-get props "ids")
ghost? (unchecked-get props "ghost?") ghost? (unchecked-get props "ghost?")
edition (unchecked-get props "edition")
data (mf/deref refs/workspace-page) data (mf/deref refs/workspace-page)
objects (:objects data) objects (:objects data)
root (get objects uuid/zero) root (get objects uuid/zero)
@ -183,7 +186,8 @@
(when (not ghost?) (when (not ghost?)
[:& shape-outlines {:objects objects [:& shape-outlines {:objects objects
:selected selected :selected selected
:hover hover}])])) :hover hover
:edition edition}])]))
(mf/defc ghost-frames (mf/defc ghost-frames
{::mf/wrap-props false} {::mf/wrap-props false}
@ -611,7 +615,8 @@
"auto")}} "auto")}}
[:& frames {:key page-id [:& frames {:key page-id
:hover (:hover local) :hover (:hover local)
:selected selected}] :selected selected
:edition edition}]
(when (= :move (:transform local)) (when (= :move (:transform local))
[:& ghost-frames {:modifiers (:modifiers local) [:& ghost-frames {:modifiers (:modifiers local)

View file

@ -250,3 +250,6 @@
(defn get-user-agent [] (defn get-user-agent []
(.-userAgent js/navigator)) (.-userAgent js/navigator))
(defn active? [node]
(= (.-activeElement js/document) node))