mirror of
https://github.com/penpot/penpot.git
synced 2026-04-30 21:59:10 +00:00
Merge pull request #440 from penpot/fix/numeric-inputs
Bug fixes and improvements
This commit is contained in:
commit
66606b7309
@ -293,7 +293,9 @@
|
||||
"Function that checks if a number is nil or nan. Will return 0 when not
|
||||
valid and the number otherwise."
|
||||
[v]
|
||||
(if (or (not v) (mth/nan? v)) 0 v))
|
||||
(if (or (not v)
|
||||
(not (mth/finite? v))
|
||||
(mth/nan? v)) 0 v))
|
||||
|
||||
|
||||
(defmacro export
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
(us/assert #{:width :height} attr)
|
||||
(us/assert number? value)
|
||||
(let [{:keys [proportion proportion-lock]} shape
|
||||
size (select-keys shape [:width :height])
|
||||
size (select-keys (:selrect shape) [:width :height])
|
||||
new-size (if-not proportion-lock
|
||||
(assoc size attr value)
|
||||
(if (= attr :width)
|
||||
@ -260,15 +260,19 @@
|
||||
(d/export gco/center-shape)
|
||||
(d/export gco/center-selrect)
|
||||
(d/export gco/center-rect)
|
||||
(d/export gco/center-points)
|
||||
(d/export gpr/rect->selrect)
|
||||
(d/export gpr/rect->points)
|
||||
(d/export gpr/points->selrect)
|
||||
(d/export gtr/transform-shape)
|
||||
(d/export gtr/transform-matrix)
|
||||
(d/export gtr/inverse-transform-matrix)
|
||||
(d/export gtr/transform-point-center)
|
||||
(d/export gtr/transform-rect)
|
||||
(d/export gtr/update-group-selrect)
|
||||
(d/export gtr/transform-points)
|
||||
|
||||
;; PATHS
|
||||
(d/export gsp/content->points)
|
||||
(d/export gsp/content->selrect)
|
||||
(d/export gsp/transform-content)
|
||||
|
||||
@ -14,7 +14,13 @@
|
||||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.path :as gpa]
|
||||
[app.common.geom.shapes.rect :as gpr]
|
||||
[app.common.math :as mth]))
|
||||
[app.common.math :as mth]
|
||||
[app.common.data :as d]))
|
||||
|
||||
(defn- modif-rotation [shape]
|
||||
(let [cur-rotation (d/check-num (:rotation shape))
|
||||
delta-angle (d/check-num (get-in shape [:modifiers :rotation]))]
|
||||
(mod (+ cur-rotation delta-angle) 360)))
|
||||
|
||||
(defn transform-matrix
|
||||
"Returns a transformation matrix without changing the shape properties.
|
||||
@ -32,6 +38,18 @@
|
||||
(and (not no-flip) flip-y) (gmt/scale (gpt/point 1 -1)))
|
||||
(gmt/translate (gpt/negate shape-center))))))
|
||||
|
||||
(defn inverse-transform-matrix
|
||||
([shape]
|
||||
(let [shape-center (or (gco/center-shape shape)
|
||||
(gpt/point 0 0))]
|
||||
(inverse-transform-matrix shape shape-center)))
|
||||
([shape center]
|
||||
(let []
|
||||
(-> (gmt/matrix)
|
||||
(gmt/translate center)
|
||||
(gmt/multiply (:transform-inverse shape (gmt/matrix)))
|
||||
(gmt/translate (gpt/negate center))))))
|
||||
|
||||
(defn transform-point-center
|
||||
"Transform a point around the shape center"
|
||||
[point center matrix]
|
||||
@ -191,18 +209,23 @@
|
||||
(defn apply-transform-path
|
||||
[shape transform]
|
||||
(let [content (gpa/transform-content (:content shape) transform)
|
||||
selrect (gpa/content->selrect content)
|
||||
points (gpr/rect->points selrect)
|
||||
;;rotation (mod (+ (:rotation shape 0)
|
||||
;; (or (get-in shape [:modifiers :rotation]) 0))
|
||||
;; 360)
|
||||
]
|
||||
|
||||
;; Calculate the new selrect by "unrotate" the shape
|
||||
rotation (modif-rotation shape)
|
||||
center (gpt/transform (gco/center-shape shape) transform)
|
||||
content-rotated (gpa/transform-content content (gmt/rotate-matrix (- rotation) center))
|
||||
selrect (gpa/content->selrect content-rotated)
|
||||
|
||||
;; Transform the points
|
||||
points (-> (:points shape)
|
||||
(transform-points transform))]
|
||||
(assoc shape
|
||||
:content content
|
||||
:points points
|
||||
:selrect selrect
|
||||
;;:rotation rotation
|
||||
)))
|
||||
:transform (gmt/rotate-matrix rotation)
|
||||
:transform-inverse (gmt/rotate-matrix (- rotation))
|
||||
:rotation rotation)))
|
||||
|
||||
(defn apply-transform-rect
|
||||
"Given a new set of points transformed, set up the rectangle so it keeps
|
||||
@ -246,6 +269,30 @@
|
||||
apply-transform-rect)]
|
||||
(apply-transform-fn shape transform)))
|
||||
|
||||
(defn transform-gradients [shape modifiers]
|
||||
(let [angle (d/check-num (get modifiers :rotation))
|
||||
;; Gradients are represented with unit vectors so its center is 0.5, 0.5
|
||||
center (gpt/point 0.5 0.5)
|
||||
transform (gmt/rotate-matrix angle center)
|
||||
transform-gradient
|
||||
(fn [{:keys [start-x start-y end-x end-y] :as gradient}]
|
||||
(let [start-point (gpt/point start-x start-y)
|
||||
end-point (gpt/point end-x end-y)
|
||||
{start-x :x start-y :y} (gpt/transform start-point transform)
|
||||
{end-x :x end-y :y} (gpt/transform end-point transform)]
|
||||
|
||||
(assoc gradient
|
||||
:start-x start-x
|
||||
:start-y start-y
|
||||
:end-x end-x
|
||||
:end-y end-y)))]
|
||||
(cond-> shape
|
||||
(:fill-color-gradient shape)
|
||||
(update :fill-color-gradient transform-gradient)
|
||||
|
||||
(:stroke-color-gradient shape)
|
||||
(update :stroke-color-gradient transform-gradient))))
|
||||
|
||||
(defn set-flip [shape modifiers]
|
||||
(let [rx (get-in modifiers [:resize-vector :x])
|
||||
ry (get-in modifiers [:resize-vector :y])]
|
||||
@ -260,6 +307,7 @@
|
||||
(-> shape
|
||||
(set-flip (:modifiers shape))
|
||||
(apply-transform transform)
|
||||
(transform-gradients (:modifiers shape))
|
||||
(dissoc :modifiers)))
|
||||
shape)))
|
||||
|
||||
@ -285,3 +333,4 @@
|
||||
(assoc :selrect new-selrect)
|
||||
(assoc :points new-points)
|
||||
(apply-transform-rect (gmt/matrix)))))
|
||||
|
||||
|
||||
@ -175,21 +175,11 @@
|
||||
([objects {:keys [include-frames?] :or {include-frames? false}}]
|
||||
(let [lookup #(get objects %)
|
||||
root (lookup uuid/zero)
|
||||
childs (:shapes root)]
|
||||
(loop [id (first childs)
|
||||
ids (rest childs)
|
||||
res []]
|
||||
(if (nil? id)
|
||||
res
|
||||
(let [obj (lookup id)
|
||||
typ (:type obj)]
|
||||
(recur (first ids)
|
||||
(rest ids)
|
||||
(if (= :frame typ)
|
||||
(if include-frames?
|
||||
(d/concat res [obj] (map lookup (:shapes obj)))
|
||||
(d/concat res (map lookup (:shapes obj))))
|
||||
(conj res obj)))))))))
|
||||
childs (:shapes root)
|
||||
shapes (->> childs
|
||||
(mapv lookup))]
|
||||
(cond->> shapes
|
||||
include-frames? (filterv #(not= :frame (:type %)))))))
|
||||
|
||||
(defn select-frames
|
||||
[objects]
|
||||
|
||||
@ -100,8 +100,7 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
img {display: none;}
|
||||
.update-overlay {opacity: 1};
|
||||
.update-overlay {opacity: 0.8};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,6 +148,7 @@
|
||||
(cond-> s
|
||||
true
|
||||
(assoc :stroke-color (:color color)
|
||||
:stroke-opacity (:opacity color)
|
||||
:stroke-color-gradient (:gradient color)
|
||||
:stroke-color-ref-id (:id color)
|
||||
:stroke-color-ref-file (:file-id color))
|
||||
|
||||
@ -1038,9 +1038,12 @@
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (dwc/lookup-page-objects state page-id)
|
||||
shape (get objects id)
|
||||
cpos (gpt/point (:x shape) (:y shape))
|
||||
pos (gpt/point (or (:x position) (:x shape))
|
||||
(or (:y position) (:y shape)))
|
||||
|
||||
bbox (-> shape :points gsh/points->selrect)
|
||||
|
||||
cpos (gpt/point (:x bbox) (:y bbox))
|
||||
pos (gpt/point (or (:x position) (:x bbox))
|
||||
(or (:y position) (:y bbox)))
|
||||
displ (gmt/translate-matrix (gpt/subtract pos cpos))]
|
||||
(rx/of (dwt/set-modifiers [id] {:displacement displ})
|
||||
(dwt/apply-modifiers [id]))))))
|
||||
@ -1544,6 +1547,7 @@
|
||||
(d/export dwt/start-move-selected)
|
||||
(d/export dwt/move-selected)
|
||||
(d/export dwt/set-rotation)
|
||||
(d/export dwt/increase-rotation)
|
||||
(d/export dwt/set-modifiers)
|
||||
(d/export dwt/apply-modifiers)
|
||||
(d/export dwt/update-dimensions)
|
||||
|
||||
@ -538,8 +538,6 @@
|
||||
unames (retrieve-used-names objects)
|
||||
name (generate-unique-name unames (:name shape))
|
||||
|
||||
|
||||
|
||||
frame-id (if (= :frame (:type attrs))
|
||||
uuid/zero
|
||||
(or (:frame-id attrs)
|
||||
@ -568,3 +566,31 @@
|
||||
(when (= :text (:type attrs))
|
||||
(->> (rx/of (start-edition-mode id))
|
||||
(rx/observe-on :async))))))))
|
||||
|
||||
(defn move-shapes-into-frame [frame-id shapes]
|
||||
(ptk/reify ::move-shapes-into-frame
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (lookup-page-objects state page-id)
|
||||
to-move-shapes (->> (cp/select-toplevel-shapes objects {:include-frames? false})
|
||||
(mapv :id)
|
||||
(d/enumerate)
|
||||
(filterv (comp shapes second)))
|
||||
|
||||
rchanges [{:type :mov-objects
|
||||
:parent-id frame-id
|
||||
:frame-id frame-id
|
||||
:page-id page-id
|
||||
:index 0
|
||||
:shapes (mapv second to-move-shapes)}]
|
||||
|
||||
uchanges (->> to-move-shapes
|
||||
(mapv (fn [[index shape-id]]
|
||||
{:type :mov-objects
|
||||
:parent-id uuid/zero
|
||||
:frame-id uuid/zero
|
||||
:page-id page-id
|
||||
:index index
|
||||
:shapes [shape-id]})))]
|
||||
(rx/of (commit-changes rchanges uchanges {:commit-local? true}))))))
|
||||
|
||||
@ -15,7 +15,8 @@
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.streams :as ms]))
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]))
|
||||
|
||||
(def clear-drawing
|
||||
(ptk/reify ::clear-drawing
|
||||
@ -31,7 +32,8 @@
|
||||
(rx/concat
|
||||
(rx/of clear-drawing)
|
||||
(when (:initialized? shape)
|
||||
(let [shape-click-width (case (:type shape)
|
||||
(let [page-id (:current-page-id state)
|
||||
shape-click-width (case (:type shape)
|
||||
:text 3
|
||||
20)
|
||||
shape-click-height (case (:type shape)
|
||||
@ -59,4 +61,11 @@
|
||||
(rx/empty))
|
||||
|
||||
(rx/of (dws/deselect-all)
|
||||
(dwc/add-shape shape))))))))))
|
||||
(dwc/add-shape shape))
|
||||
|
||||
(if (= :frame (:type shape))
|
||||
(->> (uw/ask! {:cmd :selection/query
|
||||
:page-id page-id
|
||||
:rect (:selrect shape)})
|
||||
(rx/map #(dwc/move-shapes-into-frame (:id shape) %)))
|
||||
(rx/empty))))))))))
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
[app.common.math :as mth]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.util.data :as ud]
|
||||
[app.common.data :as cd]
|
||||
[app.util.geom.path :as ugp]
|
||||
@ -87,12 +88,37 @@
|
||||
[:workspace-drawing :object])
|
||||
path)))
|
||||
|
||||
(defn- points->components [shape content]
|
||||
(let [rotation (:rotation shape 0)
|
||||
center (gsh/center-shape shape)
|
||||
content-rotated (gsh/transform-content content (gmt/rotate-matrix (- rotation) center))
|
||||
|
||||
;; Calculates the new selrect with points given the old center
|
||||
points (-> (gsh/content->selrect content-rotated)
|
||||
(gsh/rect->points)
|
||||
(gsh/transform-points center (:transform shape (gmt/matrix))))
|
||||
|
||||
points-center (gsh/center-points points)
|
||||
|
||||
;; Points is now the selrect but the center is different so we can create the selrect
|
||||
;; through points
|
||||
selrect (-> points
|
||||
(gsh/transform-points points-center (:transform-inverse shape (gmt/matrix)))
|
||||
(gsh/points->selrect))]
|
||||
[points selrect]))
|
||||
|
||||
(defn update-selrect
|
||||
"Updates the selrect and points for a path"
|
||||
[shape]
|
||||
(let [selrect (gsh/content->selrect (:content shape))
|
||||
points (gsh/rect->points selrect)]
|
||||
(assoc shape :points points :selrect selrect)))
|
||||
(if (= (:rotation shape 0) 0)
|
||||
(let [content (:content shape)
|
||||
selrect (gsh/content->selrect content)
|
||||
points (gsh/rect->points selrect)]
|
||||
(assoc shape :points points :selrect selrect))
|
||||
|
||||
(let [content (:content shape)
|
||||
[points selrect] (points->components shape content)]
|
||||
(assoc shape :points points :selrect selrect))))
|
||||
|
||||
(defn closest-angle [angle]
|
||||
(cond
|
||||
@ -157,13 +183,12 @@
|
||||
;; TODO: Enter now finish path but can finish drawing/editing as well
|
||||
(= enter-keycode (:key event)))))
|
||||
|
||||
(defn generate-path-changes [page-id shape-id old-content new-content]
|
||||
(defn generate-path-changes [page-id shape old-content new-content]
|
||||
(us/verify ::content old-content)
|
||||
(us/verify ::content new-content)
|
||||
(let [old-selrect (gsh/content->selrect old-content)
|
||||
old-points (gsh/rect->points old-selrect)
|
||||
new-selrect (gsh/content->selrect new-content)
|
||||
new-points (gsh/rect->points new-selrect)
|
||||
(let [shape-id (:id shape)
|
||||
[old-points old-selrect] (points->components shape old-content)
|
||||
[new-points new-selrect] (points->components shape new-content)
|
||||
|
||||
rch [{:type :mod-obj
|
||||
:id shape-id
|
||||
@ -393,7 +418,7 @@
|
||||
shape (get-in state (get-path state))
|
||||
selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
new-content (reduce ugp/make-corner-point (:content shape) selected-points)
|
||||
[rch uch] (generate-path-changes page-id id (:content shape) new-content)]
|
||||
[rch uch] (generate-path-changes page-id shape (:content shape) new-content)]
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true}))))))
|
||||
|
||||
(defn make-curve []
|
||||
@ -405,7 +430,7 @@
|
||||
shape (get-in state (get-path state))
|
||||
selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
new-content (reduce ugp/make-curve-point (:content shape) selected-points)
|
||||
[rch uch] (generate-path-changes page-id id (:content shape) new-content)]
|
||||
[rch uch] (generate-path-changes page-id shape (:content shape) new-content)]
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true}))))))
|
||||
|
||||
(defn path-handler-enter [index prefix]
|
||||
@ -552,7 +577,7 @@
|
||||
shape (get-in state (get-path state))
|
||||
content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers])
|
||||
new-content (ugp/apply-content-modifiers (:content shape) content-modifiers)
|
||||
[rch uch] (generate-path-changes page-id (:id shape) (:content shape) new-content)]
|
||||
[rch uch] (generate-path-changes page-id shape (:content shape) new-content)]
|
||||
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true})
|
||||
(fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers)))))))
|
||||
@ -573,7 +598,7 @@
|
||||
shape (get-in state (get-path state))
|
||||
page-id (:current-page-id state)
|
||||
old-content (get-in state [:workspace-local :edit-path id :old-content])
|
||||
[rch uch] (generate-path-changes page-id id old-content (:content shape))]
|
||||
[rch uch] (generate-path-changes page-id shape old-content (:content shape))]
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true}))))))
|
||||
|
||||
(declare start-draw-mode)
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.spec :as us]
|
||||
[app.config :as cfg]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.persistence :as dwp]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
@ -146,7 +147,7 @@
|
||||
(let [session {:id id
|
||||
:fullname (:fullname profile)
|
||||
:updated-at (dt/now)
|
||||
:photo-uri (or (:photo-uri profile)
|
||||
:photo-uri (or (and (:photo profile) (cfg/resolve-media-path (:photo profile)))
|
||||
(avatars/generate {:name (:fullname profile)}))}
|
||||
session (assign-color sessions session)]
|
||||
(assoc sessions id session)))
|
||||
|
||||
@ -431,6 +431,20 @@
|
||||
(let [page-id (:current-page-id state)]
|
||||
(d/update-in-when state [:workspace-data :pages-index page-id :objects] set-rotation)))))))
|
||||
|
||||
(defn increase-rotation [ids rotation]
|
||||
(ptk/reify ::increase-rotation
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (dwc/lookup-page-objects state page-id)
|
||||
rotate-shape (fn [shape]
|
||||
(let [delta (- rotation (:rotation shape))]
|
||||
(set-rotation delta [shape])))]
|
||||
(rx/concat
|
||||
(rx/from (->> ids (map #(get objects %)) (map rotate-shape)))
|
||||
(rx/of (apply-modifiers ids)))))))
|
||||
|
||||
(defn apply-modifiers
|
||||
[ids]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
|
||||
@ -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]))
|
||||
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
[app.util.i18n :as i18n :refer [tr t]]
|
||||
[cljs.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]))
|
||||
[rumext.alpha :as mf]
|
||||
[app.config :as cfg]))
|
||||
|
||||
(s/def ::fullname ::us/not-empty-string)
|
||||
(s/def ::email ::us/email)
|
||||
@ -90,10 +91,10 @@
|
||||
[{:keys [locale] :as props}]
|
||||
(let [file-input (mf/use-ref nil)
|
||||
profile (mf/deref refs/profile)
|
||||
photo (:photo-uri profile)
|
||||
photo (:photo profile)
|
||||
photo (if (or (str/empty? photo) (nil? photo))
|
||||
"images/avatar.jpg"
|
||||
photo)
|
||||
(cfg/resolve-media-path photo))
|
||||
|
||||
on-image-click #(dom/click (mf/ref-val file-input))
|
||||
|
||||
|
||||
@ -14,15 +14,21 @@
|
||||
[app.util.object :as obj]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.ui.context :as muc]
|
||||
[app.common.geom.point :as gpt]))
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.shapes :as gsh]))
|
||||
|
||||
(mf/defc linear-gradient [{:keys [id gradient shape]}]
|
||||
(let [{:keys [x y width height]} shape]
|
||||
(let [{:keys [x y width height]} (:selrect shape)
|
||||
transform (case (:type shape)
|
||||
:path (gmt/matrix)
|
||||
(gsh/inverse-transform-matrix shape (gpt/point 0.5 0.5)))]
|
||||
[:linearGradient {:id id
|
||||
:x1 (:start-x gradient)
|
||||
:y1 (:start-y gradient)
|
||||
:x2 (:end-x gradient)
|
||||
:y2 (:end-y gradient)}
|
||||
:y2 (:end-y gradient)
|
||||
:gradient-transform transform}
|
||||
(for [{:keys [offset color opacity]} (:stops gradient)]
|
||||
[:stop {:key (str id "-stop-" offset)
|
||||
:offset (or offset 0)
|
||||
@ -30,7 +36,10 @@
|
||||
:stop-opacity opacity}])]))
|
||||
|
||||
(mf/defc radial-gradient [{:keys [id gradient shape]}]
|
||||
(let [{:keys [x y width height]} shape]
|
||||
(let [{:keys [x y width height]} (:selrect shape)
|
||||
transform (case (:type shape)
|
||||
:path (gmt/matrix)
|
||||
(gsh/inverse-transform-matrix shape))]
|
||||
(let [[x y] (if (= (:type shape) :frame) [0 0] [x y])
|
||||
translate-vec (gpt/point (+ x (* width (:start-x gradient)))
|
||||
(+ y (* height (:start-y gradient))))
|
||||
@ -51,10 +60,10 @@
|
||||
scale-vec (gpt/point (* scale-factor-y (/ height 2))
|
||||
(* scale-factor-x (/ width 2)))
|
||||
|
||||
tr-translate (str/fmt "translate(%s, %s)" (:x translate-vec) (:y translate-vec))
|
||||
tr-rotate (str/fmt "rotate(%s)" angle)
|
||||
tr-scale (str/fmt "scale(%s, %s)" (:x scale-vec) (:y scale-vec))
|
||||
transform (str/fmt "%s %s %s" tr-translate tr-rotate tr-scale)]
|
||||
transform (gmt/multiply transform
|
||||
(gmt/translate-matrix translate-vec)
|
||||
(gmt/rotate-matrix angle)
|
||||
(gmt/scale-matrix scale-vec))]
|
||||
[:radialGradient {:id id
|
||||
:cx 0
|
||||
:cy 0
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
[rumext.alpha :as mf]
|
||||
[app.main.ui.shapes.attrs :as attrs]
|
||||
[app.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]
|
||||
[app.common.geom.shapes :as geom]
|
||||
[app.util.object :as obj]
|
||||
[app.util.geom.path :as ugp]))
|
||||
|
||||
@ -24,14 +23,11 @@
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
background? (unchecked-get props "background?")
|
||||
;; {:keys [id x y width height]} (geom/shape->rect-shape shape)
|
||||
{:keys [id x y width height]} (:selrect shape)
|
||||
transform (geom/transform-matrix shape)
|
||||
pdata (ugp/content->path (:content shape))
|
||||
props (-> (attrs/extract-style-attrs shape)
|
||||
(obj/merge!
|
||||
#js {:transform transform
|
||||
:d pdata}))]
|
||||
#js {:d pdata}))]
|
||||
(if background?
|
||||
[:g
|
||||
[:path {:stroke "transparent"
|
||||
|
||||
@ -88,7 +88,7 @@
|
||||
[props ref]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
selected? (unchecked-get props "selected?")
|
||||
grow-type (:grow-type shape)
|
||||
grow-type (unchecked-get props "grow-type")
|
||||
{:keys [id x y width height content]} shape]
|
||||
[:foreignObject {:x x
|
||||
:y y
|
||||
@ -97,7 +97,6 @@
|
||||
:transform (geom/transform-matrix shape)
|
||||
:width (if (#{:auto-width} grow-type) 10000 width)
|
||||
:height (if (#{:auto-height :auto-width} grow-type) 10000 height)
|
||||
:ref ref
|
||||
:pointer-events "none"}
|
||||
:ref ref}
|
||||
[:& text-content {:shape shape
|
||||
:content (:content shape)}]]))
|
||||
|
||||
@ -69,13 +69,15 @@
|
||||
[props]
|
||||
(let [layout (obj/get props "layout")
|
||||
selected-drawtool (mf/deref refs/selected-drawing-tool)
|
||||
select-drawtool #(st/emit! :interrupt (dw/select-for-drawing %))]
|
||||
select-drawtool #(st/emit! :interrupt (dw/select-for-drawing %))
|
||||
edition (mf/deref refs/selected-edition)]
|
||||
[:aside.left-toolbar
|
||||
[:div.left-toolbar-inside
|
||||
[:ul.left-toolbar-options
|
||||
[:li.tooltip.tooltip-right
|
||||
{:alt (tr "workspace.toolbar.move")
|
||||
:class (when (nil? selected-drawtool) "selected")
|
||||
:class (when (and (nil? selected-drawtool)
|
||||
(not edition)) "selected")
|
||||
:on-click (st/emitf :interrupt)}
|
||||
i/pointer-inner]
|
||||
[:li.tooltip.tooltip-right
|
||||
|
||||
@ -44,16 +44,17 @@
|
||||
(def selection-rect-width 1)
|
||||
|
||||
(mf/defc selection-rect [{:keys [transform rect zoom color]}]
|
||||
(let [{:keys [x y width height]} rect]
|
||||
[:rect.main
|
||||
{:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:transform transform
|
||||
:style {:stroke color
|
||||
:stroke-width (/ selection-rect-width zoom)
|
||||
:fill "transparent"}}]))
|
||||
(when rect
|
||||
(let [{:keys [x y width height]} rect]
|
||||
[:rect.main
|
||||
{:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:transform transform
|
||||
:style {:stroke color
|
||||
:stroke-width (/ selection-rect-width zoom)
|
||||
:fill "transparent"}}])))
|
||||
|
||||
(defn- handlers-for-selection [{:keys [x y width height]}]
|
||||
[;; TOP-LEFT
|
||||
@ -181,9 +182,7 @@
|
||||
current-transform (mf/deref refs/current-transform)
|
||||
|
||||
selrect (:selrect shape)
|
||||
transform (geom/transform-matrix shape {:no-flip true})
|
||||
|
||||
tr-shape (geom/transform-shape shape)]
|
||||
transform (geom/transform-matrix shape {:no-flip true})]
|
||||
|
||||
(when (not (#{:move :rotate} current-transform))
|
||||
[:g.controls
|
||||
@ -193,7 +192,7 @@
|
||||
:transform transform
|
||||
:zoom zoom
|
||||
:color color}]
|
||||
[:& outline {:shape tr-shape :color color}]
|
||||
[:& outline {:shape shape :color color}]
|
||||
|
||||
;; Handlers
|
||||
(for [{:keys [type position props]} (handlers-for-selection selrect)]
|
||||
|
||||
@ -35,11 +35,12 @@
|
||||
:stroke-width "1px"
|
||||
:stroke-opacity 0.5}]]))
|
||||
|
||||
(mf/defc render-rect [{{:keys [x y width height]} :rect :keys [color]}]
|
||||
(mf/defc render-rect [{{:keys [x y width height]} :rect :keys [color transform]}]
|
||||
[:rect {:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:transform (or transform "none")
|
||||
:style {:stroke color
|
||||
:fill "transparent"
|
||||
:stroke-width "1px"
|
||||
@ -76,7 +77,7 @@
|
||||
:fill line-color
|
||||
:stroke "white"
|
||||
:stroke-width 0.1}
|
||||
(str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x shape)) (fixed (:y shape)))]
|
||||
(str/format "%s - (%s, %s)" (str/slice (str (:id shape)) 0 8) (fixed (:x selrect)) (fixed (:y selrect)))]
|
||||
|
||||
[:& cross-point {:point shape-center
|
||||
:zoom zoom
|
||||
@ -87,7 +88,7 @@
|
||||
:zoom zoom
|
||||
:color line-color}])
|
||||
|
||||
[:& render-rect-points {:rect selrect
|
||||
[:& render-rect-points {:points (:points shape)
|
||||
:color line-color}]
|
||||
|
||||
[:& render-rect {:rect selrect
|
||||
|
||||
@ -45,7 +45,8 @@
|
||||
:ry (/ height 2)}
|
||||
|
||||
:path
|
||||
{:d (ugp/content->path (:content shape))}
|
||||
{:d (ugp/content->path (:content shape))
|
||||
:transform nil}
|
||||
|
||||
{:x x
|
||||
:y y
|
||||
|
||||
@ -110,10 +110,12 @@
|
||||
[:& text/text-shape {:key (str "text-shape" (:id shape))
|
||||
:ref text-ref-cb
|
||||
:shape shape
|
||||
:selected? selected?}]]
|
||||
:selected? selected?
|
||||
:grow-type (:grow-type shape)}]]
|
||||
(when edition?
|
||||
[:& editor/text-shape-edit {:key (str "editor" (:id shape))
|
||||
:shape shape}])
|
||||
[:g {:pointer-events "none"}
|
||||
[:& editor/text-shape-edit {:key (str "editor" (:id shape))
|
||||
:shape shape}]])
|
||||
|
||||
(when-not edition?
|
||||
[:rect.text-actions
|
||||
|
||||
@ -120,7 +120,8 @@
|
||||
(dom/stop-propagation event)
|
||||
(if (:blocked item)
|
||||
(st/emit! (dw/update-shape-flags id {:blocked false}))
|
||||
(st/emit! (dw/update-shape-flags id {:blocked true}))))
|
||||
(st/emit! (dw/update-shape-flags id {:blocked true})
|
||||
(dw/select-shape id true))))
|
||||
|
||||
toggle-visibility
|
||||
(fn [event]
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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)}]]
|
||||
|
||||
@ -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)}]
|
||||
|
||||
@ -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}]])])]))
|
||||
|
||||
|
||||
@ -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 "")}])]])
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -250,3 +250,6 @@
|
||||
|
||||
(defn get-user-agent []
|
||||
(.-userAgent js/navigator))
|
||||
|
||||
(defn active? [node]
|
||||
(= (.-activeElement js/document) node))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user