mirror of
https://github.com/penpot/penpot.git
synced 2025-03-11 23:31:21 -05:00
✨ Handoff for imported SVGS
This commit is contained in:
parent
6f07b4ea80
commit
4da3270d34
13 changed files with 187 additions and 67 deletions
|
@ -6,7 +6,7 @@
|
|||
|
||||
(ns app.common.data
|
||||
"Data manipulation and query helper functions."
|
||||
(:refer-clojure :exclude [concat read-string hash-map merge])
|
||||
(:refer-clojure :exclude [concat read-string hash-map merge name])
|
||||
#?(:cljs
|
||||
(:require-macros [app.common.data]))
|
||||
(:require
|
||||
|
@ -359,7 +359,7 @@
|
|||
;; Code for ClojureScript
|
||||
(let [mdata (aapi/resolve &env v)
|
||||
arglists (second (get-in mdata [:meta :arglists]))
|
||||
sym (symbol (name v))
|
||||
sym (symbol (core/name v))
|
||||
andsym (symbol "&")
|
||||
procarg #(if (= % andsym) % (gensym "param"))]
|
||||
(if (pos? (count arglists))
|
||||
|
@ -391,3 +391,16 @@
|
|||
|
||||
(defn any-key? [element & rest]
|
||||
(some #(contains? element %) rest))
|
||||
|
||||
(defn name
|
||||
"Improved version of name that won't fail if the input is not a keyword"
|
||||
[maybe-keyword]
|
||||
(cond
|
||||
(keyword? maybe-keyword)
|
||||
(core/name maybe-keyword)
|
||||
|
||||
(nil? maybe-keyword) nil
|
||||
|
||||
:else
|
||||
(str maybe-keyword)))
|
||||
|
||||
|
|
|
@ -5512,5 +5512,38 @@
|
|||
"en": "Imported SVG Attributes",
|
||||
"es": "Atributos del SVG Importado"
|
||||
}
|
||||
},
|
||||
|
||||
"handoff.attributes.stroke.alignment.inner" : {
|
||||
"translations" : {
|
||||
"en" : "Inside",
|
||||
"es" : "Interior",
|
||||
"fr" : "Intérieur",
|
||||
"ru" : "Внутрь",
|
||||
"zh_cn" : "内部"
|
||||
},
|
||||
"permanent": true
|
||||
},
|
||||
|
||||
"handoff.attributes.stroke.alignment.outer" : {
|
||||
"translations" : {
|
||||
"en" : "Outside",
|
||||
"es" : "Exterior",
|
||||
"fr" : "Extérieur",
|
||||
"ru" : "Наружу",
|
||||
"zh_cn" : "外部"
|
||||
},
|
||||
"permanent": true
|
||||
},
|
||||
|
||||
"handoff.attributes.stroke.alignment.center" : {
|
||||
"translations" : {
|
||||
"en" : "Center",
|
||||
"es" : "Centro",
|
||||
"fr" : "Centre",
|
||||
"ru" : "Центр",
|
||||
"zh_cn" : "居中"
|
||||
},
|
||||
"permanent": true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,10 @@
|
|||
|
||||
.attributes-label,
|
||||
.attributes-value {
|
||||
margin-right: 0.5rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 50%;
|
||||
}
|
||||
.copy-button {
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
"Given a tag returns its layer name"
|
||||
[tag]
|
||||
(str "svg-" (cond (string? tag) tag
|
||||
(keyword? tag) (name tag)
|
||||
(keyword? tag) (d/name tag)
|
||||
(nil? tag) "node"
|
||||
:else (str tag))))
|
||||
|
||||
|
|
|
@ -19,16 +19,17 @@
|
|||
[app.main.ui.handoff.attributes.shadow :refer [shadow-panel]]
|
||||
[app.main.ui.handoff.attributes.blur :refer [blur-panel]]
|
||||
[app.main.ui.handoff.attributes.image :refer [image-panel]]
|
||||
[app.main.ui.handoff.attributes.text :refer [text-panel]]))
|
||||
[app.main.ui.handoff.attributes.text :refer [text-panel]]
|
||||
[app.main.ui.handoff.attributes.svg :refer [svg-panel]]))
|
||||
|
||||
(def type->options
|
||||
{:multiple [:fill :stroke :image :text :shadow :blur]
|
||||
:frame [:layout :fill]
|
||||
:group [:layout]
|
||||
:rect [:layout :fill :stroke :shadow :blur]
|
||||
:circle [:layout :fill :stroke :shadow :blur]
|
||||
:path [:layout :fill :stroke :shadow :blur]
|
||||
:image [:image :layout :shadow :blur]
|
||||
:group [:layout :svg]
|
||||
:rect [:layout :fill :stroke :shadow :blur :svg]
|
||||
:circle [:layout :fill :stroke :shadow :blur :svg]
|
||||
:path [:layout :fill :stroke :shadow :blur :svg]
|
||||
:image [:image :layout :shadow :blur :svg]
|
||||
:text [:layout :text :shadow :blur]})
|
||||
|
||||
(mf/defc attributes
|
||||
|
@ -46,7 +47,8 @@
|
|||
:shadow shadow-panel
|
||||
:blur blur-panel
|
||||
:image image-panel
|
||||
:text text-panel)
|
||||
:text text-panel
|
||||
:svg svg-panel)
|
||||
{:shapes shapes
|
||||
:frame frame
|
||||
:locale locale}])
|
||||
|
|
|
@ -37,53 +37,55 @@
|
|||
|
||||
(mf/defc layout-block
|
||||
[{:keys [shape locale]}]
|
||||
[:*
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.width")]
|
||||
[:div.attributes-value (mth/precision (:width shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :width)}]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.height")]
|
||||
[:div.attributes-value (mth/precision (:height shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :height)}]]
|
||||
|
||||
(when (not= (:x shape) 0)
|
||||
(let [selrect (:selrect shape)
|
||||
{:keys [width height x y]} selrect]
|
||||
[:*
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.left")]
|
||||
[:div.attributes-value (mth/precision (:x shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :x)}]])
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.width")]
|
||||
[:div.attributes-value (mth/precision width 2) "px"]
|
||||
[:& copy-button {:data (copy-data selrect :width)}]]
|
||||
|
||||
(when (not= (:y shape) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.top")]
|
||||
[:div.attributes-value (mth/precision (:y shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :y)}]])
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.height")]
|
||||
[:div.attributes-value (mth/precision height 2) "px"]
|
||||
[:& copy-button {:data (copy-data selrect :height)}]]
|
||||
|
||||
(when (and (:rx shape) (not= (:rx shape) 0))
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.radius")]
|
||||
[:div.attributes-value (mth/precision (:rx shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :rx)}]])
|
||||
(when (not= (:x shape) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.left")]
|
||||
[:div.attributes-value (mth/precision x 2) "px"]
|
||||
[:& copy-button {:data (copy-data selrect :x)}]])
|
||||
|
||||
(when (and (:r1 shape)
|
||||
(or (not= (:r1 shape) 0)
|
||||
(not= (:r2 shape) 0)
|
||||
(not= (:r3 shape) 0)
|
||||
(not= (:r4 shape) 0)))
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.radius")]
|
||||
[:div.attributes-value (mth/precision (:r1 shape) 2) ", "
|
||||
(mth/precision (:r2 shape) 2) ", "
|
||||
(mth/precision (:r3 shape) 2) ", "
|
||||
(mth/precision (:r4 shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :r1)}]])
|
||||
(when (not= (:y shape) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.top")]
|
||||
[:div.attributes-value (mth/precision y 2) "px"]
|
||||
[:& copy-button {:data (copy-data selrect :y)}]])
|
||||
|
||||
(when (not= (:rotation shape 0) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.rotation")]
|
||||
[:div.attributes-value (mth/precision (:rotation shape) 2) "deg"]
|
||||
[:& copy-button {:data (copy-data shape :rotation)}]])])
|
||||
(when (and (:rx shape) (not= (:rx shape) 0))
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.radius")]
|
||||
[:div.attributes-value (mth/precision (:rx shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :rx)}]])
|
||||
|
||||
(when (and (:r1 shape)
|
||||
(or (not= (:r1 shape) 0)
|
||||
(not= (:r2 shape) 0)
|
||||
(not= (:r3 shape) 0)
|
||||
(not= (:r4 shape) 0)))
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.radius")]
|
||||
[:div.attributes-value (mth/precision (:r1 shape) 2) ", "
|
||||
(mth/precision (:r2 shape) 2) ", "
|
||||
(mth/precision (:r3 shape) 2) ", "
|
||||
(mth/precision (:r4 shape) 2) "px"]
|
||||
[:& copy-button {:data (copy-data shape :r1)}]])
|
||||
|
||||
(when (not= (:rotation shape 0) 0)
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.layout.rotation")]
|
||||
[:div.attributes-value (mth/precision (:rotation shape) 2) "deg"]
|
||||
[:& copy-button {:data (copy-data shape :rotation)}]])]))
|
||||
|
||||
|
||||
(mf/defc layout-panel
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.common.data :as d]
|
||||
[app.util.i18n :refer [t]]
|
||||
[app.util.code-gen :as cg]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -40,7 +41,7 @@
|
|||
copy-data (shadow-copy-data shadow)]
|
||||
[:div.attributes-shadow-block
|
||||
[:div.attributes-shadow-row
|
||||
[:div.attributes-label (->> shadow :style name (str "handoff.attributes.shadow.style.") (t locale))]
|
||||
[:div.attributes-label (->> shadow :style d/name (str "handoff.attributes.shadow.style.") (t locale))]
|
||||
[:div.attributes-shadow
|
||||
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.offset-x")]
|
||||
[:div.attributes-value (str (:offset-x shadow))]]
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.common.data :as d]
|
||||
[app.common.math :as mth]
|
||||
[app.util.i18n :refer [t]]
|
||||
[app.util.color :as uc]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -27,13 +29,15 @@
|
|||
|
||||
(defn format-stroke [shape]
|
||||
(let [width (:stroke-width shape)
|
||||
style (name (:stroke-style shape))
|
||||
style (d/name (:stroke-style shape))
|
||||
style (if (= style "svg") "solid" style)
|
||||
color (-> shape shape->color uc/color->background)]
|
||||
(str/format "%spx %s %s" width style color)))
|
||||
|
||||
(defn has-stroke? [shape]
|
||||
(and (:stroke-style shape)
|
||||
(not= (:stroke-style shape) :none)))
|
||||
(defn has-stroke? [{:keys [stroke-style]}]
|
||||
(and stroke-style
|
||||
(and (not= stroke-style :none)
|
||||
(not= stroke-style :svg))))
|
||||
|
||||
(defn copy-stroke-data [shape]
|
||||
(cg/generate-css-props
|
||||
|
@ -59,12 +63,15 @@
|
|||
:copy-data (copy-color-data shape)
|
||||
:on-change-format #(reset! color-format %)}]
|
||||
|
||||
[:div.attributes-stroke-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.stroke.width")]
|
||||
[:div.attributes-value (:stroke-width shape) "px"]
|
||||
[:div.attributes-value (->> shape :stroke-style name (str "handoff.attributes.stroke.style.") (t locale))]
|
||||
[:div.attributes-label (->> shape :stroke-alignment name (str "handoff.attributes.stroke.alignment.") (t locale))]
|
||||
[:& copy-button {:data (copy-stroke-data shape)}]]]))
|
||||
(let [{:keys [stroke-style stroke-alignment]} shape
|
||||
stroke-style (if (= stroke-style :svg) :solid stroke-style)
|
||||
stroke-alignment (or stroke-alignment :center)]
|
||||
[:div.attributes-stroke-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.stroke.width")]
|
||||
[:div.attributes-value (mth/precision (:stroke-width shape) 2) "px"]
|
||||
[:div.attributes-value (->> stroke-style d/name (str "handoff.attributes.stroke.style.") (t locale))]
|
||||
[:div.attributes-label (->> stroke-alignment d/name (str "handoff.attributes.stroke.alignment.") (t locale))]
|
||||
[:& copy-button {:data (copy-stroke-data shape)}]])]))
|
||||
|
||||
(mf/defc stroke-panel
|
||||
[{:keys [shapes locale]}]
|
||||
|
|
57
frontend/src/app/main/ui/handoff/attributes/svg.cljs
Normal file
57
frontend/src/app/main/ui/handoff/attributes/svg.cljs
Normal file
|
@ -0,0 +1,57 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.handoff.attributes.svg
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[app.common.data :as d]
|
||||
[cuerdas.core :as str]
|
||||
[app.util.i18n :refer [tr]]
|
||||
#_[app.common.math :as mth]
|
||||
#_[app.main.ui.icons :as i]
|
||||
#_[app.util.code-gen :as cg]
|
||||
[app.main.ui.components.copy-button :refer [copy-button]]))
|
||||
|
||||
|
||||
(defn map->css [attr]
|
||||
(->> attr
|
||||
(map (fn [[attr-key attr-value]] (str (d/name attr-key) ":" attr-value)))
|
||||
(str/join "; ")))
|
||||
|
||||
(mf/defc svg-attr [{:keys [attr value]}]
|
||||
(if (map? value)
|
||||
[:*
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (d/name attr)]
|
||||
[:& copy-button {:data (map->css value)}]]
|
||||
|
||||
(for [[attr-key attr-value] value]
|
||||
[:& svg-attr {:attr attr-key :value attr-value}])]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (d/name attr)]
|
||||
[:div.attributes-value (str value)]
|
||||
[:& copy-button {:data (d/name value)}]]))
|
||||
|
||||
(mf/defc svg-block
|
||||
[{:keys [shape]}]
|
||||
[:*
|
||||
(for [[attr-key attr-value] (:svg-attrs shape)]
|
||||
[:& svg-attr {:attr attr-key :value attr-value}])] )
|
||||
|
||||
|
||||
(mf/defc svg-panel
|
||||
[{:keys [shapes]}]
|
||||
|
||||
(let [shape (first shapes)]
|
||||
(when (and (:svg-attrs shape) (not (empty? (:svg-attrs shape))))
|
||||
[:div.attributes-block
|
||||
[:div.attributes-block-title
|
||||
[:div.attributes-block-title-text (tr "workspace.sidebar.options.svg-attrs.title")]]
|
||||
[:& svg-block {:shape shape}]])))
|
|
@ -114,7 +114,7 @@
|
|||
[:input.input-text {:on-change (partial on-suffix-change index)
|
||||
:value (:suffix export)}]
|
||||
[:select.input-select {:on-change (partial on-type-change index)
|
||||
:value (name (:type export))}
|
||||
:value (d/name (:type export))}
|
||||
[:option {:value "png"} "PNG"]
|
||||
[:option {:value "jpeg"} "JPEG"]
|
||||
[:option {:value "svg"} "SVG"]]
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[okulary.core :as l]
|
||||
[app.util.i18n :refer [t] :as i18n]
|
||||
[app.common.data :as d]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
|
@ -49,7 +50,7 @@
|
|||
[:*
|
||||
[:span.tool-window-bar-icon
|
||||
[:& element-icon {:shape (-> shapes first)}]]
|
||||
[:span.tool-window-bar-title (->> selected-type name (str "handoff.tabs.code.selected.") (t locale))]])
|
||||
[:span.tool-window-bar-title (->> selected-type d/name (str "handoff.tabs.code.selected.") (t locale))]])
|
||||
]
|
||||
[:div.tool-window-content
|
||||
[:& tab-container {:on-change-tab #(do
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
(fn []
|
||||
(on-delete attr)))
|
||||
|
||||
label (->> attr last name)]
|
||||
label (->> attr last d/name)]
|
||||
[:div.element-set-content
|
||||
(if (string? value)
|
||||
[:div.row-flex.row-flex-removable
|
||||
|
@ -48,7 +48,7 @@
|
|||
[:*
|
||||
[:div.element-set-title
|
||||
{:style {:border-bottom "1px solid #444" :margin-bottom "0.5rem"}}
|
||||
[:span (str (name (last attr)))]]
|
||||
[:span (str (d/name (last attr)))]]
|
||||
|
||||
(for [[key value] value]
|
||||
[:& attribute-value {:key key
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"Transforms attributes to their react equivalent"
|
||||
[attrs]
|
||||
(letfn [(transform-key [key]
|
||||
(-> (name key)
|
||||
(-> (d/name key)
|
||||
(str/replace ":" "-")
|
||||
(str/camel)
|
||||
(keyword)))
|
||||
|
|
Loading…
Add table
Reference in a new issue