mirror of
https://github.com/penpot/penpot.git
synced 2025-08-06 06:18:23 +02:00
More work on element options.
This commit is contained in:
parent
43b6056c1e
commit
e1a15aed9a
5 changed files with 150 additions and 45 deletions
|
@ -15,30 +15,40 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(def ^:static +shape-schema+
|
(def ^:static +shape-schema+
|
||||||
{:x [v/integer]
|
{:x [sc/integer]
|
||||||
:y [v/integer]
|
:y [sc/integer]
|
||||||
:width [v/integer]
|
:width [sc/integer]
|
||||||
:height [v/integer]
|
:height [sc/integer]
|
||||||
:type [v/required sc/shape-type]})
|
:type [sc/required sc/shape-type]})
|
||||||
|
|
||||||
(def ^:static +shape-update-size-schema+
|
(def ^:static +shape-size-schema+
|
||||||
{:width [v/integer]
|
{:width [sc/integer]
|
||||||
:height [v/integer]
|
:height [sc/integer]
|
||||||
:lock [v/boolean]})
|
:lock [sc/boolean]})
|
||||||
|
|
||||||
(def ^:static +shape-update-fill-schema+
|
(def ^:static +shape-fill-attrs-schema+
|
||||||
{:color [sc/color]
|
{:color [sc/color]
|
||||||
:opacity [v/number]})
|
:opacity [sc/number]})
|
||||||
|
|
||||||
(def ^:static +shape-update-stroke-schema+
|
(def ^:static +shape-stroke-attrs-schema+
|
||||||
{:color [sc/color]
|
{:color [sc/color]
|
||||||
:opacity [v/number]})
|
:width [sc/integer]
|
||||||
|
:type [sc/keyword]
|
||||||
|
:opacity [sc/number]})
|
||||||
|
|
||||||
(def ^:static +shape-update-position-schema+
|
(def ^:static +shape-line-attrs-schema+
|
||||||
{:x1 [v/integer]
|
{:x1 [sc/integer]
|
||||||
:y1 [v/integer]
|
:y1 [sc/integer]
|
||||||
:x2 [v/integer]
|
:x2 [sc/integer]
|
||||||
:y2 [v/integer]})
|
:y2 [sc/integer]})
|
||||||
|
|
||||||
|
(def ^:static +shape-radius-attrs-schema+
|
||||||
|
{:rx [sc/integer]
|
||||||
|
:ry [sc/integer]})
|
||||||
|
|
||||||
|
(def ^:static +shape-position-schema+
|
||||||
|
{:x [sc/integer]
|
||||||
|
:y [sc/integer]})
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Events (explicit)
|
;; Events (explicit)
|
||||||
|
@ -194,13 +204,14 @@
|
||||||
(let [shape (get-in state [:shapes-by-id sid])]
|
(let [shape (get-in state [:shapes-by-id sid])]
|
||||||
(update-in state [:shapes-by-id sid] sh/-move delta)))))
|
(update-in state [:shapes-by-id sid] sh/-move delta)))))
|
||||||
|
|
||||||
(defn update-line
|
(defn update-line-attrs
|
||||||
[sid props]
|
[sid {:keys [x1 y1 x2 y2] :as opts}]
|
||||||
|
(sc/validate! +shape-line-attrs-schema+ opts)
|
||||||
(reify
|
(reify
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
(let [shape (get-in state [:shapes-by-id sid])
|
(let [shape (get-in state [:shapes-by-id sid])
|
||||||
props (select-keys props [:x1 :y1 :x2 :y2])
|
props (select-keys opts [:x1 :y1 :x2 :y2])
|
||||||
props' (select-keys shape [:x1 :y1 :x2 :y2])]
|
props' (select-keys shape [:x1 :y1 :x2 :y2])]
|
||||||
(update-in state [:shapes-by-id sid] sh/-initialize
|
(update-in state [:shapes-by-id sid] sh/-initialize
|
||||||
(merge props' props))))))
|
(merge props' props))))))
|
||||||
|
@ -224,7 +235,7 @@
|
||||||
WARN: only works with shapes that works
|
WARN: only works with shapes that works
|
||||||
with height and width such are"
|
with height and width such are"
|
||||||
[sid {:keys [width height] :as opts}]
|
[sid {:keys [width height] :as opts}]
|
||||||
(sc/validate! +shape-update-size-schema+ opts)
|
(sc/validate! +shape-size-schema+ opts)
|
||||||
(reify
|
(reify
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
|
@ -234,17 +245,15 @@
|
||||||
(defn update-position
|
(defn update-position
|
||||||
"Update the start position coordenate of the shape."
|
"Update the start position coordenate of the shape."
|
||||||
[sid {:keys [x y] :as opts}]
|
[sid {:keys [x y] :as opts}]
|
||||||
(sc/validate! +shape-update-position-schema+ opts)
|
(sc/validate! +shape-position-schema+ opts)
|
||||||
(reify
|
(reify
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
(update-in state [:shapes-by-id sid] sh/-move' [x y]))))
|
(update-in state [:shapes-by-id sid] sh/-move' [x y]))))
|
||||||
|
|
||||||
;; TODO: rename fill to "color" for consistency.
|
|
||||||
|
|
||||||
(defn update-fill-attrs
|
(defn update-fill-attrs
|
||||||
[sid {:keys [color opacity] :as opts}]
|
[sid {:keys [color opacity] :as opts}]
|
||||||
(sc/validate! +shape-update-fill-schema+ opts)
|
(sc/validate! +shape-fill-attrs-schema+ opts)
|
||||||
(reify
|
(reify
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
|
@ -254,8 +263,8 @@
|
||||||
(when opacity {:opacity opacity})))))
|
(when opacity {:opacity opacity})))))
|
||||||
|
|
||||||
(defn update-stroke-attrs
|
(defn update-stroke-attrs
|
||||||
[sid {:keys [color opacity width type] :as opts}]
|
[sid {:keys [color opacity type width] :as opts}]
|
||||||
(sc/validate! +shape-update-stroke-schema+ opts)
|
(sc/validate! +shape-stroke-attrs-schema+ opts)
|
||||||
(reify
|
(reify
|
||||||
rs/UpdateEvent
|
rs/UpdateEvent
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
|
@ -266,6 +275,17 @@
|
||||||
(when color {:stroke color})
|
(when color {:stroke color})
|
||||||
(when opacity {:stroke-opacity opacity})))))
|
(when opacity {:stroke-opacity opacity})))))
|
||||||
|
|
||||||
|
(defn update-radius-attrs
|
||||||
|
[sid {:keys [rx ry] :as opts}]
|
||||||
|
(sc/validate! +shape-radius-attrs-schema+ opts)
|
||||||
|
(reify
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(update-in state [:shapes-by-id sid]
|
||||||
|
merge
|
||||||
|
(when rx {:rx rx})
|
||||||
|
(when ry {:ry ry})))))
|
||||||
|
|
||||||
(defn hide-shape
|
(defn hide-shape
|
||||||
[sid]
|
[sid]
|
||||||
(reify
|
(reify
|
||||||
|
@ -455,7 +475,7 @@
|
||||||
"Update the fill related attributed on
|
"Update the fill related attributed on
|
||||||
selected shapes."
|
selected shapes."
|
||||||
[opts]
|
[opts]
|
||||||
(sc/validate! +shape-update-fill-schema+ opts)
|
(sc/validate! +shape-fill-attrs-schema+ opts)
|
||||||
(reify
|
(reify
|
||||||
rs/WatchEvent
|
rs/WatchEvent
|
||||||
(-apply-watch [_ state]
|
(-apply-watch [_ state]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
(ns uxbox.schema
|
(ns uxbox.schema
|
||||||
(:refer-clojure :exclude [keyword uuid vector])
|
(:refer-clojure :exclude [keyword uuid vector boolean])
|
||||||
(:require [bouncer.core :as b]
|
(:require [bouncer.core :as b]
|
||||||
[bouncer.validators :as v]
|
[bouncer.validators :as v]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
@ -49,6 +49,8 @@
|
||||||
|
|
||||||
(def required v/required)
|
(def required v/required)
|
||||||
(def number v/number)
|
(def number v/number)
|
||||||
|
(def integer v/integer)
|
||||||
|
(def boolean v/boolean)
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Public Api
|
;; Public Api
|
||||||
|
|
|
@ -196,11 +196,8 @@
|
||||||
|
|
||||||
(defmethod -move' :builtin/circle
|
(defmethod -move' :builtin/circle
|
||||||
[shape [x y]]
|
[shape [x y]]
|
||||||
(let [{:keys [cx cy rx ry]} shape
|
(let [dx (if x (- (:cx shape) x) 0)
|
||||||
x1 (- cx rx)
|
dy (if y (- (:cy shape) y) 0)]
|
||||||
y1 (- cy ry)
|
|
||||||
dx (if x (- (:x1 shape) x) 0)
|
|
||||||
dy (if y (- (:y1 shape) y) 0)]
|
|
||||||
(-move shape [dx dy])))
|
(-move shape [dx dy])))
|
||||||
|
|
||||||
(defmethod -move' :default
|
(defmethod -move' :default
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(def ^:static ^:private +style-attrs+
|
(def ^:static ^:private +style-attrs+
|
||||||
#{:fill :opacity :stroke :stroke-opacity :stroke-width :stroke-type})
|
#{:fill :opacity :stroke :stroke-opacity :stroke-width :stroke-type :rx :ry})
|
||||||
|
|
||||||
(defn- transform-stroke-type
|
(defn- transform-stroke-type
|
||||||
[attrs]
|
[attrs]
|
||||||
|
|
|
@ -18,14 +18,18 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(def ^:static ^:private +menus-map+
|
(def ^:static ^:private +menus-map+
|
||||||
{:builtin/icon [:menu/rect-measures :menu/fill :menu/stroke]
|
{:builtin/icon [:menu/icon-measures :menu/fill :menu/stroke]
|
||||||
:builtin/rect [:menu/rect-measures :menu/fill :menu/stroke]
|
:builtin/rect [:menu/rect-measures :menu/fill :menu/stroke]
|
||||||
:builtin/line [:menu/line-measures :menu/stroke]
|
:builtin/line [:menu/line-measures :menu/stroke]
|
||||||
:builtin/circle [:menu/circle-measures :menu/fill :menu/stroke]
|
:builtin/circle [:menu/circle-measures :menu/fill :menu/stroke]
|
||||||
:builtin/group []})
|
:builtin/group []})
|
||||||
|
|
||||||
(def ^:static ^:private +menus-by-id+
|
(def ^:static ^:private +menus-by-id+
|
||||||
{:menu/rect-measures
|
{:menu/icon-measures
|
||||||
|
{:name "Size, position & rotation"
|
||||||
|
:icon i/infocard}
|
||||||
|
|
||||||
|
:menu/rect-measures
|
||||||
{:name "Size, position & rotation"
|
{:name "Size, position & rotation"
|
||||||
:icon i/infocard}
|
:icon i/infocard}
|
||||||
|
|
||||||
|
@ -192,7 +196,12 @@
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
props {attr value}]
|
||||||
(rs/emit! (dw/update-position sid props))))
|
(rs/emit! (dw/update-position sid props))))
|
||||||
(on-border-change [attr event])]
|
(on-border-change [attr event]
|
||||||
|
(let [value (dom/event->value event)
|
||||||
|
value (parse-int value nil)
|
||||||
|
sid (:id shape)
|
||||||
|
props {attr value}]
|
||||||
|
(rs/emit! (dw/update-radius-attrs sid props))))]
|
||||||
(html
|
(html
|
||||||
[:div.element-set {:key (str (:id menu))}
|
[:div.element-set {:key (str (:id menu))}
|
||||||
[:div.element-set-title (:name menu)]
|
[:div.element-set-title (:name menu)]
|
||||||
|
@ -263,6 +272,83 @@
|
||||||
]]]
|
]]]
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
|
||||||
|
(defmethod -render-menu :menu/icon-measures
|
||||||
|
[menu own shape]
|
||||||
|
(letfn [(on-size-change [attr event]
|
||||||
|
(let [value (dom/event->value event)
|
||||||
|
value (parse-int value 0)
|
||||||
|
sid (:id shape)
|
||||||
|
props {attr value}]
|
||||||
|
(rs/emit! (dw/update-size sid props))))
|
||||||
|
(on-rotation-change [event]
|
||||||
|
(let [value (dom/event->value event)
|
||||||
|
value (parse-int value 0)
|
||||||
|
sid (:id shape)]
|
||||||
|
(rs/emit! (dw/update-rotation sid value))))
|
||||||
|
(on-pos-change [attr event]
|
||||||
|
(let [value (dom/event->value event)
|
||||||
|
value (parse-int value nil)
|
||||||
|
sid (:id shape)
|
||||||
|
props {attr value}]
|
||||||
|
(rs/emit! (dw/update-position sid props))))]
|
||||||
|
(html
|
||||||
|
[:div.element-set {:key (str (:id menu))}
|
||||||
|
[:div.element-set-title (:name menu)]
|
||||||
|
[:div.element-set-content
|
||||||
|
;; SLIDEBAR FOR ROTATION AND OPACITY
|
||||||
|
[:span "Size"]
|
||||||
|
[:div.row-flex
|
||||||
|
[:input#width.input-text
|
||||||
|
{:placeholder "Width"
|
||||||
|
:type "number"
|
||||||
|
:min "0"
|
||||||
|
:value (:width shape)
|
||||||
|
:on-change (partial on-size-change :width)}]
|
||||||
|
[:div.lock-size i/lock]
|
||||||
|
[:input#width.input-text
|
||||||
|
{:placeholder "Height"
|
||||||
|
:type "number"
|
||||||
|
:min "0"
|
||||||
|
:value (:height shape)
|
||||||
|
:on-change (partial on-size-change :height)}]]
|
||||||
|
|
||||||
|
[:span "Position"]
|
||||||
|
[:div.row-flex
|
||||||
|
[:input#width.input-text
|
||||||
|
{:placeholder "x"
|
||||||
|
:type "number"
|
||||||
|
:value (:x shape "")
|
||||||
|
:on-change (partial on-pos-change :x)}]
|
||||||
|
[:input#width.input-text
|
||||||
|
{:placeholder "y"
|
||||||
|
:type "number"
|
||||||
|
:value (:y shape "")
|
||||||
|
:on-change (partial on-pos-change :y)}]]
|
||||||
|
|
||||||
|
[:span "Rotation"]
|
||||||
|
[:div.row-flex
|
||||||
|
[:input.slidebar
|
||||||
|
{:type "range"
|
||||||
|
:min 0
|
||||||
|
:max 360
|
||||||
|
:value (:rotation shape 0)
|
||||||
|
:on-change on-rotation-change}]]
|
||||||
|
|
||||||
|
[:div.row-flex
|
||||||
|
[:input#width.input-text
|
||||||
|
{:placeholder ""
|
||||||
|
:type "number"
|
||||||
|
:min 0
|
||||||
|
:max 360
|
||||||
|
:value (:rotation shape "0")
|
||||||
|
:on-change on-rotation-change
|
||||||
|
}]
|
||||||
|
[:input.input-text
|
||||||
|
{:style {:visibility "hidden"}}]
|
||||||
|
]]]
|
||||||
|
)))
|
||||||
|
|
||||||
(defmethod -render-menu :menu/circle-measures
|
(defmethod -render-menu :menu/circle-measures
|
||||||
[menu own shape]
|
[menu own shape]
|
||||||
(letfn [(on-size-change [attr event]
|
(letfn [(on-size-change [attr event]
|
||||||
|
@ -270,18 +356,18 @@
|
||||||
value (parse-int value 0)
|
value (parse-int value 0)
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
props {attr value}]
|
||||||
#_(rs/emit! (dw/update-size sid props))))
|
(rs/emit! (dw/update-radius-attrs sid props))))
|
||||||
(on-rotation-change [event]
|
(on-rotation-change [event]
|
||||||
(let [value (dom/event->value event)
|
(let [value (dom/event->value event)
|
||||||
value (parse-int value 0)
|
value (parse-int value 0)
|
||||||
sid (:id shape)]
|
sid (:id shape)]
|
||||||
#_(rs/emit! (dw/update-rotation sid value))))
|
(rs/emit! (dw/update-rotation sid value))))
|
||||||
(on-pos-change [attr event]
|
(on-pos-change [attr event]
|
||||||
(let [value (dom/event->value event)
|
(let [value (dom/event->value event)
|
||||||
value (parse-int value nil)
|
value (parse-int value nil)
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
props {attr value}]
|
||||||
#_(rs/emit! (dw/update-position sid props))))]
|
(rs/emit! (dw/update-position sid props))))]
|
||||||
(html
|
(html
|
||||||
[:div.element-set {:key (str (:id menu))}
|
[:div.element-set {:key (str (:id menu))}
|
||||||
[:div.element-set-title (:name menu)]
|
[:div.element-set-title (:name menu)]
|
||||||
|
@ -309,12 +395,12 @@
|
||||||
{:placeholder "cx"
|
{:placeholder "cx"
|
||||||
:type "number"
|
:type "number"
|
||||||
:value (:cx shape "")
|
:value (:cx shape "")
|
||||||
:on-change (partial on-pos-change :cx)}]
|
:on-change (partial on-pos-change :x)}]
|
||||||
[:input#width.input-text
|
[:input#width.input-text
|
||||||
{:placeholder "cy"
|
{:placeholder "cy"
|
||||||
:type "number"
|
:type "number"
|
||||||
:value (:cy shape "")
|
:value (:cy shape "")
|
||||||
:on-change (partial on-pos-change :cy)}]]
|
:on-change (partial on-pos-change :y)}]]
|
||||||
|
|
||||||
[:span "Rotation"]
|
[:span "Rotation"]
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
|
@ -351,7 +437,7 @@
|
||||||
value (parse-int value nil)
|
value (parse-int value nil)
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
props {attr value}]
|
||||||
(rs/emit! (dw/update-line sid props))))]
|
(rs/emit! (dw/update-line-attrs sid props))))]
|
||||||
(html
|
(html
|
||||||
[:div.element-set {:key (str (:id menu))}
|
[:div.element-set {:key (str (:id menu))}
|
||||||
[:div.element-set-title (:name menu)]
|
[:div.element-set-title (:name menu)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue