mirror of
https://github.com/penpot/penpot.git
synced 2026-07-20 13:08:23 +00:00
🎉 Add text panel to inspect styles tab (#7413)
This commit is contained in:
parent
2548bec651
commit
253605f6cc
@ -13,29 +13,18 @@
|
||||
[app.common.types.fills :as types.fills]
|
||||
[app.common.types.text :as types.text]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.copy-button :refer [copy-button*]]
|
||||
[app.main.ui.components.title-bar :refer [inspect-title-bar*]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.inspect.attributes.common :refer [color-row]]
|
||||
[app.main.ui.inspect.common.typography :as ict]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- has-text? [shape]
|
||||
(:content shape))
|
||||
|
||||
(def ^:private file-typographies-ref
|
||||
(l/derived (l/in [:viewer :file :data :typographies]) st/state))
|
||||
|
||||
(defn- make-typographies-library-ref [file-id]
|
||||
(let [get-library
|
||||
(fn [state]
|
||||
(get-in state [:viewer-libraries file-id :data :typographies]))]
|
||||
#(l/derived get-library st/state)))
|
||||
|
||||
(defn- copy-style-data
|
||||
[style & properties]
|
||||
(->> properties
|
||||
@ -44,24 +33,10 @@
|
||||
|
||||
(mf/defc typography-block
|
||||
[{:keys [text style]}]
|
||||
(let [typography-library-ref
|
||||
(mf/use-memo
|
||||
(mf/deps (:typography-ref-file style))
|
||||
(make-typographies-library-ref (:typography-ref-file style)))
|
||||
|
||||
typography-library (mf/deref typography-library-ref)
|
||||
|
||||
;; FIXME: too many duplicate operations
|
||||
file-typographies-viewer (mf/deref file-typographies-ref)
|
||||
file-typographies-workspace (mf/deref refs/workspace-file-typography)
|
||||
|
||||
file-library-workspace (get (mf/deref refs/files) (:typography-ref-file style))
|
||||
typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)])
|
||||
|
||||
color-format* (mf/use-state :hex)
|
||||
(let [color-format* (mf/use-state :hex)
|
||||
color-format (deref color-format*)
|
||||
|
||||
typography (or (get (or typography-library file-typographies-viewer file-typographies-workspace) (:typography-ref-id style)) typography-external-lib)]
|
||||
typography (ict/get-typography style)]
|
||||
|
||||
[:div {:class (stl/css :attributes-content)}
|
||||
(when (:fills style)
|
||||
|
||||
38
frontend/src/app/main/ui/inspect/common/typography.cljs
Normal file
38
frontend/src/app/main/ui/inspect/common/typography.cljs
Normal file
@ -0,0 +1,38 @@
|
||||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.inspect.common.typography
|
||||
(:require
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- make-typographies-library-ref
|
||||
[file-id]
|
||||
(let [get-library
|
||||
(fn [state]
|
||||
(get-in state [:viewer-libraries file-id :data :typographies]))]
|
||||
#(l/derived get-library st/state)))
|
||||
|
||||
(def ^:private file-typographies-ref
|
||||
(l/derived (l/in [:viewer :file :data :typographies]) st/state))
|
||||
|
||||
(defn get-typography
|
||||
[style]
|
||||
(let [typography-library-ref
|
||||
(mf/use-memo
|
||||
(mf/deps (:typography-ref-file style))
|
||||
(make-typographies-library-ref (:typography-ref-file style)))
|
||||
|
||||
; FIXME: too many duplicate operations
|
||||
typography-library (mf/deref typography-library-ref)
|
||||
file-typographies-viewer (mf/deref file-typographies-ref)
|
||||
file-typographies-workspace (mf/deref refs/workspace-file-typography)
|
||||
file-library-workspace (get (mf/deref refs/files) (:typography-ref-file style))
|
||||
typography-external-lib (get-in file-library-workspace [:data :typographies (:typography-ref-id style)])
|
||||
typography (or (get (or typography-library file-typographies-viewer file-typographies-workspace) (:typography-ref-id style)) typography-external-lib)]
|
||||
typography))
|
||||
@ -22,6 +22,7 @@
|
||||
[app.main.ui.inspect.styles.panels.layout-element :refer [layout-element-panel*]]
|
||||
[app.main.ui.inspect.styles.panels.stroke :refer [stroke-panel*]]
|
||||
[app.main.ui.inspect.styles.panels.svg :refer [svg-panel*]]
|
||||
[app.main.ui.inspect.styles.panels.text :refer [text-panel*]]
|
||||
[app.main.ui.inspect.styles.panels.tokens-panel :refer [tokens-panel*]]
|
||||
[app.main.ui.inspect.styles.panels.variants-panel :refer [variants-panel*]]
|
||||
[app.main.ui.inspect.styles.panels.visibility :refer [visibility-panel*]]
|
||||
@ -71,6 +72,9 @@
|
||||
(defn- has-blur? [shape]
|
||||
(:blur shape))
|
||||
|
||||
(defn- has-text? [shape]
|
||||
(:content shape))
|
||||
|
||||
(defn- get-shape-type
|
||||
[shapes first-shape first-component]
|
||||
(if (= (count shapes) 1)
|
||||
@ -195,6 +199,14 @@
|
||||
[:> style-box* {:panel :blur}
|
||||
[:> blur-panel* {:shapes shapes
|
||||
:objects objects}]]))
|
||||
:text
|
||||
(let [shapes (filter has-text? shapes)]
|
||||
(when (seq shapes)
|
||||
[:> style-box* {:panel :text}
|
||||
[:> text-panel* {:shapes shapes
|
||||
:color-space color-space
|
||||
:objects objects
|
||||
:resolved-tokens resolved-active-tokens}]]))
|
||||
;; DEFAULT WIP
|
||||
[:> style-box* {:panel panel}
|
||||
[:div color-space]])])]))
|
||||
|
||||
@ -30,9 +30,9 @@
|
||||
:term (d/name sub-attr-key)
|
||||
:detail (dm/str sub-attr-value)
|
||||
:property property-value
|
||||
:copiable false}]))
|
||||
:copiable true}]))
|
||||
[:> properties-row* {:key (dm/str "svg-property-" (d/name attr-key))
|
||||
:term (d/name attr-key)
|
||||
:detail (dm/str attr-value)
|
||||
:property (dm/str attr-key ": " attr-value ";")
|
||||
:copiable false}]))]])
|
||||
:copiable true}]))]])
|
||||
|
||||
171
frontend/src/app/main/ui/inspect/styles/panels/text.cljs
Normal file
171
frontend/src/app/main/ui/inspect/styles/panels/text.cljs
Normal file
@ -0,0 +1,171 @@
|
||||
;; 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/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.inspect.styles.panels.text
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.types.fills :as types.fills]
|
||||
[app.common.types.text :as txt]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.inspect.common.typography :as ict]
|
||||
[app.main.ui.inspect.styles.property-detail-copiable :refer [property-detail-copiable*]]
|
||||
[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.timers :as tm]
|
||||
[app.util.webapi :as wapi]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- get-applied-tokens-in-shape
|
||||
[shape-tokens property]
|
||||
(get shape-tokens property))
|
||||
|
||||
(defn- get-resolved-token
|
||||
[property shape resolved-tokens]
|
||||
(let [shape-tokens (:applied-tokens shape)
|
||||
applied-tokens-in-shape (get-applied-tokens-in-shape shape-tokens property)
|
||||
token (get resolved-tokens applied-tokens-in-shape)]
|
||||
token))
|
||||
|
||||
(defn- get-style-text
|
||||
[shape]
|
||||
(->> (:content shape)
|
||||
(txt/content->text+styles)
|
||||
(remove (fn [[_ text]] (str/empty? (str/trim text))))
|
||||
(mapv (fn [[style text]] (vector (merge (txt/get-default-text-attrs) style) text)))))
|
||||
|
||||
(mf/defc typography-name-block*
|
||||
[{:keys [style]}]
|
||||
(let [typography (ict/get-typography style)
|
||||
property-value (:name typography)]
|
||||
(when typography
|
||||
[:> properties-row* {:term "Typography"
|
||||
:detail (:name typography)
|
||||
:property property-value
|
||||
:copiable true}])))
|
||||
|
||||
(mf/defc typography-color-row*
|
||||
[{:keys [fill shape resolved-tokens color-space]}]
|
||||
(let [color (types.fills/fill->color fill)
|
||||
resolved-token (get-resolved-token :fill shape resolved-tokens)]
|
||||
[:> color-properties-row* {:term "Font Color"
|
||||
:color color
|
||||
:token resolved-token
|
||||
:format color-space
|
||||
: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)]
|
||||
|
||||
[:div {:key (:id shape) :class "text-shape"}
|
||||
(for [[style text] style-text-blocks]
|
||||
|
||||
[: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 (:typography-ref-id style)
|
||||
[:> typography-name-block* {:style style}])
|
||||
|
||||
(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-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 (: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-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)
|
||||
|
||||
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]]]))])]))])
|
||||
17
frontend/src/app/main/ui/inspect/styles/panels/text.scss
Normal file
17
frontend/src/app/main/ui/inspect/styles/panels/text.scss
Normal file
@ -0,0 +1,17 @@
|
||||
// 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/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "ds/_borders.scss" as *;
|
||||
|
||||
.text-content-wrapper {
|
||||
--border-color: var(--color-background-quaternary);
|
||||
--border-radius: ${$br-8};
|
||||
--text-color: var(--color-foreground-secondary);
|
||||
|
||||
border: $b-1 solid var(--border-color);
|
||||
border-radius: var(--border-radius);
|
||||
color: var(--text-color);
|
||||
}
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
(def ^:private schema:property-detail-copiable
|
||||
[:map
|
||||
[:detail :string]
|
||||
[:color {:optional true} :any] ;; color object with :color, :gradient or :image
|
||||
[:token {:optional true} :any] ;; resolved token object
|
||||
[:copied :boolean]
|
||||
@ -24,7 +23,7 @@
|
||||
|
||||
(mf/defc property-detail-copiable*
|
||||
{::mf/schema schema:property-detail-copiable}
|
||||
[{:keys [detail color token copied on-click]}]
|
||||
[{:keys [color token copied on-click children]}]
|
||||
[:button {:class (stl/css-case :property-detail-copiable true
|
||||
:property-detail-copied copied
|
||||
:property-detail-copiable-color (some? color))
|
||||
@ -45,7 +44,7 @@
|
||||
color-library-name (get-in (or colors-library file-colors) [(:ref-id color) :name])
|
||||
color (assoc color :name color-library-name)]
|
||||
[:span {:class (stl/css :property-detail-text)} (:name color)])
|
||||
[:span {:class (stl/css :property-detail-text)} detail]))
|
||||
[:span {:class (stl/css :property-detail-text)} children]))
|
||||
[:> icon* {:class (stl/css :property-detail-icon)
|
||||
:icon-id (if copied i/tick i/clipboard)
|
||||
:size "s"
|
||||
|
||||
@ -101,18 +101,16 @@
|
||||
[:div {:class (stl/css :tooltip-token-title)}
|
||||
(tr "inspect.tabs.styles.token.resolved-value")]
|
||||
[:div {:class (stl/css :tooltip-token-value)}
|
||||
(:value token)]])}
|
||||
[:> property-detail-copiable* {:detail formatted-color-value
|
||||
:color color
|
||||
(:resolved-value token)]])}
|
||||
[:> property-detail-copiable* {:color color
|
||||
:token token
|
||||
:copied copied
|
||||
:on-click copy-attr}]]
|
||||
:on-click copy-attr} formatted-color-value]]
|
||||
|
||||
|
||||
[:> property-detail-copiable* {:detail formatted-color-value
|
||||
:color color
|
||||
[:> property-detail-copiable* {:color color
|
||||
:copied copied
|
||||
:on-click copy-attr}])]]
|
||||
:on-click copy-attr} formatted-color-value])]]
|
||||
(when (:image color)
|
||||
[:div {:class (stl/css :color-image-preview)}
|
||||
[:div {:class (stl/css :color-image-preview-wrapper)}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
(ns app.main.ui.inspect.styles.rows.properties-row
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.ui.ds.tooltip :refer [tooltip*]]
|
||||
[app.main.ui.inspect.styles.property-detail-copiable :refer [property-detail-copiable*]]
|
||||
[app.util.i18n :refer [tr]]
|
||||
@ -26,7 +27,7 @@
|
||||
(mf/defc properties-row*
|
||||
{::mf/schema schema:properties-row}
|
||||
[{:keys [class term detail token property copiable]}]
|
||||
(let [copiable? (or copiable false)
|
||||
(let [copiable? (d/nilv copiable false)
|
||||
detail? (not (or (nil? detail) (str/blank? detail)))
|
||||
detail (if detail? detail "-")
|
||||
copied* (mf/use-state false)
|
||||
@ -51,12 +52,10 @@
|
||||
:content #(mf/html
|
||||
[:div {:class (stl/css :tooltip-token)}
|
||||
[:div {:class (stl/css :tooltip-token-title)} (tr "inspect.tabs.styles.token.resolved-value")]
|
||||
[:div {:class (stl/css :tooltip-token-value)} (:value token)]])}
|
||||
[:> property-detail-copiable* {:detail detail
|
||||
:token token
|
||||
[:div {:class (stl/css :tooltip-token-value)} (:resolved-value token)]])}
|
||||
[:> property-detail-copiable* {:token token
|
||||
:copied copied
|
||||
:on-click copy-attr}]]
|
||||
[:> property-detail-copiable* {:detail detail
|
||||
:copied copied
|
||||
:on-click copy-attr}])
|
||||
:on-click copy-attr} detail]]
|
||||
[:> property-detail-copiable* {:copied copied
|
||||
:on-click copy-attr} detail])
|
||||
detail)]]))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user