From e1923468a4ad59854f9fce72a361d77a55b9fcad Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 22 Dec 2020 18:05:37 +0100 Subject: [PATCH] :bug: Fixes issues with empty input in options --- .../app/main/ui/components/numeric_input.cljs | 120 ++++++++++++++---- .../ui/workspace/sidebar/options/frame.cljs | 20 +-- .../workspace/sidebar/options/frame_grid.cljs | 10 +- .../workspace/sidebar/options/measures.cljs | 84 ++++++------ .../ui/workspace/sidebar/options/path.cljs | 5 + .../sidebar/options/rows/color_row.cljs | 18 +-- .../sidebar/options/rows/input_row.cljs | 17 +-- .../ui/workspace/sidebar/options/shadow.cljs | 25 ++-- .../src/app/main/ui/workspace/viewport.cljs | 9 +- frontend/src/app/util/dom.cljs | 3 + 10 files changed, 181 insertions(+), 130 deletions(-) diff --git a/frontend/src/app/main/ui/components/numeric_input.cljs b/frontend/src/app/main/ui/components/numeric_input.cljs index d2c005729..6ee38c6d1 100644 --- a/frontend/src/app/main/ui/components/numeric_input.cljs +++ b/frontend/src/app/main/ui/components/numeric_input.cljs @@ -13,36 +13,110 @@ [app.main.ui.keyboard :as kbd] [app.common.data :as d] [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/wrap-props false ::mf/forward-ref true} [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 - (fn [event] - (when (and (or (kbd/up-arrow? event) (kbd/down-arrow? event)) - (kbd/shift? event)) - (let [increment (if (kbd/up-arrow? event) 9 -9) ; this is added to the - target (dom/get-target event) ; default 1 or -1 step - 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))))) + (mf/deps on-change) + (fn [event] + (let [value (parse-value event)] + (when (and on-change (num? value)) + (on-change value))))) - props (-> props - (obj/set! "className" "input-text") - (obj/set! "type" "number") - (obj/set! "ref" ref) - (obj/set! "onKeyDown" on-key-down))] + set-delta + (mf/use-callback + (mf/deps on-change wrap-value? min-val max-val) + (fn [event up? 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])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs index 90489cee2..8e5c77c86 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs @@ -49,24 +49,16 @@ (udw/update-dimensions [(:id shape)] :height new-height)))) on-size-change - (fn [event attr] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 1))] - (st/emit! (udw/update-dimensions [(:id shape)] attr value)))) + (fn [value attr] + (st/emit! (udw/update-dimensions [(:id shape)] attr value))) on-proportion-lock-change (fn [event] (st/emit! (udw/set-shape-proportion-lock (:id shape) (not (:proportion-lock shape))))) on-position-change - (fn [event attr] - (let [cval (-> (dom/get-target event) - (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}))))) + (fn [value attr] + (st/emit! (udw/update-position (:id shape) {attr value}))) on-width-change #(on-size-change % :width) on-height-change #(on-size-change % :height) @@ -105,7 +97,7 @@ i/lock i/unlock)] [:div.input-element.pixels - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :on-click select-all :on-change on-width-change :value (-> (:width shape) @@ -114,7 +106,7 @@ [:div.input-element.pixels - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :on-click select-all :on-change on-height-change :value (-> (:height shape) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs index ed4c96295..cc0e88175 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/frame_grid.cljs @@ -74,12 +74,6 @@ (fn [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 (fn [size] (let [grid (d/deep-merge grid (:changes @state)) @@ -136,10 +130,10 @@ (if (= type :square) [:div.input-element.pixels - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :no-validate true :value (:size params) - :on-change (handle-change-event :params :size)}]] + :on-change (handle-change :params :size)}]] [:& editable-select {:value (:size params) :type (when (number? (:size params)) "number" ) :class "input-option" diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs index c26a11a8c..236196506 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/measures.cljs @@ -54,57 +54,54 @@ (not= (:x values) :multiple) (assoc :x x) (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) on-size-change - (fn [event attr] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 1))] - (st/emit! (udw/update-dimensions ids attr value)))) + (mf/use-callback + (mf/deps ids) + (fn [value attr] + (st/emit! (udw/update-dimensions ids attr value)))) on-proportion-lock-change - (fn [event] - (let [new-lock (if (= proportion-lock :multiple) true (not proportion-lock))] - (run! #(st/emit! (udw/set-shape-proportion-lock % new-lock)) ids))) + (mf/use-callback + (mf/deps 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 - (fn [shape' frame' value attr] - (let [from (-> shape' :points gsh/points->selrect attr) - to (+ value (attr frame')) - target (+ (attr shape') (- to from))] - (st/emit! (udw/update-position (:id shape') {attr target})))) + (mf/use-callback + (mf/deps ids) + (fn [shape' frame' value attr] + (let [to (+ value (attr frame'))] + (st/emit! (udw/update-position (:id shape') { attr to }))))) on-position-change - (fn [event attr] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 0))] - (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')}))) + (mf/use-callback + (mf/deps ids) + (fn [value attr] + (doall (map #(do-position-change %1 %2 value attr) shapes frames)))) on-rotation-change - (fn [event] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 0))] - (doall (map #(do-rotation-change %1 %2 value) shapes old-shapes)))) + (mf/use-callback + (mf/deps ids) + (fn [value] + (st/emit! (udw/increase-rotation ids value)))) on-radius-change - (fn [event] - (let [value (-> (dom/get-target event) - (dom/get-value) - (d/parse-integer 0))] - (st/emit! (dwc/update-shapes - ids-with-children - #(if (:rx %) - (assoc % :rx value :ry value) - %))))) + (mf/use-callback + (mf/deps ids) + (fn [value] + (let [radius-update + (fn [shape] + (cond-> shape + (:rx shape) (assoc :rx value :ry value)))] + (st/emit! (dwc/update-shapes ids-with-children radius-update))))) on-width-change #(on-size-change % :width) on-height-change #(on-size-change % :height) @@ -120,7 +117,7 @@ [:div.row-flex [:span.element-set-subtitle (t locale "workspace.options.size")] [:div.input-element.width - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :no-validate true :placeholder "--" :on-click select-all @@ -128,7 +125,7 @@ :value (attr->string :width values)}]] [:div.input-element.height - [:> numeric-input {:min "1" + [:> numeric-input {:min 1 :no-validate true :placeholder "--" :on-click select-all @@ -167,8 +164,9 @@ [:div.input-element.degrees [:> numeric-input {:no-validate true - :min "0" - :max "359" + :min 0 + :max 359 + :data-wrap true :placeholder "--" :on-click select-all :on-change on-rotation-change @@ -189,7 +187,7 @@ [:div.input-element.pixels [:> numeric-input {:placeholder "--" - :min "0" + :min 0 :on-click select-all :on-change on-radius-change :value (attr->string :rx values)}]] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs index 0f01f9522..363385f2f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs @@ -11,6 +11,7 @@ (:require [rumext.alpha :as mf] [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.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] @@ -20,8 +21,12 @@ [{:keys [shape] :as props}] (let [ids [(:id shape)] type (:type shape) + measure-values (select-keys shape measure-attrs) stroke-values (select-keys shape stroke-attrs)] [:* + [:& measures-menu {:ids ids + :type type + :values measure-values}] [:& fill-menu {:ids ids :type type :values (select-keys shape fill-attrs)}] diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index f5b771dce..58a378da5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -55,11 +55,6 @@ (* 100) (math/round))))) -(defn string->opacity [opacity-str] - (-> opacity-str - (d/parse-integer 1) - (/ 100))) - (defn remove-multiple [v] (if (= v :multiple) nil v)) @@ -103,13 +98,8 @@ append-hash change-value)))) - handle-opacity-change (fn [event] - (let [target (dom/get-target event)] - (when (dom/valid? target) - (-> target - dom/get-value - string->opacity - change-opacity)))) + handle-opacity-change (fn [value] + (change-opacity (/ value 100))) select-all (fn [event] (dom/select-text! (dom/get-target event))) @@ -171,6 +161,6 @@ :placeholder (tr "settings.multiple") :on-click select-all :on-change handle-opacity-change - :min "0" - :max "100"}]])])])) + :min 0 + :max 100}]])])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs index a04be184d..c21ff370d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/input_row.cljs @@ -36,16 +36,9 @@ :placeholder placeholder :on-change on-change}] - (let [handle-change - (fn [event] - (let [value (-> event dom/get-target dom/get-value d/parse-integer)] - (when (and (not (nil? on-change)) - (or (not min) (>= value min)) - (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 "")}]))]]) + [:> numeric-input {:placeholder placeholder + :min min + :max max + :on-change on-change + :value (or value "")}])]]) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs index fe99c537f..4525a4c90 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs @@ -70,13 +70,10 @@ (update-attr index attr valid? nil)) ([index attr valid? update-ref] - (fn [event] - (let [value (dom/get-value (dom/get-target event))] - (when (or (not valid?) (valid? value)) - (do - (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)))))))))) + (fn [value] + (when (or (not valid?) (valid? value)) + (do (st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index attr] value))) + (when update-ref (dom/set-value! (mf/ref-val update-ref) value))))))) update-color (fn [index] @@ -101,16 +98,16 @@ [:> numeric-input {:ref basic-offset-x-ref :on-change (update-attr index :offset-x valid-number?) :on-click (select-text basic-offset-x-ref) - :default-value (:offset-x value)}] + :value (:offset-x value)}] [:> numeric-input {:ref basic-offset-y-ref :on-change (update-attr index :offset-y valid-number?) :on-click (select-text basic-offset-y-ref) - :default-value (:offset-y value)}] + :value (:offset-y value)}] [:> numeric-input {:ref basic-blur-ref :on-click (select-text basic-blur-ref) :on-change (update-attr index :blur valid-number?) :min 0 - :default-value (:blur value)}] + :value (:blur value)}] [:div.element-set-actions [:div.element-set-actions-button {:on-click (toggle-visibility index)} @@ -136,7 +133,7 @@ :placeholder "--" :on-click (select-text adv-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")]] [:div.input-element @@ -145,7 +142,7 @@ :placeholder "--" :on-click (select-text adv-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")]]] [:div.row-grid-2 @@ -156,7 +153,7 @@ :on-click (select-text adv-blur-ref) :on-change (update-attr index :blur valid-number? basic-blur-ref) :min 0 - :default-value (:blur value)}] + :value (:blur value)}] [:span.after (t locale "workspace.options.shadow-options.blur")]] [:div.input-element @@ -166,7 +163,7 @@ :on-click (select-text adv-spread-ref) :on-change (update-attr index :spread valid-number?) :min 0 - :default-value (:spread value)}] + :value (:spread value)}] [:span.after (t locale "workspace.options.shadow-options.spread")]]] [:div.color-row-wrap diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 8747752a3..a9ace2171 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -134,9 +134,11 @@ (let [objects (unchecked-get props "objects") selected (or (unchecked-get props "selected") #{}) hover (or (unchecked-get props "hover") #{}) + edition (unchecked-get props "edition") outline? (set/union selected hover) show-outline? (fn [shape] (and (not (:hidden shape)) (not (:blocked shape)) + (not= edition (:id shape)) (outline? (:id shape)))) shapes (->> (vals objects) (filter show-outline?)) transform (mf/deref refs/current-transform) @@ -158,6 +160,7 @@ selected (unchecked-get props "selected") ids (unchecked-get props "ids") ghost? (unchecked-get props "ghost?") + edition (unchecked-get props "edition") data (mf/deref refs/workspace-page) objects (:objects data) root (get objects uuid/zero) @@ -183,7 +186,8 @@ (when (not ghost?) [:& shape-outlines {:objects objects :selected selected - :hover hover}])])) + :hover hover + :edition edition}])])) (mf/defc ghost-frames {::mf/wrap-props false} @@ -611,7 +615,8 @@ "auto")}} [:& frames {:key page-id :hover (:hover local) - :selected selected}] + :selected selected + :edition edition}] (when (= :move (:transform local)) [:& ghost-frames {:modifiers (:modifiers local) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index 1dad84d48..bf42d709f 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -250,3 +250,6 @@ (defn get-user-agent [] (.-userAgent js/navigator)) + +(defn active? [node] + (= (.-activeElement js/document) node))