0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-11 23:31:21 -05:00

Adds copy properties.

This commit is contained in:
alonso.torres 2020-10-23 15:41:06 +02:00 committed by Hirunatan
parent 1e48221d7b
commit d6573c2bcc
9 changed files with 454 additions and 166 deletions

View file

@ -3366,6 +3366,16 @@
"handoff.tabs.info": "Info",
"handoff.tabs.code": "Code",
"handoff.tabs.code.selected.frame": "Artboard",
"handoff.tabs.code.selected.group": "Group",
"handoff.tabs.code.selected.rect": "Rectangle",
"handoff.tabs.code.selected.circle": "Circle",
"handoff.tabs.code.selected.path": "Path",
"handoff.tabs.code.selected.curve": "Curve",
"handoff.tabs.code.selected.image": "Image",
"handoff.tabs.code.selected.text": "Text",
"handoff.tabs.code.selected.multiple": "%s Selected",
"handoff.attributes.color.hex": "HEX",
"handoff.attributes.color.rgba": "RGBA",
"handoff.attributes.color.hsla": "HSLA",

View file

@ -22,6 +22,14 @@
padding-bottom: 0.5rem;
font-size: $fs12;
.attributes-text-block {
border-bottom: 1px solid $color-gray-60;
}
& :last-child{
border-bottom: none;
}
.attributes-copy-button {
visibility: hidden;
opacity: 0;
@ -139,13 +147,18 @@
.attributes-content {
overflow-y: auto;
max-height: 10rem;
max-height: 5rem;
background: $color-gray-60;
border-radius: 4px;
padding: 1rem 0.5rem;
color: $color-gray-10;
white-space: pre-wrap;
}
.attributes-copy-button {
padding: 0.5rem;
margin-top: 0.25rem;
}
}
.attributes-image-row {
@ -194,6 +207,16 @@
justify-content: space-between;
}
.attributes-typography-row {
position: relative;
margin: 0.5rem;
padding-right: 2rem;
.typography-sample {
font-size: $fs16;
}
}
.download-button {
display: block;
text-align: center;
@ -216,7 +239,9 @@
.attributes-unit-row,
.attributes-color-row,
.attributes-shadow-row,
.attributes-stroke-row {
.attributes-stroke-row,
.attributes-typography-row,
.attributes-content-row {
&:hover .attributes-copy-button {
visibility: visible;
opacity: 1;

View file

@ -77,6 +77,13 @@
(let [page-id (get @state :current-page-id)]
(logjs "state" (get-in @state [:workspace-data :pages-index page-id :objects]))))
(defn ^:export dump-object [name]
(let [page-id (get @state :current-page-id)]
(let [objects (get-in @state [:workspace-data :pages-index page-id :objects])
target (d/seek (fn [[id shape]] (= name (:name shape))) objects)]
(->> target
(logjs "state")))))
(defn ^:export dump-tree
([] (dump-tree false))
([show-touched]

View file

@ -12,150 +12,271 @@
[rumext.alpha :as mf]
[cuerdas.core :as str]
[app.config :as cfg]
[app.util.data :as d]
[app.util.dom :as dom]
[app.util.i18n :refer [locale t]]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
[app.main.ui.icons :as i]
[app.util.color :as uc]
[app.util.text :as ut]
[app.common.math :as mth]
[app.common.geom.shapes :as gsh]
[app.main.fonts :as fonts]
[app.main.ui.icons :as i]
[app.util.webapi :as wapi]
[app.main.ui.components.color-bullet :refer [color-bullet color-name]]))
(mf/defc color-row [{:keys [color]}]
(defn copy-cb [values properties & {:keys [to-prop format] :or {to-prop {}}}]
(fn [event]
(let [
;; We allow the :format and :to-prop to be a map for different properties
;; or just a value for a single property. This code transform a single
;; property to a uniform one
properties (if-not (coll? properties) [properties] properties)
format (if (not (map? format))
(into {} (map #(vector % format) properties))
format)
to-prop (if (not (map? to-prop))
(into {} (map #(vector % to-prop) properties))
to-prop)
default-format (fn [value] (str (mth/precision value 2) "px"))
format-property (fn [prop]
(let [css-prop (or (prop to-prop) (name prop))]
(str/fmt " %s: %s;" css-prop ((or (prop format) default-format) (prop values) values))))
text-props (->> properties
(remove #(let [value (get values %)]
(or (nil? value) (= value 0))))
(map format-property)
(str/join "\n"))
result (str/fmt "{\n%s\n}" text-props)]
(wapi/write-to-clipboard result))))
(mf/defc color-row [{:keys [color format on-copy on-change-format]}]
(let [locale (mf/deref locale)]
[:div.attributes-color-row
[:& color-bullet {:color color}]
[:*
[:& color-name {:color color}]
(when-not (:gradient color) [:div (str (* 100 (:opacity color)) "%")])]
[:select
[:option (t locale "handoff.attributes.color.hex")]
[:option (t locale "handoff.attributes.color.rgba")]
[:option (t locale "handoff.attributes.color.hsla")]]
(if (:gradient color)
[:& color-name {:color color}]
(case format
:rgba (let [[r g b a] (->> (uc/hex->rgba (:color color) (:opacity color)) (map #(mth/precision % 2)))]
[:div (str/fmt "%s, %s, %s, %s" r g b a)])
:hsla (let [[h s l a] (->> (uc/hex->hsla (:color color) (:opacity color)) (map #(mth/precision % 2)))]
[:div (str/fmt "%s, %s, %s, %s" h s l a)])
[:*
[:& color-name {:color color}]
(when-not (:gradient color) [:div (str (* 100 (:opacity color)) "%")])]))
[:button.attributes-copy-button i/copy]]))
(when-not (and on-change-format (:gradient color))
[:select {:on-change #(-> (dom/get-target-val %) keyword on-change-format)}
[:option {:value "hex"}
(t locale "handoff.attributes.color.hex")]
[:option {:value "rgba"}
(t locale "handoff.attributes.color.rgba")]
[:option {:value "hsla"}
(t locale "handoff.attributes.color.hsla")]])
(when on-copy
[:button.attributes-copy-button {:on-click on-copy} i/copy])]))
(mf/defc layout-panel
[{:keys [shape locale]}]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.layout")]
[:button.attributes-copy-button i/copy]]
[:button.attributes-copy-button
{:on-click (copy-cb shape
[:width :height :x :y :rotation]
:to-prop {:x "left" :y "top" :rotation "transform"}
:format {:rotation #(str/fmt "rotate(%sdeg)" %)})}
i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.width")]
[:div.attributes-value (mth/precision (:width shape) 2) "px"]
[:button.attributes-copy-button i/copy]]
[:button.attributes-copy-button
{:on-click (copy-cb shape :width)}
i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.height")]
[:div.attributes-value (mth/precision (:height shape) 2) "px"]
[:button.attributes-copy-button i/copy]]
[:button.attributes-copy-button
{:on-click (copy-cb shape :height)}
i/copy]]
(when (not= (:x shape) 0)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.layout.left")]
[:div.attributes-value (mth/precision (:x shape) 2) "px"]
[:button.attributes-copy-button i/copy]])
[:button.attributes-copy-button
{:on-click (copy-cb shape :x :to-prop "left")}
i/copy]])
(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"]
[:button.attributes-copy-button i/copy]])
[:button.attributes-copy-button
{:on-click (copy-cb shape :y :to-prop "top")}
i/copy]])
(when (not= (:rotation shape) 0)
(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"]
[:button.attributes-copy-button i/copy]])])
[:button.attributes-copy-button
{:on-click (copy-cb shape
:rotation
:to-prop "transform"
:format #(str/fmt "rotate(%sdeg)" %))}
i/copy]])])
(mf/defc fill-panel
[{:keys [shape locale]}]
(let [{:keys [fill-color fill-opacity fill-color-gradient fill-ref-id fill-ref-file-id]} shape]
(when (or fill-color fill-color-gradient)
(let [color-format (mf/use-state :hex)
color {:color (:fill-color shape)
:opacity (:fill-opacity shape)
:gradient (:fill-color-gradient shape)
:id (:fill-ref-id shape)
:file-id (:fill-ref-file-id shape)}
handle-copy (copy-cb shape
[:fill-color :fill-color-gradient]
:to-prop "background"
:format #(uc/color->background color))]
(when (or (:color color) (:gradient color))
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.fill")]
[:button.attributes-copy-button i/copy]]
[:button.attributes-copy-button
{:on-click handle-copy}
i/copy]]
(let [color {:color fill-color
:opacity fill-opacity
:gradient fill-color-gradient
:id fill-ref-id
:file-id fill-ref-file-id}]
[:& color-row {:color color}])])))
[:& color-row {:color color
:format @color-format
:on-change-format #(reset! color-format %)
:on-copy handle-copy}]])))
(mf/defc stroke-panel
[{:keys [shape locale]}]
(when (and (:stroke-style shape) (not= (:stroke-style shape) :none))
(let [{:keys [stroke-style stroke-alignment stroke-width
stroke-color stroke-opacity stroke-color-gradient
stroke-color-ref-id stroke-color-file-id]} shape
color {:color stroke-color
:opacity stroke-opacity
:gradient stroke-color-gradient
:id stroke-color-ref-id
:file-id stroke-color-file-id}]
(let [color-format (mf/use-state :hex)
color {:color (:stroke-color shape)
:opacity (:stroke-opacity shape)
:gradient (:stroke-color-gradient shape)
:id (:stroke-color-ref-id shape)
:file-id (:stroke-color-file-id shape)}
handle-copy-stroke (copy-cb shape
:stroke-style
:to-prop "border"
:format #(let [width (:stroke-width %2)
style (name (:stroke-style %2))
color (uc/color->background color)]
(str/format "%spx %s %s" width style color)))]
(when (and (:stroke-style shape) (not= (:stroke-style shape) :none))
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.stroke")]
[:button.attributes-copy-button i/copy]]
[:button.attributes-copy-button
{:on-click handle-copy-stroke} i/copy]]
[:& color-row {:color color}]
[:& color-row {:color color
:format @color-format
:on-change-format #(reset! color-format %)
:on-copy (copy-cb shape
:stroke-color
:to-prop "border-color"
:format #(uc/color->background color))}]
[:div.attributes-stroke-row
[:div.attributes-label (t locale "handoff.attributes.stroke.width")]
[:div.attributes-value (str stroke-width) "px"]
[:div.attributes-value (->> stroke-style name (str "handoff.attributes.stroke.style.") (t locale))]
[:div.attributes-label (->> stroke-alignment name (str "handoff.attributes.stroke.alignment.") (t locale))]
[:button.attributes-copy-button i/copy]]])))
[: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))]
[:button.attributes-copy-button
{:on-click handle-copy-stroke} i/copy]]])))
(defn shadow->css [shadow]
(let [{:keys [style offset-x offset-y blur spread]} shadow
css-color (uc/color->background (:color shadow))]
(str
(if (= style :inner-shadow) "inset " "")
(str/fmt "%spx %spx %spx %spx %s" offset-x offset-y blur spread css-color))))
(mf/defc shadow-block [{:keys [shape locale shadow]}]
(let [color-format (mf/use-state :hex)]
[:div.attributes-shadow-block
[:div.attributes-shadow-row
[:div.attributes-label (->> shadow :style 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))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.offset-y")]
[:div.attributes-value (str (:offset-y shadow))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.blur")]
[:div.attributes-value (str (:blur shadow))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.spread")]
[:div.attributes-value (str (:spread shadow))]]
[:button.attributes-copy-button
{:on-click (copy-cb shadow
:style
:to-prop "box-shadow"
:format #(shadow->css shadow))}
i/copy]]
[:& color-row {:color (:color shadow)
:format @color-format
:on-change-format #(reset! color-format %)}]]))
(mf/defc shadow-panel [{:keys [shape locale]}]
(when (seq (:shadow shape))
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.shadow")]
[:button.attributes-copy-button i/copy]]
[:button.attributes-copy-button
{:on-click (copy-cb shape
:shadow
:to-prop "box-shadow"
:format #(str/join ", " (map shadow->css (:shadow shape))))}
i/copy]]
(for [shadow (:shadow shape)]
(do
(prn "???" (:spread shadow))
[:*
[:div.attributes-shadow-row
[:div.attributes-label (->> shadow :style 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))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.offset-y")]
[:div.attributes-value (str (:offset-y shadow))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.blur")]
[:div.attributes-value (str (:blur shadow))]]
[:div.attributes-shadow
[:div.attributes-label (t locale "handoff.attributes.shadow.shorthand.spread")]
[:div.attributes-value (str (:spread shadow))]]
[:button.attributes-copy-button i/copy]]
[:& color-row {:color (:color shadow)}]]))]))
[:& shadow-block {:shape shape
:locale locale
:shadow shadow}])]))
(mf/defc blur-panel [{:keys [shape locale]}]
(when (:blur shape)
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.blur")]
[:button.attributes-copy-button i/copy]]
(let [handle-copy
(copy-cb shape
:blur
:to-prop "filter"
:format #(str/fmt "blur(%spx)" %))]
(when (:blur shape)
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.blur")]
[:button.attributes-copy-button {:on-click handle-copy} i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.blur.value")]
[:div.attributes-value (-> shape :blur :value) "px"]
[:button.attributes-copy-button i/copy]]]))
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.blur.value")]
[:div.attributes-value (-> shape :blur :value) "px"]
[:button.attributes-copy-button {:on-click handle-copy} i/copy]]])))
(mf/defc image-panel [{:keys [shape locale]}]
[:div.attributes-block
@ -163,70 +284,143 @@
[:div.attributes-image
[:img {:src (cfg/resolve-media-path (-> shape :metadata :path))}]]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.image.width")]
[:div.attributes-value (-> shape :metadata :width) "px"]]
[:div.attributes-label (t locale "handoff.attributes.image.width")]
[:div.attributes-value (-> shape :metadata :width) "px"]
[:button.attributes-copy-button {:on-click (copy-cb shape :width)} i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.image.height")]
[:div.attributes-value (-> shape :metadata :height) "px"]]
[:div.attributes-label (t locale "handoff.attributes.image.height")]
[:div.attributes-value (-> shape :metadata :height) "px"]
[:button.attributes-copy-button {:on-click (copy-cb shape :height)} i/copy]]
(let [filename (last (str/split (-> shape :metadata :path) "/"))]
[:a.download-button {:target "_blank"
:download filename
:href (cfg/resolve-media-path (-> shape :metadata :path))}
(t locale "handoff.attributes.image.download")])])
(mf/defc text-block [{:keys [shape locale text style full-style]}]
(let [color-format (mf/use-state :hex)
color {:color (:fill-color style)
:opacity (:fill-opacity style)
:gradient (:fill-color-gradient style)
:id (:fill-color-ref-id style)
:file-id (:fill-color-ref-file-id style)}
properties [:fill-color
:fill-color-gradient
:font-family
:font-style
:font-size
:line-height
:letter-spacing
:text-decoration
:text-transform]
format {:font-family identity
:font-style identity
:font-size #(str % "px")
:line-height #(str % "px")
:letter-spacing #(str % "px")
:text-decoration name
:text-transform name
:fill-color #(uc/color->background color)
:fill-color-gradient #(uc/color->background color)}
to-prop {:fill-color "color"
:fill-color-gradient "color"}]
[:div.attributes-text-block
[:div.attributes-typography-row
[:div.typography-sample
{:style {:font-family (:font-family full-style)
:font-weight (:font-weight full-style)
:font-style (:font-style full-style)}}
(t locale "workspace.assets.typography.sample")]
[:button.attributes-copy-button
{:on-click (copy-cb style properties :to-prop to-prop :format format)} i/copy]]
[:div.attributes-content-row
[:pre.attributes-content (str/trim text)]
[:button.attributes-copy-button
{:on-click #(wapi/write-to-clipboard (str/trim text))}
i/copy]]
(when (or (:fill-color style) (:fill-color-gradient style))
(let [color {:color (:fill-color style)
:opacity (:fill-opacity style)
:gradient (:fill-color-gradient style)
:id (:fill-ref-id style)
:file-id (:fill-ref-file-id style)}]
[:& color-row {:format @color-format
:on-change-format #(reset! color-format %)
:color color
:on-copy (copy-cb style [:fill-color :fill-color-gradient] :to-prop to-prop :format format)}]))
(when (:font-id style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-family")]
[:div.attributes-value (-> style :font-id fonts/get-font-data :name)]
[:button.attributes-copy-button {:on-click (copy-cb style :font-family :format identity)} i/copy]])
(when (:font-style style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-style")]
[:div.attributes-value (str (:font-style style))]
[:button.attributes-copy-button {:on-click (copy-cb style :font-style :format identity)} i/copy]])
(when (:font-size style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-size")]
[:div.attributes-value (str (:font-size style)) "px"]
[:button.attributes-copy-button {:on-click (copy-cb style :font-size :format #(str % "px"))} i/copy]])
(when (:line-height style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.line-height")]
[:div.attributes-value (str (:line-height style)) "px"]
[:button.attributes-copy-button {:on-click (copy-cb style :line-height :format #(str % "px"))} i/copy]])
(when (:letter-spacing style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.letter-spacing")]
[:div.attributes-value (str (:letter-spacing style)) "px"]
[:button.attributes-copy-button {:on-click (copy-cb style :letter-spacing :format #(str % "px"))} i/copy]])
(when (:text-decoration style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.text-decoration")]
[:div.attributes-value (->> style :text-decoration (str "handoff.attributes.typography.text-decoration.") (t locale))]
[:button.attributes-copy-button {:on-click (copy-cb style :text-decoration :format name)} i/copy]])
(when (:text-transform style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.text-transform")]
[:div.attributes-value (->> style :text-transform (str "handoff.attributes.typography.text-transform.") (t locale))]
[:button.attributes-copy-button {:on-click (copy-cb style :text-transform :format name)} i/copy]])]))
(mf/defc typography-panel [{:keys [shape locale]}]
(let [font (ut/search-text-attrs (:content shape)
(keys ut/default-text-attrs))
style-text-blocks (->> (keys ut/default-text-attrs)
(ut/parse-style-text-blocks (:content shape))
(remove (fn [[style text]] (str/empty? (str/trim text))))
(mapv (fn [[style text]] (vector (merge ut/default-text-attrs style) text))))
font (merge ut/default-text-attrs font)]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.typography")]
[:button.attributes-copy-button i/copy]]
[:div.attributes-block-title-text (t locale "handoff.attributes.typography")]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-family")]
[:div.attributes-value (-> font :font-id fonts/get-font-data :name)]
[:button.attributes-copy-button i/copy]]
(for [[idx [full-style text]] (map-indexed vector style-text-blocks)]
(let [previus-style (first (nth style-text-blocks (dec idx) nil))
style (d/remove-equal-values full-style previus-style)
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-style")]
[:div.attributes-value (str (:font-style font))]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.font-size")]
[:div.attributes-value (str (:font-size font)) "px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.line-height")]
[:div.attributes-value (str (:line-height font)) "px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.letter-spacing")]
[:div.attributes-value (str (:letter-spacing font)) "px"]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.text-decoration")]
[:div.attributes-value (->> font :text-decoration (str "handoff.attributes.typography.text-decoration.") (t locale))]
[:button.attributes-copy-button i/copy]]
[:div.attributes-unit-row
[:div.attributes-label (t locale "handoff.attributes.typography.text-transform")]
[:div.attributes-value (->> font :text-transform (str "handoff.attributes.typography.text-transform.") (t locale))]
[:button.attributes-copy-button i/copy]]]))
(mf/defc content-panel [{:keys [shape locale]}]
[:div.attributes-block
[:div.attributes-block-title
[:div.attributes-block-title-text (t locale "handoff.attributes.content")]
[:button.attributes-copy-button i/copy]]
[:div.attributes-content-row
[:pre.attributes-content (ut/content->text (:content shape))]
[:button.attributes-copy-button i/copy]]])
;; If the color is set we need to add opacity otherwise the display will not work
style (cond-> style
(:fill-color style)
(assoc :fill-opacity (:fill-opacity full-style)))]
[:& text-block {:shape shape
:locale locale
:full-style full-style
:style style
:text text}]))]))
(mf/defc attrib-panel [{:keys [shape frame options]}]
(let [locale (mf/deref locale)]
@ -240,9 +434,7 @@
:shadow shadow-panel
:blur blur-panel
:image image-panel
:typography typography-panel
:content content-panel
)
:typography typography-panel)
{:shape (gsh/translate-to-frame shape frame)
:frame frame
:locale locale}])]))

View file

@ -15,7 +15,6 @@
(mf/defc layout-panel [{:keys [shapes]}]
(prn "???" shapes)
[:*
[:div.attributes-block
[:div.attributes-block-title

View file

@ -11,10 +11,12 @@
(:require
[rumext.alpha :as mf]
[okulary.core :as l]
[app.util.i18n :refer [t] :as i18n]
[app.main.store :as st]
[app.main.ui.icons :as i]
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
[app.main.ui.viewer.handoff.attrib-panel :refer [attrib-panel]]))
[app.main.ui.viewer.handoff.attrib-panel :refer [attrib-panel]]
[app.main.ui.workspace.sidebar.layers :refer [element-icon]]))
(defn make-selected-shapes-iref
[]
@ -26,44 +28,54 @@
(mapv resolve-shape selected)))]
#(l/derived selected->shapes st/state)))
(mf/defc info-panel [{:keys [frame]}]
(let [selected-ref (mf/use-memo (make-selected-shapes-iref))
shapes (mf/deref selected-ref)]
(if (> (count shapes) 1)
;; Multiple selection
nil
;; Single shape
(when-let [shape (first shapes)]
(let [options
(case (:type shape)
:frame [:layout :fill]
:group [:layout]
:rect [:layout :fill :stroke :shadow :blur]
:circle [:layout :fill :stroke :shadow :blur]
:path [:layout :fill :stroke :shadow :blur]
:curve [:layout :fill :stroke :shadow :blur]
:image [:image :layout :shadow :blur]
:text [:layout :fill :typography :content :shadow :blur])]
[:& attrib-panel {:frame frame
:shape shape
:options options}])))))
(mf/defc info-panel [{:keys [frame shapes]}]
(if (> (count shapes) 1)
;; TODO:Multiple selection
nil
;; Single shape
(when-let [shape (first shapes)]
(let [options
(case (:type shape)
:frame [:layout :fill]
:group [:layout]
:rect [:layout :fill :stroke :shadow :blur]
:circle [:layout :fill :stroke :shadow :blur]
:path [:layout :fill :stroke :shadow :blur]
:curve [:layout :fill :stroke :shadow :blur]
:image [:image :layout :shadow :blur]
:text [:layout :typography :shadow :blur])]
[:& attrib-panel {:frame frame
:shape shape
:options options}]))))
(mf/defc code-panel []
[:div.element-options])
(mf/defc attributes-sidebar [{:keys [frame]}]
(let [section (mf/use-state :info #_:code)]
(let [locale (mf/deref i18n/locale)
section (mf/use-state :info #_:code)
selected-ref (mf/use-memo (make-selected-shapes-iref))
shapes (mf/deref selected-ref)]
[:aside.settings-bar.settings-bar-right
[:div.settings-bar-inside
[:div.tool-window
[:div.tool-window-bar.big
[:span.tool-window-bar-icon i/text]
[:span.tool-window-bar-title "Text"]]
[:div.tool-window-content
[:& tab-container {:on-change-tab #(reset! section %)
:selected @section}
[:& tab-element {:id :info :title "Info"}
[:& info-panel {:frame frame}]]
(when (seq shapes)
[:div.tool-window
[:div.tool-window-bar.big
(if (> (count shapes) 1)
[:*
[:span.tool-window-bar-icon i/layers]
[:span.tool-window-bar-title (t locale "handoff.tabs.code.selected.multiple" (count shapes))]]
[:*
[:span.tool-window-bar-icon
[:& element-icon {:shape (-> shapes first)}]]
[:span.tool-window-bar-title (->> shapes first :type name (str "handoff.tabs.code.selected.") (t locale))]])
]
[:div.tool-window-content
[:& tab-container {:on-change-tab #(reset! section %)
:selected @section}
[:& tab-element {:id :info :title (t locale "handoff.tabs.info")}
[:& info-panel {:frame frame
:shapes shapes}]]
[:& tab-element {:id :code :title "Code"}
[:& code-panel]]]]]]]))
[:& tab-element {:id :code :title (t locale "handoff.tabs.code")}
[:& code-panel]]]]])]]))

View file

@ -53,6 +53,11 @@
(into [] (gcolor/hexToHsl hex))
(catch :default e [0 0 0])))
(defn hex->hsla
[^string data ^number opacity]
(-> (hex->hsl data)
(conj opacity)))
(defn hsl->rgb
[[h s l]]
(gcolor/hslToRgb h s l))

