mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 22:53:02 +00:00
🎉 Add copy shortands button to panels (#7580)
* 🎉 Add copy shorthands button to panels * 🎉 Add shorthand for strokes * 🎉 Add shorthand for fonts * 🎉 Add shorthand for borders * 🎉 Add shorthand for padding * 🎉 Add shorthand for grid * 🎉 Add shorthand for layout element * 🐛 Refactor to fix hook rendering
This commit is contained in:
@@ -77,7 +77,7 @@
|
||||
(:content shape))
|
||||
|
||||
(defn- has-shadow? [shape]
|
||||
(:shadow shape))
|
||||
(seq (:shadow shape)))
|
||||
|
||||
(defn- get-shape-type
|
||||
[shapes first-shape first-component]
|
||||
@@ -111,7 +111,26 @@
|
||||
(not (or (= shape-type :text) (= shape-type :group)))
|
||||
(or (:opacity shape)
|
||||
(:blend-mode shape)
|
||||
(:visibility shape))))))]
|
||||
(:visibility shape))))))
|
||||
shorthands* (mf/use-state #(do {:fill nil
|
||||
:stroke nil
|
||||
:text nil
|
||||
:shadow nil
|
||||
:blur nil
|
||||
:layout nil
|
||||
:layout-element nil
|
||||
:geometry nil
|
||||
:svg nil
|
||||
:visibility nil
|
||||
:variant nil
|
||||
:grid-element nil}))
|
||||
shorthands (deref shorthands*)
|
||||
set-shorthands
|
||||
;; This fn must receive an object `shorthand` with :panel and :property (the shorthand string) keys
|
||||
(mf/use-fn
|
||||
(mf/deps shorthands*)
|
||||
(fn [shorthand]
|
||||
(swap! shorthands* assoc (:panel shorthand) (:property shorthand))))]
|
||||
[:ol {:class (stl/css :styles-tab) :aria-label (tr "labels.styles")}
|
||||
;; TOKENS PANEL
|
||||
(when (or active-themes active-sets)
|
||||
@@ -130,18 +149,22 @@
|
||||
:data data}]]
|
||||
;; GEOMETRY PANEL
|
||||
:geometry
|
||||
[:> style-box* {:panel :geometry}
|
||||
[:> style-box* {:panel :geometry
|
||||
:shorthand (:geometry shorthands)}
|
||||
[:> geometry-panel* {:shapes shapes
|
||||
:objects objects
|
||||
:resolved-tokens resolved-active-tokens}]]
|
||||
:resolved-tokens resolved-active-tokens
|
||||
:on-geometry-shorthand set-shorthands}]]
|
||||
;; LAYOUT PANEL
|
||||
:layout
|
||||
(let [layout-shapes (->> shapes (filter ctl/any-layout?))]
|
||||
(when (seq layout-shapes)
|
||||
[:> style-box* {:panel :layout}
|
||||
[:> style-box* {:panel :layout
|
||||
:shorthand (:layout shorthands)}
|
||||
[:> layout-panel* {:shapes layout-shapes
|
||||
:objects objects
|
||||
:resolved-tokens resolved-active-tokens}]]))
|
||||
:resolved-tokens resolved-active-tokens
|
||||
:on-layout-shorthand set-shorthands}]]))
|
||||
;; LAYOUT ELEMENT PANEL
|
||||
:layout-element
|
||||
(let [shapes (->> shapes (filter #(ctl/any-layout-immediate-child? objects %)))
|
||||
@@ -157,29 +180,35 @@
|
||||
(if only-grid?
|
||||
:grid-element
|
||||
:layout-element))]
|
||||
[:> style-box* {:panel panel}
|
||||
[:> style-box* {:panel panel
|
||||
:shorthand (:layout-element shorthands)}
|
||||
[:> layout-element-panel* {:shapes shapes
|
||||
:objects objects
|
||||
:resolved-tokens resolved-active-tokens
|
||||
:layout-element-properties layout-element-properties}]])))
|
||||
:layout-element-properties layout-element-properties
|
||||
:on-layout-element-shorthand set-shorthands}]])))
|
||||
;; FILL PANEL
|
||||
:fill
|
||||
(let [shapes (filter has-fill? shapes)]
|
||||
(when (seq shapes)
|
||||
[:> style-box* {:panel :fill}
|
||||
[:> style-box* {:panel :fill
|
||||
:shorthand (:fill shorthands)}
|
||||
[:> fill-panel* {:color-space color-space
|
||||
:shapes shapes
|
||||
:resolved-tokens resolved-active-tokens}]]))
|
||||
:resolved-tokens resolved-active-tokens
|
||||
:on-fill-shorthand set-shorthands}]]))
|
||||
|
||||
;; STROKE PANEL
|
||||
:stroke
|
||||
(let [shapes (filter has-stroke? shapes)]
|
||||
(when (seq shapes)
|
||||
[:> style-box* {:panel :stroke}
|
||||
[:> style-box* {:panel :stroke
|
||||
:shorthand (:stroke shorthands)}
|
||||
[:> stroke-panel* {:color-space color-space
|
||||
:shapes shapes
|
||||
:objects objects
|
||||
:resolved-tokens resolved-active-tokens}]]))
|
||||
:resolved-tokens resolved-active-tokens
|
||||
:on-stroke-shorthand set-shorthands}]]))
|
||||
|
||||
;; VISIBILITY PANEL
|
||||
:visibility
|
||||
@@ -207,18 +236,23 @@
|
||||
:text
|
||||
(let [shapes (filter has-text? shapes)]
|
||||
(when (seq shapes)
|
||||
[:> style-box* {:panel :text}
|
||||
[:> style-box* {:panel :text
|
||||
:shorthand (:text shorthands)}
|
||||
[:> text-panel* {:shapes shapes
|
||||
:color-space color-space
|
||||
:objects objects
|
||||
:resolved-tokens resolved-active-tokens}]]))
|
||||
:resolved-tokens resolved-active-tokens
|
||||
:on-font-shorthand set-shorthands}]]))
|
||||
|
||||
;; SHADOW PANEL
|
||||
:shadow
|
||||
(let [shapes (filter has-shadow? shapes)]
|
||||
(when (seq shapes)
|
||||
[:> style-box* {:panel :shadow}
|
||||
[:> style-box* {:panel :shadow
|
||||
:shorthand (:shadow shorthands)}
|
||||
[:> shadow-panel* {:shapes shapes
|
||||
:color-space color-space}]]))
|
||||
:color-space color-space
|
||||
:on-shadow-shorthand set-shorthands}]]))
|
||||
|
||||
;; DEFAULT WIP
|
||||
[:> style-box* {:panel panel}
|
||||
[:div color-space]])])]))
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
[{:keys [shapes objects]}]
|
||||
[:div {:class (stl/css :blur-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class "blur-shape"}
|
||||
[:div {:key (:id shape) :class (stl/css :blur-shape)}
|
||||
(let [property :filter
|
||||
value (css/get-css-value objects shape property)
|
||||
property-name (cmm/get-css-rule-humanized property)
|
||||
|
||||
@@ -7,9 +7,12 @@
|
||||
(ns app.main.ui.inspect.styles.panels.fill
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.fills :as types.fills]
|
||||
[app.config :as cfg]
|
||||
[app.main.ui.inspect.attributes.common :as cmm]
|
||||
[app.main.ui.inspect.styles.rows.color-properties-row :refer [color-properties-row*]]
|
||||
[app.util.color :as uc]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- get-applied-tokens-in-shape
|
||||
@@ -32,28 +35,56 @@
|
||||
(and (= (:resolved-value resolved-token) (:color color-type))
|
||||
(= 0 idx)))
|
||||
|
||||
(mf/defc fill-panel*
|
||||
[{:keys [shapes resolved-tokens color-space]}]
|
||||
[:div {:class (stl/css :fill-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class "fill-shape"}
|
||||
(for [[idx fill] (map-indexed vector (:fills shape))]
|
||||
(let [property :background
|
||||
color-type (types.fills/fill->color fill) ;; can be :color, :gradient or :image
|
||||
property-name (cmm/get-css-rule-humanized property)
|
||||
resolved-token (get-resolved-token shape resolved-tokens)
|
||||
has-token (has-token? resolved-token color-type idx)]
|
||||
(defn- generate-fill-shorthand
|
||||
[shape]
|
||||
(reduce
|
||||
(fn [acc fill]
|
||||
(let [color-type (types.fills/fill->color fill)
|
||||
color-value (:color color-type)
|
||||
color-gradient (:gradient color-type)
|
||||
gradient-data {:type color-type
|
||||
:stops (:stops color-gradient)}
|
||||
color-image (:image color-type)
|
||||
prefix (if color-value "background-color: " "background-image: ")
|
||||
value (cond
|
||||
(:color color-type) (dm/str color-value)
|
||||
color-gradient (uc/gradient->css gradient-data)
|
||||
color-image (str "url(\"" (cfg/resolve-file-media color-image) "\")")
|
||||
:else "")
|
||||
full-value (str prefix value ";")]
|
||||
(if (empty? acc)
|
||||
full-value
|
||||
(str acc " " full-value))))
|
||||
""
|
||||
(:fills shape)))
|
||||
|
||||
(if (:color color-type)
|
||||
[:> color-properties-row* {:key idx
|
||||
:term property-name
|
||||
:color color-type
|
||||
:token (when has-token resolved-token)
|
||||
:format color-space
|
||||
:copiable true}]
|
||||
(if (or (:gradient color-type) (:image color-type))
|
||||
(mf/defc fill-panel*
|
||||
[{:keys [shapes resolved-tokens color-space on-fill-shorthand]}]
|
||||
(let [shorthand* (mf/use-state #(generate-fill-shorthand (first shapes)))
|
||||
shorthand (deref shorthand*)]
|
||||
(mf/use-effect
|
||||
(mf/deps shorthand on-fill-shorthand shapes)
|
||||
(fn []
|
||||
(reset! shorthand* (generate-fill-shorthand (first shapes)))
|
||||
(on-fill-shorthand {:panel :fill
|
||||
:property shorthand})))
|
||||
[:div {:class (stl/css :fill-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class (stl/css :fill-shape)}
|
||||
(for [[idx fill] (map-indexed vector (:fills shape))]
|
||||
(let [property :background
|
||||
color-type (types.fills/fill->color fill) ;; can be :color, :gradient or :image
|
||||
property-name (cmm/get-css-rule-humanized property)
|
||||
resolved-token (get-resolved-token shape resolved-tokens)
|
||||
has-token (has-token? resolved-token color-type idx)]
|
||||
(if (:color color-type)
|
||||
[:> color-properties-row* {:key idx
|
||||
:term property-name
|
||||
:color color-type
|
||||
:token (when has-token resolved-token)
|
||||
:format color-space
|
||||
:copiable true}]
|
||||
[:span "background-image"]))))])])
|
||||
[:> color-properties-row* {:key idx
|
||||
:term property-name
|
||||
:color color-type
|
||||
:copiable true}])))])]))
|
||||
|
||||
@@ -30,6 +30,15 @@
|
||||
:border-end-start-radius :r3
|
||||
:border-end-end-radius :r4})
|
||||
|
||||
(defn- has-border-radius?
|
||||
"Returns true if the shape has any non-zero border radius values."
|
||||
[shape]
|
||||
(let [radius-keys [:r1 :r2 :r3 :r4]]
|
||||
(some (fn [key]
|
||||
(and (contains? shape key)
|
||||
(not= 0 (get shape key))))
|
||||
radius-keys)))
|
||||
|
||||
(defn- get-applied-tokens-in-shape
|
||||
[shape-tokens property]
|
||||
(let [border-prop (get shape-prop->border-radius-prop property)]
|
||||
@@ -44,19 +53,33 @@
|
||||
token (get resolved-tokens applied-tokens-in-shape)]
|
||||
token))
|
||||
|
||||
(defn- generate-geometry-shorthand
|
||||
[shapes objects]
|
||||
(when (and (= (count shapes) 1) (has-border-radius? (first shapes)))
|
||||
(css/get-css-property objects (first shapes) :border-radius)))
|
||||
|
||||
(mf/defc geometry-panel*
|
||||
[{:keys [shapes objects resolved-tokens]}]
|
||||
[:div {:class (stl/css :geometry-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class "geometry-shape"}
|
||||
(for [property properties]
|
||||
(when-let [value (css/get-css-value objects shape property)]
|
||||
(let [property-name (cmm/get-css-rule-humanized property)
|
||||
resolved-token (get-resolved-token property shape resolved-tokens)
|
||||
property-value (if (not resolved-token) (css/get-css-property objects shape property) "")]
|
||||
[:> properties-row* {:key (dm/str "geometry-property-" property)
|
||||
:term property-name
|
||||
:detail value
|
||||
:token resolved-token
|
||||
:property property-value
|
||||
:copiable true}])))])])
|
||||
[{:keys [shapes objects resolved-tokens on-geometry-shorthand]}]
|
||||
(let [shorthand* (mf/use-state #(generate-geometry-shorthand shapes objects))
|
||||
shorthand (deref shorthand*)]
|
||||
(mf/use-effect
|
||||
(mf/deps shorthand on-geometry-shorthand shapes objects)
|
||||
(fn []
|
||||
(reset! shorthand* (generate-geometry-shorthand shapes objects))
|
||||
(on-geometry-shorthand {:panel :geometry
|
||||
:property shorthand})))
|
||||
[:div {:class (stl/css :geometry-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class (stl/css :geometry-shape)}
|
||||
|
||||
(for [property properties]
|
||||
(when-let [value (css/get-css-value objects shape property)]
|
||||
(let [property-name (cmm/get-css-rule-humanized property)
|
||||
resolved-token (get-resolved-token property shape resolved-tokens)
|
||||
property-value (if (not resolved-token) (css/get-css-property objects shape property) "")]
|
||||
[:> properties-row* {:key (dm/str "geometry-property-" property)
|
||||
:term property-name
|
||||
:detail value
|
||||
:token resolved-token
|
||||
:property property-value
|
||||
:copiable true}])))])]))
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
:padding-block-end :p3
|
||||
:padding-inline-start :p4})
|
||||
|
||||
(defn- has-padding?
|
||||
[shape]
|
||||
(let [padding (:layout-padding shape)
|
||||
padding-keys [:p1 :p2 :p3 :p4]]
|
||||
(some (fn [key]
|
||||
(and (contains? padding key)
|
||||
(not= 0 (get padding key))))
|
||||
padding-keys)))
|
||||
|
||||
(defn- get-applied-tokens-in-shape
|
||||
[shape-tokens property]
|
||||
(let [padding-prop (get shape-prop->padding-prop property)]
|
||||
@@ -51,19 +60,43 @@
|
||||
token (get resolved-tokens applied-tokens-in-shape)]
|
||||
token))
|
||||
|
||||
(defn- generate-layout-shorthand
|
||||
[shapes objects]
|
||||
(let [shape (first shapes)
|
||||
shorthand-padding (when (and (= (count shapes) 1) (has-padding? shape))
|
||||
(css/get-css-property objects shape :padding))
|
||||
shorthand-grid (when (and (= (count shapes) 1)
|
||||
(= :grid (:layout shape)))
|
||||
(str "grid: "
|
||||
(css/get-css-value objects shape :grid-template-rows)
|
||||
" / "
|
||||
(css/get-css-value objects shape :grid-template-columns)
|
||||
";"))
|
||||
shorthand (when (or shorthand-padding shorthand-grid)
|
||||
(str shorthand-grid " " shorthand-padding))]
|
||||
shorthand))
|
||||
|
||||
(mf/defc layout-panel*
|
||||
[{:keys [shapes objects resolved-tokens]}]
|
||||
[:div {:class (stl/css :variants-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class "layout-shape"}
|
||||
(for [property properties]
|
||||
(when-let [value (css/get-css-value objects shape property)]
|
||||
(let [property-name (cmm/get-css-rule-humanized property)
|
||||
resolved-token (get-resolved-token property shape resolved-tokens)
|
||||
property-value (if (not resolved-token) (css/get-css-property objects shape property) "")]
|
||||
[:> properties-row* {:key (dm/str "layout-property-" property)
|
||||
:term property-name
|
||||
:detail value
|
||||
:token resolved-token
|
||||
:property property-value
|
||||
:copiable true}])))])])
|
||||
[{:keys [shapes objects resolved-tokens on-layout-shorthand]}]
|
||||
(let [shorthand* (mf/use-state #(generate-layout-shorthand shapes objects))
|
||||
shorthand (deref shorthand*)]
|
||||
(mf/use-effect
|
||||
(mf/deps shorthand on-layout-shorthand shapes objects)
|
||||
(fn []
|
||||
(reset! shorthand* (generate-layout-shorthand shapes objects))
|
||||
(on-layout-shorthand {:panel :layout
|
||||
:property shorthand})))
|
||||
[:div {:class (stl/css :variants-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class (stl/css :layout-shape)}
|
||||
(for [property properties]
|
||||
(when-let [value (css/get-css-value objects shape property)]
|
||||
(let [property-name (cmm/get-css-rule-humanized property)
|
||||
resolved-token (get-resolved-token property shape resolved-tokens)
|
||||
property-value (if (not resolved-token) (css/get-css-property objects shape property) "")]
|
||||
[:> properties-row* {:key (dm/str "layout-property-" property)
|
||||
:term property-name
|
||||
:detail value
|
||||
:token resolved-token
|
||||
:property property-value
|
||||
:copiable true}])))])]))
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
:min-inline-size :layout-item-min-w ;; :min-width
|
||||
})
|
||||
|
||||
(defn- has-margin?
|
||||
[shape]
|
||||
(let [margin (:layout-item-margin shape)
|
||||
margin-keys [:m1 :m2 :m3 :m4]]
|
||||
(some (fn [key]
|
||||
(and (contains? margin key)
|
||||
(not= 0 (get margin key))))
|
||||
margin-keys)))
|
||||
|
||||
(defn- get-applied-margins-in-shape
|
||||
[shape-tokens property]
|
||||
(if-let [margin-prop (get shape-prop->margin-prop property)]
|
||||
@@ -38,12 +47,40 @@
|
||||
token (get resolved-tokens applied-tokens-in-shape)]
|
||||
token)))
|
||||
|
||||
(defn- generate-layout-element-shorthand
|
||||
[shapes objects]
|
||||
(let [shape (first shapes)
|
||||
shorthand-margin (when (and (= (count shapes) 1) (has-margin? shape))
|
||||
(css/get-css-property objects shape :margin))
|
||||
shorthand-grow (when (and (= (count shapes) 1)
|
||||
(ctl/flex-layout-immediate-child? objects shape))
|
||||
(if-let [flex-value (css/get-css-value objects shape :flex)]
|
||||
flex-value
|
||||
0))
|
||||
shorthand-basis 0 ;; Default-value. Currently not supported in the UI
|
||||
shorthand-shrink (when (and (= (count shapes) 1)
|
||||
(ctl/flex-layout-immediate-child? objects shape))
|
||||
(if-let [flex-shrink-value (css/get-css-value objects shape :flex-shrink)]
|
||||
flex-shrink-value
|
||||
0))
|
||||
shorthand-flex (dm/str "flex: " shorthand-grow " " shorthand-basis " " shorthand-shrink ";")
|
||||
shorthand (dm/str shorthand-margin " " shorthand-flex)]
|
||||
shorthand))
|
||||
|
||||
(mf/defc layout-element-panel*
|
||||
[{:keys [shapes objects resolved-tokens layout-element-properties]}]
|
||||
(let [shapes (->> shapes (filter #(ctl/any-layout-immediate-child? objects %)))]
|
||||
[{:keys [shapes objects resolved-tokens layout-element-properties on-layout-element-shorthand]}]
|
||||
(let [shapes (->> shapes (filter #(ctl/any-layout-immediate-child? objects %)))
|
||||
shorthand* (mf/use-state #(generate-layout-element-shorthand shapes objects))
|
||||
shorthand (deref shorthand*)]
|
||||
(mf/use-effect
|
||||
(mf/deps shorthand on-layout-element-shorthand shapes objects)
|
||||
(fn []
|
||||
(reset! shorthand* (generate-layout-element-shorthand shapes objects))
|
||||
(on-layout-element-shorthand {:panel :layout-element
|
||||
:property shorthand})))
|
||||
[:div {:class (stl/css :layout-element-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class "layout-element-shape"}
|
||||
[:div {:key (:id shape) :class (stl/css :layout-element-shape)}
|
||||
(for [property layout-element-properties]
|
||||
(when-let [value (css/get-css-value objects shape property)]
|
||||
(let [property-name (cmm/get-css-rule-humanized property)
|
||||
|
||||
@@ -12,22 +12,45 @@
|
||||
[app.main.ui.inspect.styles.rows.color-properties-row :refer [color-properties-row*]]
|
||||
[app.main.ui.inspect.styles.rows.properties-row :refer [properties-row*]]
|
||||
[app.util.code-gen.style-css :as css]
|
||||
[app.util.code-gen.style-css-formats :as scf]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- generate-shadow-shorthand
|
||||
[shapes]
|
||||
(when (= (count shapes) 1)
|
||||
(let [shorthand-property (dm/str "box-shadow: ")
|
||||
shorthand-value (reduce
|
||||
(fn [acc shadow]
|
||||
(let [value (scf/format-shadow->css shadow {})]
|
||||
(if (empty? acc)
|
||||
value
|
||||
(dm/str acc ", " value))))
|
||||
""
|
||||
(:shadow (first shapes)))]
|
||||
(dm/str shorthand-property shorthand-value ";"))))
|
||||
|
||||
(mf/defc shadow-panel*
|
||||
[{:keys [shapes color-space]}]
|
||||
[:div {:class (stl/css :shadow-panel)}
|
||||
(for [shape shapes]
|
||||
(for [shadow (:shadow shape)]
|
||||
[:div {:key (dm/str (:id shape) (:type shadow)) :class "shadow-shape"}
|
||||
[:> color-properties-row* {:term "Shadow Color"
|
||||
:color (:color shadow)
|
||||
:format color-space
|
||||
:copiable true}]
|
||||
(let [value (dm/str (:offset-x shadow) "px" " " (:offset-y shadow) "px" " " (:blur shadow) "px" " " (:spread shadow) "px")
|
||||
property-name (cmm/get-css-rule-humanized (:style shadow))
|
||||
property-value (css/shadow->css shadow)]
|
||||
[:> properties-row* {:term property-name
|
||||
:detail (dm/str value)
|
||||
:property property-value
|
||||
:copiable true}])]))])
|
||||
[{:keys [shapes color-space on-shadow-shorthand]}]
|
||||
(let [shorthand* (mf/use-state #(generate-shadow-shorthand shapes))
|
||||
shorthand (deref shorthand*)]
|
||||
(mf/use-effect
|
||||
(mf/deps shorthand on-shadow-shorthand shapes)
|
||||
(fn []
|
||||
(reset! shorthand* (generate-shadow-shorthand shapes))
|
||||
(on-shadow-shorthand {:panel :shadow
|
||||
:property shorthand})))
|
||||
[:div {:class (stl/css :shadow-panel)}
|
||||
(for [shape shapes]
|
||||
(for [[idx shadow] (map-indexed vector (:shadow shape))]
|
||||
[:div {:key (dm/str idx) :class (stl/css :shadow-shape)}
|
||||
[:> color-properties-row* {:term "Shadow Color"
|
||||
:color (:color shadow)
|
||||
:format color-space
|
||||
:copiable true}]
|
||||
(let [value (dm/str (:offset-x shadow) "px" " " (:offset-y shadow) "px" " " (:blur shadow) "px" " " (:spread shadow) "px")
|
||||
property-name (cmm/get-css-rule-humanized (:style shadow))
|
||||
property-value (css/shadow->css shadow)]
|
||||
[:> properties-row* {:term property-name
|
||||
:detail (dm/str value)
|
||||
:property property-value
|
||||
:copiable true}])]))]))
|
||||
|
||||
@@ -9,22 +9,17 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.config :as cfg]
|
||||
[app.main.ui.inspect.attributes.common :as cmm]
|
||||
[app.main.ui.inspect.styles.rows.color-properties-row :refer [color-properties-row*]]
|
||||
[app.main.ui.inspect.styles.rows.properties-row :refer [properties-row*]]
|
||||
[app.util.code-gen.style-css :as css]
|
||||
[app.util.color :as uc]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def ^:private properties [:border-color :border-style :border-width])
|
||||
|
||||
(defn- stroke->color [shape]
|
||||
{:color (:stroke-color shape)
|
||||
:opacity (:stroke-opacity shape)
|
||||
:gradient (:stroke-color-gradient shape)
|
||||
:id (:stroke-color-ref-id shape)
|
||||
:file-id (:stroke-color-ref-file shape)
|
||||
:image (:stroke-image shape)})
|
||||
|
||||
(def ^:private shape-prop->stroke-prop
|
||||
{:border-style :stroke-style
|
||||
:border-width :stroke-width
|
||||
@@ -57,29 +52,62 @@
|
||||
(and (= (:resolved-value resolved-token) (:color stroke-type))
|
||||
(is-first-element? idx)))
|
||||
|
||||
(defn- generate-stroke-shorthand
|
||||
[shapes]
|
||||
(when (= (count shapes) 1)
|
||||
(let [shape (first shapes)]
|
||||
(reduce
|
||||
(fn [acc stroke]
|
||||
(let [stroke-type (ctc/stroke->color stroke)
|
||||
stroke-width (:stroke-width stroke)
|
||||
stroke-style (:stroke-style stroke)
|
||||
color-value (:color stroke-type)
|
||||
color-gradient (:gradient stroke-type)
|
||||
gradient-data {:type (get-in stroke-type [:gradient :type])
|
||||
:stops (get-in stroke-type [:gradient :stops])}
|
||||
color-image (:image stroke-type)
|
||||
value (cond
|
||||
color-value (dm/str "border: " stroke-width "px " (d/name stroke-style) " " color-value ";")
|
||||
color-gradient (dm/str "border-image: " (uc/gradient->css gradient-data) " 100 / " stroke-width "px;")
|
||||
color-image (dm/str "border-image: url(" (cfg/resolve-file-media color-image) ") 100 / " stroke-width "px;")
|
||||
:else "")]
|
||||
(if (empty? acc)
|
||||
value
|
||||
(str acc " " value))))
|
||||
""
|
||||
(:strokes shape)))))
|
||||
|
||||
(mf/defc stroke-panel*
|
||||
[{:keys [shapes objects resolved-tokens color-space]}]
|
||||
[:div {:class (stl/css :stroke-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class "stroke-shape"}
|
||||
(for [[idx stroke] (map-indexed vector (:strokes shape))]
|
||||
(for [property properties]
|
||||
(let [value (css/get-css-value objects stroke property)
|
||||
stroke-type (stroke->color stroke)
|
||||
property-name (cmm/get-css-rule-humanized property)
|
||||
property-value (css/get-css-property objects stroke property)
|
||||
resolved-token (when (is-first-element? idx) (get-resolved-token property shape resolved-tokens))
|
||||
has-color-token (has-color-token? resolved-token stroke-type idx)]
|
||||
(if (= property :border-color)
|
||||
[:> color-properties-row* {:key (str idx property)
|
||||
:term property-name
|
||||
:color stroke-type
|
||||
:token (when has-color-token resolved-token)
|
||||
:format color-space
|
||||
:copiable true}]
|
||||
[:> properties-row* {:key (str idx property)
|
||||
:term (d/name property-name)
|
||||
:detail (dm/str value)
|
||||
:token resolved-token
|
||||
:property property-value
|
||||
:copiable true}]))))])])
|
||||
[{:keys [shapes objects resolved-tokens color-space on-stroke-shorthand]}]
|
||||
(let [shorthand* (mf/use-state #(generate-stroke-shorthand shapes))
|
||||
shorthand (deref shorthand*)]
|
||||
(mf/use-effect
|
||||
(mf/deps shorthand on-stroke-shorthand shapes)
|
||||
(fn []
|
||||
(reset! shorthand* (generate-stroke-shorthand shapes))
|
||||
(on-stroke-shorthand {:panel :stroke
|
||||
:property shorthand})))
|
||||
[:div {:class (stl/css :stroke-panel)}
|
||||
(for [shape shapes]
|
||||
[:div {:key (:id shape) :class (stl/css :stroke-shape)}
|
||||
(for [[idx stroke] (map-indexed vector (:strokes shape))]
|
||||
(for [property properties]
|
||||
(let [value (css/get-css-value objects stroke property)
|
||||
stroke-type (ctc/stroke->color stroke)
|
||||
property-name (cmm/get-css-rule-humanized property)
|
||||
property-value (css/get-css-property objects stroke property)
|
||||
resolved-token (when (is-first-element? idx) (get-resolved-token property shape resolved-tokens))
|
||||
has-color-token (has-color-token? resolved-token stroke-type idx)]
|
||||
(if (= property :border-color)
|
||||
[:> color-properties-row* {:key (str idx property)
|
||||
:term property-name
|
||||
:color stroke-type
|
||||
:token (when has-color-token resolved-token)
|
||||
:format color-space
|
||||
:copiable true}]
|
||||
[:> properties-row* {:key (str idx property)
|
||||
:term (d/name property-name)
|
||||
:detail (dm/str value)
|
||||
:token resolved-token
|
||||
:property property-value
|
||||
:copiable true}]))))])]))
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
(ns app.main.ui.inspect.styles.panels.text
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.fills :as types.fills]
|
||||
[app.common.types.text :as txt]
|
||||
[app.main.fonts :as fonts]
|
||||
@@ -38,6 +39,23 @@
|
||||
(remove (fn [[_ text]] (str/empty? (str/trim text))))
|
||||
(mapv (fn [[style text]] (vector (merge (txt/get-default-text-attrs) style) text)))))
|
||||
|
||||
(defn- generate-typography-shorthand
|
||||
[shapes]
|
||||
(when (= (count shapes) 1)
|
||||
(let [shape (first shapes)
|
||||
style-text-blocks (get-style-text shape)]
|
||||
(reduce
|
||||
(fn [acc [style _]]
|
||||
(let [font-style (:font-style style)
|
||||
font-family (dm/str (:font-family style))
|
||||
font-size (:font-size style)
|
||||
font-weight (:font-weight style)
|
||||
line-height (:line-height style)
|
||||
text-transform (:text-transform style)]
|
||||
(dm/str acc "font:" font-style " " text-transform " " font-weight " " font-size "/" line-height " " \" font-family \" ";")))
|
||||
""
|
||||
style-text-blocks))))
|
||||
|
||||
(mf/defc typography-name-block*
|
||||
[{:keys [style]}]
|
||||
(let [typography (ict/get-typography style)
|
||||
@@ -59,126 +77,133 @@
|
||||
:copiable true}]))
|
||||
|
||||
(mf/defc text-panel*
|
||||
[{:keys [shapes _ resolved-tokens color-space]}]
|
||||
[:div {:class (stl/css :text-panel)}
|
||||
(for [shape shapes]
|
||||
(let [style-text-blocks (get-style-text shape)
|
||||
composite-typography-token (get-resolved-token :typography shape resolved-tokens)]
|
||||
[{:keys [shapes resolved-tokens color-space on-font-shorthand]}]
|
||||
(let [shorthand* (mf/use-state #(generate-typography-shorthand shapes))
|
||||
shorthand (deref shorthand*)]
|
||||
(mf/use-effect
|
||||
(mf/deps shorthand on-font-shorthand shapes)
|
||||
(fn []
|
||||
(reset! shorthand* (generate-typography-shorthand shapes))
|
||||
(on-font-shorthand {:panel :text
|
||||
:property shorthand})))
|
||||
[:div {:class (stl/css :text-panel)}
|
||||
(for [shape shapes]
|
||||
(let [style-text-blocks (get-style-text shape)
|
||||
composite-typography-token (get-resolved-token :typography shape resolved-tokens)]
|
||||
[:div {:key (:id shape) :class (stl/css :text-shape)}
|
||||
(for [[style text] style-text-blocks]
|
||||
|
||||
[:div {:key (:id shape) :class "text-shape"}
|
||||
(for [[style text] style-text-blocks]
|
||||
[:div {:key (:id shape) :class (stl/css :text-properties)}
|
||||
|
||||
[:div {:key (:id shape) :class "text-properties"}
|
||||
|
||||
(when (:fills style)
|
||||
(for [[idx fill] (map-indexed vector (:fills style))]
|
||||
[:> typography-color-row* {:key idx
|
||||
:fill fill
|
||||
:shape shape
|
||||
:resolved-tokens resolved-tokens
|
||||
:color-space color-space}]))
|
||||
(when (:fills style)
|
||||
(for [[idx fill] (map-indexed vector (:fills style))]
|
||||
[:> typography-color-row* {:key idx
|
||||
:fill fill
|
||||
:shape shape
|
||||
:resolved-tokens resolved-tokens
|
||||
:color-space color-space}]))
|
||||
|
||||
;; Typography style
|
||||
(when (and (not composite-typography-token)
|
||||
(:typography-ref-id style))
|
||||
[:> typography-name-block* {:style style}])
|
||||
(when (and (not composite-typography-token)
|
||||
(:typography-ref-id style))
|
||||
[:> typography-name-block* {:style style}])
|
||||
|
||||
;; Composite Typography token
|
||||
(when (and (not (:typography-ref-id style))
|
||||
composite-typography-token)
|
||||
[:> properties-row* {:term "Typography"
|
||||
:detail (:name composite-typography-token)
|
||||
:token composite-typography-token
|
||||
:property (:name composite-typography-token)
|
||||
:copiable true}])
|
||||
(when (and (not (:typography-ref-id style))
|
||||
composite-typography-token)
|
||||
[:> properties-row* {:term "Typography"
|
||||
:detail (:name composite-typography-token)
|
||||
:token composite-typography-token
|
||||
:property (:name composite-typography-token)
|
||||
:copiable true}])
|
||||
|
||||
(when (:font-id style)
|
||||
(let [name (get (fonts/get-font-data (:font-id style)) :name)
|
||||
resolved-token (get-resolved-token :font-family shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Font Family"
|
||||
:detail name
|
||||
:token resolved-token
|
||||
:property (str "font-family: \"" name "\";")
|
||||
:copiable true}]))
|
||||
(when (:font-id style)
|
||||
(let [name (get (fonts/get-font-data (:font-id style)) :name)
|
||||
resolved-token (get-resolved-token :font-family shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Font Family"
|
||||
:detail name
|
||||
:token resolved-token
|
||||
:property (str "font-family: \"" name "\";")
|
||||
:copiable true}]))
|
||||
|
||||
(when (:font-style style)
|
||||
[:> properties-row* {:term "Font Style"
|
||||
:detail (:font-style style)
|
||||
:property (str "font-style: " (:font-style style) ";")
|
||||
:copiable true}])
|
||||
(when (:font-style style)
|
||||
[:> properties-row* {:term "Font Style"
|
||||
:detail (:font-style style)
|
||||
:property (str "font-style: " (:font-style style) ";")
|
||||
:copiable true}])
|
||||
|
||||
(when (:font-size style)
|
||||
(let [font-size (fmt/format-pixels (:font-size style))
|
||||
resolved-token (get-resolved-token :font-size shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Font Size"
|
||||
:detail font-size
|
||||
:token resolved-token
|
||||
:property (str "font-size: " font-size ";")
|
||||
:copiable true}]))
|
||||
(when (:font-weight style)
|
||||
(let [resolved-token (get-resolved-token :font-weight shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Font Weight"
|
||||
:detail (:font-weight style)
|
||||
:token resolved-token
|
||||
:property (str "font-weight: " (:font-weight style) ";")
|
||||
:copiable true}]))
|
||||
(when (:font-size style)
|
||||
(let [font-size (fmt/format-pixels (:font-size style))
|
||||
resolved-token (get-resolved-token :font-size shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Font Size"
|
||||
:detail font-size
|
||||
:token resolved-token
|
||||
:property (str "font-size: " font-size ";")
|
||||
:copiable true}]))
|
||||
(when (:font-weight style)
|
||||
(let [resolved-token (get-resolved-token :font-weight shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Font Weight"
|
||||
:detail (:font-weight style)
|
||||
:token resolved-token
|
||||
:property (str "font-weight: " (:font-weight style) ";")
|
||||
:copiable true}]))
|
||||
|
||||
(when (:line-height style)
|
||||
(let [line-height (:line-height style)
|
||||
resolved-token (get-resolved-token :line-height shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Line Height"
|
||||
:detail (str line-height)
|
||||
:token resolved-token
|
||||
:property (str "line-height: " line-height ";")
|
||||
:copiable true}]))
|
||||
(when (:line-height style)
|
||||
(let [line-height (:line-height style)
|
||||
resolved-token (get-resolved-token :line-height shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Line Height"
|
||||
:detail (str line-height)
|
||||
:token resolved-token
|
||||
:property (str "line-height: " line-height ";")
|
||||
:copiable true}]))
|
||||
|
||||
(when (:letter-spacing style)
|
||||
(let [letter-spacing (fmt/format-pixels (:letter-spacing style))
|
||||
resolved-token (get-resolved-token :letter-spacing shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Letter Spacing"
|
||||
:detail letter-spacing
|
||||
:token resolved-token
|
||||
:property (str "letter-spacing: " letter-spacing ";")
|
||||
:copiable true}]))
|
||||
(when (:letter-spacing style)
|
||||
(let [letter-spacing (fmt/format-pixels (:letter-spacing style))
|
||||
resolved-token (get-resolved-token :letter-spacing shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Letter Spacing"
|
||||
:detail letter-spacing
|
||||
:token resolved-token
|
||||
:property (str "letter-spacing: " letter-spacing ";")
|
||||
:copiable true}]))
|
||||
|
||||
(when (:text-decoration style)
|
||||
(let [resolved-token (get-resolved-token :text-decoration shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Text Decoration"
|
||||
:detail (:text-decoration style)
|
||||
:token resolved-token
|
||||
:property (str "text-decoration: " (:text-decoration style) ";")
|
||||
:copiable true}]))
|
||||
(when (:text-decoration style)
|
||||
(let [resolved-token (get-resolved-token :text-decoration shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Text Decoration"
|
||||
:detail (:text-decoration style)
|
||||
:token resolved-token
|
||||
:property (str "text-decoration: " (:text-decoration style) ";")
|
||||
:copiable true}]))
|
||||
|
||||
(when (:text-transform style)
|
||||
(let [resolved-token (get-resolved-token :text-case shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Text Transform"
|
||||
:detail (:text-transform style)
|
||||
:token resolved-token
|
||||
:property (str "text-transform: " (:text-transform style) ";")
|
||||
:copiable true}]))
|
||||
(when text
|
||||
(let [copied* (mf/use-state false)
|
||||
copied (deref copied*)
|
||||
(when (:text-transform style)
|
||||
(let [resolved-token (get-resolved-token :text-case shape resolved-tokens)]
|
||||
[:> properties-row* {:term "Text Transform"
|
||||
:detail (:text-transform style)
|
||||
:token resolved-token
|
||||
:property (str "text-transform: " (:text-transform style) ";")
|
||||
:copiable true}]))
|
||||
(when text
|
||||
(let [copied* (mf/use-state false)
|
||||
copied (deref copied*)
|
||||
|
||||
text (str/trim text)
|
||||
text (str/trim text)
|
||||
|
||||
copy-text
|
||||
(mf/use-fn
|
||||
(mf/deps copied)
|
||||
(fn []
|
||||
(let [formatted-text (if (= (:text-transform style) "uppercase")
|
||||
(.toUpperCase text)
|
||||
text)]
|
||||
(reset! copied* true)
|
||||
(wapi/write-to-clipboard formatted-text)
|
||||
(tm/schedule 1000 #(reset! copied* false)))))]
|
||||
[:div {:class (stl/css :text-content-wrapper)}
|
||||
[:> property-detail-copiable* {:copied copied
|
||||
:on-click copy-text}
|
||||
[:span {:class (stl/css :text-content)
|
||||
:style {:font-family (:font-family style)
|
||||
:font-weight (:font-weight style)
|
||||
:text-transform (:text-transform style)
|
||||
:letter-spacing (fmt/format-pixels (:letter-spacing style))
|
||||
:font-style (:font-style style)}}
|
||||
text]]]))])]))])
|
||||
copy-text
|
||||
(mf/use-fn
|
||||
(mf/deps copied)
|
||||
(fn []
|
||||
(let [formatted-text (if (= (:text-transform style) "uppercase")
|
||||
(.toUpperCase text)
|
||||
text)]
|
||||
(reset! copied* true)
|
||||
(wapi/write-to-clipboard formatted-text)
|
||||
(tm/schedule 1000 #(reset! copied* false)))))]
|
||||
[:div {:class (stl/css :text-content-wrapper)}
|
||||
[:> property-detail-copiable* {:copied copied
|
||||
:on-click copy-text}
|
||||
[:span {:class (stl/css :text-content)
|
||||
:style {:font-family (:font-family style)
|
||||
:font-weight (:font-weight style)
|
||||
:text-transform (:text-transform style)
|
||||
:letter-spacing (fmt/format-pixels (:letter-spacing style))
|
||||
:font-style (:font-style style)}}
|
||||
text]]]))])]))]))
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
[{:keys [class term color format token]}]
|
||||
(let [copied* (mf/use-state false)
|
||||
copied (deref copied*)
|
||||
|
||||
color-value (:color color)
|
||||
color-gradient (:gradient color)
|
||||
color-image (:image color)
|
||||
|
||||
@@ -48,8 +48,9 @@
|
||||
|
||||
copy-shorthand
|
||||
(mf/use-fn
|
||||
(mf/deps shorthand)
|
||||
(fn []
|
||||
(wapi/write-to-clipboard (str "Style: " title))))]
|
||||
(wapi/write-to-clipboard (str shorthand))))]
|
||||
[:article {:class (stl/css :style-box)}
|
||||
[:header {:class (stl/css :disclosure-header)}
|
||||
[:button {:class (stl/css :disclosure-button)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
.disclosure-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--title-gap);
|
||||
padding-block: var(--title-padding);
|
||||
}
|
||||
|
||||
@@ -1904,7 +1904,7 @@ msgstr "Info"
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:66
|
||||
#, fuzzy
|
||||
msgid "inspect.tabs.styles.panel.copy-style-shorthand"
|
||||
msgstr ""
|
||||
msgstr "Copy CSS shorthand to clipboard"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
|
||||
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
|
||||
|
||||
@@ -1896,6 +1896,23 @@ msgstr "Calculado"
|
||||
msgid "inspect.tabs.info"
|
||||
msgstr "Información"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:66
|
||||
#, fuzzy
|
||||
msgid "inspect.tabs.styles.panel.copy-style-shorthand"
|
||||
msgstr "Copiar CSS shorthand al portapapeles"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:52
|
||||
msgid "inspect.tabs.styles.panel.copy-to-clipboard"
|
||||
msgstr "Copiar al portapapeles"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
|
||||
msgid "inspect.tabs.styles.panel.tokens.active-sets"
|
||||
msgstr "Sets activos"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
|
||||
msgid "inspect.tabs.styles.panel.tokens.active-themes"
|
||||
msgstr "Temas activos"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:22
|
||||
msgid "inspect.tabs.styles.panel.geometry"
|
||||
msgstr "Tamaño y posición"
|
||||
|
||||
Reference in New Issue
Block a user