mirror of
https://github.com/penpot/penpot.git
synced 2025-02-18 21:06:11 -05:00
✨ Adds rects, ellipses and uses to svg elements
This commit is contained in:
parent
0f7596bacf
commit
237ef2a205
8 changed files with 215 additions and 116 deletions
|
@ -578,36 +578,39 @@
|
||||||
[frame-id parent-id (inc index)])))))
|
[frame-id parent-id (inc index)])))))
|
||||||
|
|
||||||
(defn add-shape-changes
|
(defn add-shape-changes
|
||||||
[page-id objects selected attrs]
|
([page-id objects selected attrs]
|
||||||
(let [id (:id attrs)
|
(add-shape-changes page-id objects selected attrs true))
|
||||||
shape (gpr/setup-proportions attrs)
|
([page-id objects selected attrs reg-object?]
|
||||||
|
(let [id (:id attrs)
|
||||||
|
shape (gpr/setup-proportions attrs)
|
||||||
|
|
||||||
default-attrs (if (= :frame (:type shape))
|
default-attrs (if (= :frame (:type shape))
|
||||||
cp/default-frame-attrs
|
cp/default-frame-attrs
|
||||||
cp/default-shape-attrs)
|
cp/default-shape-attrs)
|
||||||
|
|
||||||
shape (merge default-attrs shape)
|
shape (merge default-attrs shape)
|
||||||
|
|
||||||
not-frame? #(not (= :frame (get-in objects [% :type])))
|
not-frame? #(not (= :frame (get-in objects [% :type])))
|
||||||
selected (into #{} (filter not-frame?) selected)
|
selected (into #{} (filter not-frame?) selected)
|
||||||
|
|
||||||
[frame-id parent-id index] (get-shape-layer-position objects selected attrs)
|
[frame-id parent-id index] (get-shape-layer-position objects selected attrs)
|
||||||
|
|
||||||
redo-changes [{:type :add-obj
|
redo-changes (cond-> [{:type :add-obj
|
||||||
:id id
|
:id id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:frame-id frame-id
|
:frame-id frame-id
|
||||||
:parent-id parent-id
|
:parent-id parent-id
|
||||||
:index index
|
:index index
|
||||||
:obj shape}
|
:obj shape}]
|
||||||
{:type :reg-objects
|
reg-object?
|
||||||
:page-id page-id
|
(conj {:type :reg-objects
|
||||||
:shapes [id]}]
|
:page-id page-id
|
||||||
undo-changes [{:type :del-obj
|
:shapes [id]}))
|
||||||
:page-id page-id
|
undo-changes [{:type :del-obj
|
||||||
:id id}]]
|
:page-id page-id
|
||||||
|
:id id}]]
|
||||||
|
|
||||||
[redo-changes undo-changes]))
|
[redo-changes undo-changes])))
|
||||||
|
|
||||||
(defn add-shape
|
(defn add-shape
|
||||||
[attrs]
|
[attrs]
|
||||||
|
|
|
@ -28,10 +28,9 @@
|
||||||
(let [width (get-in data [:attrs :width] 100)
|
(let [width (get-in data [:attrs :width] 100)
|
||||||
height (get-in data [:attrs :height] 100)
|
height (get-in data [:attrs :height] 100)
|
||||||
viewbox (get-in data [:attrs :viewBox] (str "0 0 " width " " height))
|
viewbox (get-in data [:attrs :viewBox] (str "0 0 " width " " height))
|
||||||
[_ _ width-str height-str] (str/split viewbox " ")
|
[x y width height] (->> (str/split viewbox " ")
|
||||||
width (d/parse-integer width-str)
|
(map d/parse-double))]
|
||||||
height (d/parse-integer height-str)]
|
[x y width height]))
|
||||||
[width height]))
|
|
||||||
|
|
||||||
(defn tag->name
|
(defn tag->name
|
||||||
"Given a tag returns its layer name"
|
"Given a tag returns its layer name"
|
||||||
|
@ -61,15 +60,10 @@
|
||||||
(d/parse-double))))
|
(d/parse-double))))
|
||||||
|
|
||||||
(get-in shape [:svg-attrs :style :fill-opacity])
|
(get-in shape [:svg-attrs :style :fill-opacity])
|
||||||
(-> (update :svg-attrs dissoc :fill-opacity)
|
(-> (update-in [:svg-attrs :style] dissoc :fill-opacity)
|
||||||
(assoc :fill-opacity (-> (get-in shape [:svg-attrs :style :fill-opacity])
|
(assoc :fill-opacity (-> (get-in shape [:svg-attrs :style :fill-opacity])
|
||||||
(d/parse-double))))))
|
(d/parse-double))))))
|
||||||
|
|
||||||
(defonce default-stroke {:stroke-color "#000000"
|
|
||||||
:stroke-opacity 1
|
|
||||||
:stroke-alignment :center
|
|
||||||
:stroke-style :svg})
|
|
||||||
|
|
||||||
(defn setup-stroke [shape]
|
(defn setup-stroke [shape]
|
||||||
(let [shape
|
(let [shape
|
||||||
(cond-> shape
|
(cond-> shape
|
||||||
|
@ -90,9 +84,8 @@
|
||||||
(-> (update-in [:svg-attrs :style] dissoc :stroke-width)
|
(-> (update-in [:svg-attrs :style] dissoc :stroke-width)
|
||||||
(assoc :stroke-width (-> (get-in shape [:svg-attrs :style :stroke-width])
|
(assoc :stroke-width (-> (get-in shape [:svg-attrs :style :stroke-width])
|
||||||
(d/parse-double)))))]
|
(d/parse-double)))))]
|
||||||
shape
|
(if (d/any-key? shape :stroke-color :stroke-opacity :stroke-width)
|
||||||
#_(if (d/any-key? shape :stroke-color :stroke-opacity :stroke-width)
|
(merge {:stroke-style :svg} shape)
|
||||||
(merge default-stroke shape)
|
|
||||||
shape)))
|
shape)))
|
||||||
|
|
||||||
(defn create-raw-svg [name frame-id svg-data {:keys [attrs] :as data}]
|
(defn create-raw-svg [name frame-id svg-data {:keys [attrs] :as data}]
|
||||||
|
@ -112,27 +105,39 @@
|
||||||
(gsh/setup-selrect))))
|
(gsh/setup-selrect))))
|
||||||
|
|
||||||
(defn create-svg-root [frame-id svg-data]
|
(defn create-svg-root [frame-id svg-data]
|
||||||
(let [{:keys [name x y width height]} svg-data]
|
(let [{:keys [name x y width height offset-x offset-y]} svg-data]
|
||||||
(-> {:id (uuid/next)
|
(-> {:id (uuid/next)
|
||||||
:type :group
|
:type :group
|
||||||
:name name
|
:name name
|
||||||
:frame-id frame-id
|
:frame-id frame-id
|
||||||
:width width
|
:width width
|
||||||
:height height
|
:height height
|
||||||
:x x
|
:x (+ x offset-x)
|
||||||
:y y}
|
:y (+ y offset-y)}
|
||||||
(gsh/setup-selrect)
|
(gsh/setup-selrect)
|
||||||
(assoc :svg-attrs (-> (:attrs svg-data)
|
(assoc :svg-attrs (-> (:attrs svg-data)
|
||||||
(dissoc :viewBox :xmlns))))))
|
(dissoc :viewBox :xmlns))))))
|
||||||
|
|
||||||
|
(defn create-group [name frame-id svg-data {:keys [attrs]}]
|
||||||
|
(let [{:keys [x y width height offset-x offset-y]} svg-data]
|
||||||
|
(-> {:id (uuid/next)
|
||||||
|
:type :group
|
||||||
|
:name name
|
||||||
|
:frame-id frame-id
|
||||||
|
:x (+ x offset-x)
|
||||||
|
:y (+ y offset-y)
|
||||||
|
:width width
|
||||||
|
:height height}
|
||||||
|
(assoc :svg-attrs (dissoc attrs :transform))
|
||||||
|
(assoc :svg-viewbox (select-keys svg-data [:x :y :width :height]))
|
||||||
|
(gsh/setup-selrect))))
|
||||||
|
|
||||||
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
||||||
(let [svg-transform (usvg/parse-transform (:transform attrs))
|
(let [svg-transform (usvg/parse-transform (:transform attrs))
|
||||||
content (cond-> (ugp/path->content (:d attrs))
|
content (cond-> (ugp/path->content (:d attrs))
|
||||||
svg-transform
|
svg-transform
|
||||||
(gsh/transform-content svg-transform))
|
(gsh/transform-content svg-transform))
|
||||||
|
|
||||||
;; attrs (d/update-when attrs :transform #(-> (usvg/parse-transform %) str))
|
|
||||||
|
|
||||||
selrect (gsh/content->selrect content)
|
selrect (gsh/content->selrect content)
|
||||||
points (gsh/rect->points selrect)
|
points (gsh/rect->points selrect)
|
||||||
|
|
||||||
|
@ -149,7 +154,6 @@
|
||||||
(assoc :svg-transform svg-transform)
|
(assoc :svg-transform svg-transform)
|
||||||
(gsh/translate-to-frame origin))))
|
(gsh/translate-to-frame origin))))
|
||||||
|
|
||||||
|
|
||||||
(defn inverse-matrix [{:keys [a b c d e f]}]
|
(defn inverse-matrix [{:keys [a b c d e f]}]
|
||||||
(let [dom-matrix (-> (js/DOMMatrix.)
|
(let [dom-matrix (-> (js/DOMMatrix.)
|
||||||
(obj/set! "a" a)
|
(obj/set! "a" a)
|
||||||
|
@ -212,51 +216,108 @@
|
||||||
:name name
|
:name name
|
||||||
:frame-id frame-id}
|
:frame-id frame-id}
|
||||||
(cond->
|
(cond->
|
||||||
(contains? attrs :rx) (:rx attrs)
|
(contains? attrs :rx) (assoc :rx (d/parse-double (:rx attrs)))
|
||||||
(contains? attrs :rx) (:rx attrs))
|
(contains? attrs :ry) (assoc :ry (d/parse-double (:ry attrs))))
|
||||||
|
|
||||||
(merge metadata)
|
(merge metadata)
|
||||||
(assoc :svg-transform transform)
|
(assoc :svg-transform transform)
|
||||||
(assoc :svg-viewbox (select-keys rect [:x :y :width :height]))
|
(assoc :svg-viewbox (select-keys rect [:x :y :width :height]))
|
||||||
(assoc :svg-attrs (dissoc attrs :x :y :width :height :rx :ry :transform)))))
|
(assoc :svg-attrs (dissoc attrs :x :y :width :height :rx :ry :transform)))))
|
||||||
|
|
||||||
(defn create-group [name frame-id svg-data {:keys [attrs]}]
|
(def default-circle {:r 0 :cx 0 :cy 0})
|
||||||
(let [{:keys [x y width height]} svg-data]
|
|
||||||
|
(defn create-circle-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
||||||
|
(let [svg-transform (usvg/parse-transform (:transform attrs))
|
||||||
|
transform (->> svg-transform
|
||||||
|
(gmt/transform-in (gpt/point svg-data)))
|
||||||
|
|
||||||
|
circle (->> (select-keys attrs [:r :ry :rx :cx :cy])
|
||||||
|
(d/mapm #(d/parse-double %2)))
|
||||||
|
|
||||||
|
{:keys [cx cy]} circle
|
||||||
|
|
||||||
|
rx (or (:r circle) (:rx circle))
|
||||||
|
ry (or (:r circle) (:ry circle))
|
||||||
|
|
||||||
|
rect {:x (- cx rx)
|
||||||
|
:y (- cy ry)
|
||||||
|
:width (* 2 rx)
|
||||||
|
:height (* 2 ry)}
|
||||||
|
|
||||||
|
origin (gpt/negate (gpt/point svg-data))
|
||||||
|
|
||||||
|
rect-data (-> rect
|
||||||
|
(update :x - (:x origin))
|
||||||
|
(update :y - (:y origin)))
|
||||||
|
|
||||||
|
metadata (calculate-rect-metadata rect-data transform)]
|
||||||
(-> {:id (uuid/next)
|
(-> {:id (uuid/next)
|
||||||
:type :group
|
:type :circle
|
||||||
:name name
|
:name name
|
||||||
:frame-id frame-id
|
:frame-id frame-id}
|
||||||
:x x
|
|
||||||
:y y
|
(merge metadata)
|
||||||
:width width
|
(assoc :svg-transform transform)
|
||||||
:height height}
|
(assoc :svg-viewbox (select-keys rect [:x :y :width :height]))
|
||||||
(assoc :svg-attrs attrs)
|
(assoc :svg-attrs (dissoc attrs :cx :cy :r :rx :ry :transform)))))
|
||||||
(assoc :svg-viewbox (select-keys svg-data [0 0 :width :height]))
|
|
||||||
(gsh/setup-selrect))))
|
(defn add-transform [transform node]
|
||||||
|
(letfn [(append-transform [old-transform]
|
||||||
|
(if (or (nil? old-transform) (empty? old-transform))
|
||||||
|
transform
|
||||||
|
(str old-transform " " transform)))]
|
||||||
|
|
||||||
|
(cond-> node
|
||||||
|
transform
|
||||||
|
(update-in [:attrs :transform] append-transform))))
|
||||||
|
|
||||||
(defn parse-svg-element [frame-id svg-data element-data unames]
|
(defn parse-svg-element [frame-id svg-data element-data unames]
|
||||||
(let [{:keys [tag attrs]} element-data
|
(let [{:keys [tag attrs]} element-data
|
||||||
|
attrs (cond-> attrs (contains? attrs :style) usvg/format-styles)
|
||||||
|
element-data (cond-> element-data (map? element-data) (assoc :attrs attrs))
|
||||||
name (dwc/generate-unique-name unames (or (:id attrs) (tag->name tag)) true)
|
name (dwc/generate-unique-name unames (or (:id attrs) (tag->name tag)) true)
|
||||||
att-refs (usvg/find-attr-references attrs)
|
att-refs (usvg/find-attr-references attrs)
|
||||||
references (usvg/find-def-references (:defs svg-data) att-refs)]
|
references (usvg/find-def-references (:defs svg-data) att-refs)
|
||||||
|
|
||||||
;; SVG graphic elements
|
href-id (-> (or (:href attrs) (:xlink:href attrs) "")
|
||||||
;; :circle :ellipse :image :line :path :polygon :polyline :rect :text :use
|
(subs 1))
|
||||||
(-> (case tag
|
defs (:defs svg-data)
|
||||||
:g (create-group name frame-id svg-data element-data)
|
|
||||||
:rect (create-rect-shape name frame-id svg-data element-data)
|
|
||||||
:path (create-path-shape name frame-id svg-data element-data)
|
|
||||||
#_other (create-raw-svg name frame-id svg-data element-data))
|
|
||||||
|
|
||||||
(assoc :svg-defs (select-keys (:defs svg-data) references))
|
use-tag? (and (= :use tag) (contains? defs href-id))]
|
||||||
(setup-fill)
|
|
||||||
(setup-stroke))))
|
|
||||||
|
|
||||||
(defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data ids-mappings result [index data]]
|
(if use-tag?
|
||||||
(let [[unames [rchs uchs]] result
|
(let [use-data (get defs href-id)
|
||||||
shape (parse-svg-element frame-id svg-data data unames)
|
translate (gpt/point (:x attrs 0) (:y attrs 0))
|
||||||
|
attrs' (dissoc attrs :x :y :width :height :href :xlink:href)
|
||||||
|
;; TODO: If the child is a symbol we've to take the width/height into account
|
||||||
|
use-data (update use-data :attrs #(d/deep-merge attrs' %))
|
||||||
|
[shape children] (parse-svg-element frame-id svg-data use-data unames)]
|
||||||
|
[(-> shape (gsh/move translate)) children])
|
||||||
|
|
||||||
|
;; SVG graphic elements
|
||||||
|
;; :circle :ellipse :image :line :path :polygon :polyline :rect :text :use
|
||||||
|
(let [shape (-> (case tag
|
||||||
|
(:g :a) (create-group name frame-id svg-data element-data)
|
||||||
|
:rect (create-rect-shape name frame-id svg-data element-data)
|
||||||
|
(:circle
|
||||||
|
:ellipse) (create-circle-shape name frame-id svg-data element-data)
|
||||||
|
:path (create-path-shape name frame-id svg-data element-data)
|
||||||
|
#_other (create-raw-svg name frame-id svg-data element-data))
|
||||||
|
|
||||||
|
(assoc :svg-defs (select-keys (:defs svg-data) references))
|
||||||
|
(setup-fill)
|
||||||
|
(setup-stroke))
|
||||||
|
|
||||||
|
children (cond->> (:content element-data)
|
||||||
|
(= tag :g)
|
||||||
|
(mapv #(add-transform (:transform attrs) %)))]
|
||||||
|
[shape children]))))
|
||||||
|
|
||||||
|
(defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data [unames [rchs uchs]] [index data]]
|
||||||
|
(let [[shape children] (parse-svg-element frame-id svg-data data unames)
|
||||||
shape-id (:id shape)
|
shape-id (:id shape)
|
||||||
[rch1 uch1] (dwc/add-shape-changes page-id objects selected shape)
|
|
||||||
|
[rch1 uch1] (dwc/add-shape-changes page-id objects selected shape false)
|
||||||
|
|
||||||
;; Mov-objects won't have undo because we "delete" the object in the undo of the
|
;; Mov-objects won't have undo because we "delete" the object in the undo of the
|
||||||
;; previous operation
|
;; previous operation
|
||||||
|
@ -270,8 +331,8 @@
|
||||||
;; Careful! the undo changes are concatenated reversed (we undo in reverse order
|
;; Careful! the undo changes are concatenated reversed (we undo in reverse order
|
||||||
changes [(d/concat rchs rch1 rch2) (d/concat uch1 uchs)]
|
changes [(d/concat rchs rch1 rch2) (d/concat uch1 uchs)]
|
||||||
unames (conj unames (:name shape))
|
unames (conj unames (:name shape))
|
||||||
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id shape-id svg-data ids-mappings)]
|
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id shape-id svg-data)]
|
||||||
(reduce reducer-fn [unames changes] (d/enumerate (:content data)))))
|
(reduce reducer-fn [unames changes] (d/enumerate children))))
|
||||||
|
|
||||||
(defn svg-uploaded [svg-data x y]
|
(defn svg-uploaded [svg-data x y]
|
||||||
(ptk/reify ::svg-uploaded
|
(ptk/reify ::svg-uploaded
|
||||||
|
@ -283,21 +344,22 @@
|
||||||
frame-id (cp/frame-id-by-position objects {:x x :y y})
|
frame-id (cp/frame-id-by-position objects {:x x :y y})
|
||||||
selected (get-in state [:workspace-local :selected])
|
selected (get-in state [:workspace-local :selected])
|
||||||
|
|
||||||
[width height] (svg-dimensions svg-data)
|
[vb-x vb-y vb-width vb-height] (svg-dimensions svg-data)
|
||||||
x (- x (/ width 2))
|
x (- x vb-x (/ vb-width 2))
|
||||||
y (- y (/ height 2))
|
y (- y vb-y (/ vb-height 2))
|
||||||
|
|
||||||
unames (dwc/retrieve-used-names objects)
|
unames (dwc/retrieve-used-names objects)
|
||||||
|
|
||||||
svg-name (->> (str/replace (:name svg-data) ".svg" "")
|
svg-name (->> (str/replace (:name svg-data) ".svg" "")
|
||||||
(dwc/generate-unique-name unames))
|
(dwc/generate-unique-name unames))
|
||||||
|
|
||||||
ids-mappings (usvg/generate-id-mapping svg-data)
|
|
||||||
svg-data (-> svg-data
|
svg-data (-> svg-data
|
||||||
(assoc :x x
|
(assoc :x x
|
||||||
:y y
|
:y y
|
||||||
:width width
|
:offset-x vb-x
|
||||||
:height height
|
:offset-y vb-y
|
||||||
|
:width vb-width
|
||||||
|
:height vb-height
|
||||||
:name svg-name))
|
:name svg-name))
|
||||||
|
|
||||||
[def-nodes svg-data] (usvg/extract-defs svg-data)
|
[def-nodes svg-data] (usvg/extract-defs svg-data)
|
||||||
|
@ -308,11 +370,17 @@
|
||||||
|
|
||||||
changes (dwc/add-shape-changes page-id objects selected root-shape)
|
changes (dwc/add-shape-changes page-id objects selected root-shape)
|
||||||
|
|
||||||
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data ids-mappings)
|
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data)
|
||||||
[_ [rchanges uchanges]] (reduce reducer-fn [unames changes] (d/enumerate (:content svg-data)))]
|
[_ [rchanges uchanges]] (reduce reducer-fn [unames changes] (d/enumerate (:content svg-data)))
|
||||||
|
|
||||||
|
reg-objects-action {:type :reg-objects
|
||||||
|
:page-id page-id
|
||||||
|
:shapes (->> rchanges (map :id) (remove nil?) (into #{root-id}) vec)}
|
||||||
|
|
||||||
|
rchanges (conj rchanges reg-objects-action)]
|
||||||
|
|
||||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||||
(dwc/select-shapes (d/ordered-set root-id))))
|
(dwc/select-shapes (d/ordered-set root-id))))
|
||||||
|
|
||||||
(catch :default e
|
(catch :default e
|
||||||
(.error js/console e))
|
(.error js/console "Error upload" e))))))
|
||||||
))))
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
;; This is a list of svg tags that can be grouped in shape-container
|
;; This is a list of svg tags that can be grouped in shape-container
|
||||||
;; this allows them to have gradients, shadows and masks
|
;; this allows them to have gradients, shadows and masks
|
||||||
(def svg-elements #{:svg :circle :ellipse :image :line :path :polygon :polyline :rect :symbol :text :textPath})
|
(def svg-elements #{:svg :circle :ellipse :image :line :path :polygon :polyline :rect :symbol :text :textPath :use})
|
||||||
|
|
||||||
(defn svg-raw-wrapper-factory
|
(defn svg-raw-wrapper-factory
|
||||||
[shape-wrapper]
|
[shape-wrapper]
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
[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]]
|
||||||
[app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]]))
|
[app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]]
|
||||||
|
[app.main.ui.workspace.sidebar.options.svg-attrs :refer [svg-attrs-menu]]))
|
||||||
|
|
||||||
(mf/defc options
|
(mf/defc options
|
||||||
[{:keys [shape] :as props}]
|
[{:keys [shape] :as props}]
|
||||||
|
@ -36,4 +37,6 @@
|
||||||
[:& shadow-menu {:ids ids
|
[:& shadow-menu {:ids ids
|
||||||
:values (select-keys shape [:shadow])}]
|
:values (select-keys shape [:shadow])}]
|
||||||
[:& blur-menu {:ids ids
|
[:& blur-menu {:ids ids
|
||||||
:values (select-keys shape [:blur])}]]))
|
:values (select-keys shape [:blur])}]
|
||||||
|
[:& svg-attrs-menu {:ids ids
|
||||||
|
:values (select-keys shape [:svg-attrs])}]]))
|
||||||
|
|
|
@ -38,6 +38,5 @@
|
||||||
:values (select-keys shape [:shadow])}]
|
:values (select-keys shape [:shadow])}]
|
||||||
[:& blur-menu {:ids ids
|
[:& blur-menu {:ids ids
|
||||||
:values (select-keys shape [:blur])}]
|
:values (select-keys shape [:blur])}]
|
||||||
|
|
||||||
[:& svg-attrs-menu {:ids ids
|
[:& svg-attrs-menu {:ids ids
|
||||||
:values (select-keys shape [:svg-attrs])}]]))
|
:values (select-keys shape [:svg-attrs])}]]))
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
[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]]
|
||||||
[app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]]))
|
[app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]]
|
||||||
|
[app.main.ui.workspace.sidebar.options.svg-attrs :refer [svg-attrs-menu]]))
|
||||||
|
|
||||||
(mf/defc options
|
(mf/defc options
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
|
@ -41,4 +42,7 @@
|
||||||
:values (select-keys shape [:shadow])}]
|
:values (select-keys shape [:shadow])}]
|
||||||
|
|
||||||
[:& blur-menu {:ids ids
|
[:& blur-menu {:ids ids
|
||||||
:values (select-keys shape [:blur])}]]))
|
:values (select-keys shape [:blur])}]
|
||||||
|
|
||||||
|
[:& svg-attrs-menu {:ids ids
|
||||||
|
:values (select-keys shape [:svg-attrs])}]]))
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.sidebar.options.svg-attrs
|
(ns app.main.ui.workspace.sidebar.options.svg-attrs
|
||||||
(:require
|
(:require
|
||||||
|
[cuerdas.core :as str]
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -22,13 +23,22 @@
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps attr on-change)
|
(mf/deps attr on-change)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(on-change attr (dom/get-target-val event))))]
|
(on-change attr (dom/get-target-val event))))
|
||||||
|
|
||||||
|
label (->> attr (map name) (str/join "."))]
|
||||||
[:div.element-set-content
|
[:div.element-set-content
|
||||||
[:& input-row {:label (name attr)
|
(if (string? value)
|
||||||
:type :text
|
[:& input-row {:label label
|
||||||
:class "large"
|
:type :text
|
||||||
:value (str value)
|
:class "large"
|
||||||
:on-change handle-change}]]))
|
:value (str value)
|
||||||
|
:on-change handle-change}]
|
||||||
|
|
||||||
|
(for [[key value] value]
|
||||||
|
[:& attribute-value {:key key
|
||||||
|
:attr (conj attr key)
|
||||||
|
:value value
|
||||||
|
:on-change handle-change}]))]))
|
||||||
|
|
||||||
(mf/defc svg-attrs-menu [{:keys [ids type values]}]
|
(mf/defc svg-attrs-menu [{:keys [ids type values]}]
|
||||||
(let [handle-change
|
(let [handle-change
|
||||||
|
@ -36,7 +46,7 @@
|
||||||
(mf/deps ids)
|
(mf/deps ids)
|
||||||
(fn [attr value]
|
(fn [attr value]
|
||||||
(let [update-fn
|
(let [update-fn
|
||||||
(fn [shape] (assoc-in shape [:svg-attrs attr] value))]
|
(fn [shape] (assoc-in shape (concat [:svg-attrs] attr) value))]
|
||||||
|
|
||||||
(st/emit! (dwc/update-shapes ids update-fn)))))]
|
(st/emit! (dwc/update-shapes ids update-fn)))))]
|
||||||
|
|
||||||
|
@ -47,7 +57,6 @@
|
||||||
|
|
||||||
(for [[index [attr-key attr-value]] (d/enumerate (:svg-attrs values))]
|
(for [[index [attr-key attr-value]] (d/enumerate (:svg-attrs values))]
|
||||||
[:& attribute-value {:key attr-key
|
[:& attribute-value {:key attr-key
|
||||||
:ids ids
|
:attr [attr-key]
|
||||||
:attr attr-key
|
|
||||||
:value attr-value
|
:value attr-value
|
||||||
:on-change handle-change}])])))
|
:on-change handle-change}])])))
|
||||||
|
|
|
@ -35,6 +35,22 @@
|
||||||
:else
|
:else
|
||||||
num-str))
|
num-str))
|
||||||
|
|
||||||
|
(defn format-styles
|
||||||
|
"Transforms attributes to their react equivalent"
|
||||||
|
[attrs]
|
||||||
|
(letfn [(format-styles [style-str]
|
||||||
|
(if (string? style-str)
|
||||||
|
(->> (str/split style-str ";")
|
||||||
|
(map str/trim)
|
||||||
|
(map #(str/split % ":"))
|
||||||
|
(group-by first)
|
||||||
|
(map (fn [[key val]]
|
||||||
|
(vector (keyword key) (second (first val)))))
|
||||||
|
(into {}))
|
||||||
|
style-str))]
|
||||||
|
|
||||||
|
(update attrs :style format-styles)))
|
||||||
|
|
||||||
(defn clean-attrs
|
(defn clean-attrs
|
||||||
"Transforms attributes to their react equivalent"
|
"Transforms attributes to their react equivalent"
|
||||||
[attrs]
|
[attrs]
|
||||||
|
@ -60,6 +76,7 @@
|
||||||
(cond
|
(cond
|
||||||
(= key :class) [:className val]
|
(= key :class) [:className val]
|
||||||
(and (= key :style) (string? val)) [key (format-styles val)]
|
(and (= key :style) (string? val)) [key (format-styles val)]
|
||||||
|
(and (= key :style) (map? val)) [key (clean-attrs val)]
|
||||||
:else (vector (transform-key key) val))))]
|
:else (vector (transform-key key) val))))]
|
||||||
|
|
||||||
(->> attrs
|
(->> attrs
|
||||||
|
@ -100,34 +117,30 @@
|
||||||
(reduce visit-node result (:content node))))]
|
(reduce visit-node result (:content node))))]
|
||||||
(visit-node {} content)))
|
(visit-node {} content)))
|
||||||
|
|
||||||
(defn extract-defs [{:keys [tag content] :as node}]
|
(defn extract-defs [{:keys [tag attrs content] :as node}]
|
||||||
|
|
||||||
(if-not (map? node)
|
(if-not (map? node)
|
||||||
[{} node]
|
[{} node]
|
||||||
(letfn [(def-tag? [{:keys [tag]}] (= tag :defs))
|
|
||||||
|
|
||||||
(assoc-node [result node]
|
(let [remove-node? (fn [{:keys [tag]}] (= tag :defs))
|
||||||
(assoc result (-> node :attrs :id) node))
|
|
||||||
|
|
||||||
(node-data [node]
|
rec-result (->> (:content node) (map extract-defs))
|
||||||
(->> (:content node) (reduce assoc-node {})))]
|
node (assoc node :content (->> rec-result (map second) (filterv (comp not remove-node?))))
|
||||||
|
|
||||||
(let [current-def (->> content
|
|
||||||
(filterv def-tag?)
|
|
||||||
(map node-data)
|
|
||||||
(reduce merge))
|
|
||||||
result (->> content
|
|
||||||
(filter (comp not def-tag?))
|
|
||||||
(map extract-defs))
|
|
||||||
|
|
||||||
current-def (->> result (map first) (reduce merge current-def))
|
current-node-defs (if (contains? attrs :id)
|
||||||
content (->> result (mapv second))]
|
(hash-map (:id attrs) node)
|
||||||
|
(hash-map))
|
||||||
|
|
||||||
[current-def (assoc node :content content)]))))
|
node-defs (->> rec-result (map first) (reduce merge current-node-defs))]
|
||||||
|
|
||||||
|
[ node-defs node ])))
|
||||||
|
|
||||||
(defn find-attr-references [attrs]
|
(defn find-attr-references [attrs]
|
||||||
(->> attrs
|
(->> attrs
|
||||||
(mapcat (fn [[_ attr-value]] (extract-ids attr-value)))))
|
(mapcat (fn [[_ attr-value]]
|
||||||
|
(if (string? attr-value)
|
||||||
|
(extract-ids attr-value)
|
||||||
|
(find-attr-references attr-value))))))
|
||||||
|
|
||||||
(defn find-node-references [node]
|
(defn find-node-references [node]
|
||||||
(let [current (->> (find-attr-references (:attrs node)) (into #{}))
|
(let [current (->> (find-attr-references (:attrs node)) (into #{}))
|
||||||
|
|
Loading…
Add table
Reference in a new issue