View file

@ -111,6 +111,14 @@
not-found))
not-found coll)))
(defn remove-equal-values [m1 m2]
(if (and (map? m1) (map? m2) (not (nil? m1)) (not (nil? m2)))
(->> m1
(remove (fn [[k v]] (= (k m2) v)))
(into {}))
m1))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Numbers Parsing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -50,6 +50,36 @@
(str/join (if (= "paragraph-set" (:type node)) "\n" "") (map content->text (:children node)))
(:text node ""))))
(defn parse-style-text-blocks
[node attrs]
(letfn
[(rec-style-text-map [acc node style]
(let [node-style (merge style (select-keys node attrs))
head (or (-> acc first) [{} ""])
[head-style head-text] head
new-acc
(cond
(:children node)
(reduce #(rec-style-text-map %1 %2 node-style) acc (:children node))
(not= head-style node-style)
(cons [node-style (:text node "")] acc)
:else
(cons [node-style (str head-text "" (:text node))] (rest acc)))
;; We add an end-of-line when finish a paragraph
new-acc
(if (= (:type node) "paragraph")
(let [[hs ht] (first new-acc)]
(cons [hs (str ht "\n")] (rest new-acc)))
new-acc)]
new-acc))]
(-> (rec-style-text-map [] node {})
reverse)))
(defn search-text-attrs
[node attrs]