From 8bb210e7b69990feeaa8852f3faf6dace4907228 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 9 Jul 2025 17:02:23 +0200 Subject: [PATCH] :tada: Add binary fills integration --- common/src/app/common/files/builder.cljc | 2 +- common/src/app/common/types/fills.cljc | 14 +-- common/src/app/common/types/fills/impl.cljc | 21 +++- common/src/app/common/types/path.cljc | 4 +- common/src/app/common/types/path/bool.cljc | 10 +- common/src/app/common/types/shape.cljc | 14 ++- common/src/app/common/types/text.cljc | 36 ++++-- frontend/src/app/main/data/helpers.cljs | 17 +++ .../src/app/main/data/workspace/bool.cljs | 4 +- .../app/main/data/workspace/clipboard.cljs | 2 +- .../src/app/main/data/workspace/colors.cljs | 108 ++++++++---------- .../src/app/main/data/workspace/media.cljs | 37 +++--- .../src/app/main/data/workspace/texts.cljs | 32 ++++-- frontend/src/app/main/fonts.cljs | 2 +- .../app/main/ui/inspect/attributes/text.cljs | 2 +- frontend/src/app/main/ui/shapes/text.cljs | 2 +- .../src/app/main/ui/shapes/text/styles.cljs | 6 +- .../ui/workspace/shapes/text/v2_editor.cljs | 4 +- .../workspace/sidebar/options/menus/text.cljs | 2 +- .../sidebar/options/menus/typography.cljs | 6 +- .../sidebar/options/shapes/multiple.cljs | 5 +- .../src/app/util/text/content/to_dom.cljs | 4 +- frontend/src/debug.cljs | 9 ++ .../logic/components_and_tokens.cljs | 2 +- .../tokens/logic/token_actions_test.cljs | 12 +- 25 files changed, 210 insertions(+), 147 deletions(-) diff --git a/common/src/app/common/files/builder.cljc b/common/src/app/common/files/builder.cljc index aa8601bba3..181824c672 100644 --- a/common/src/app/common/files/builder.cljc +++ b/common/src/app/common/files/builder.cljc @@ -356,7 +356,7 @@ (first children) (last children)) fills (if (and (contains? head :svg-attrs) (empty? (:fills head))) - types.path/default-bool-fills + (types.path/get-default-bool-fills) (get head :fills))] (-> bool-shape (assoc :fills fills) diff --git a/common/src/app/common/types/fills.cljc b/common/src/app/common/types/fills.cljc index 0a476e1343..910f476a69 100644 --- a/common/src/app/common/types/fills.cljc +++ b/common/src/app/common/types/fills.cljc @@ -83,20 +83,12 @@ :else (ex/raise :type :internal :code :invalid-type - :hint (str "cannot coerce " (pr-str o) "to fills")))) + :hint (str "cannot coerce " (pr-str o) " to fills")))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; HELPERS +;; TYPE HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; FIXME: duplicated of `assoc` -(defn assoc-fill - [fills position fill] - (if (nil? fills) - (impl/from-plain [fill]) - (-> (coerce fills) - (c/assoc position fill)))) - (defn get-image-ids [fills] (if (vector? fills) @@ -136,7 +128,7 @@ fills (apply f fills args)] (if (contains? flags/*current* :frontend-binary-fills) (impl/from-plain fills) - fills))) + (vec fills)))) (defn create [& elements] diff --git a/common/src/app/common/types/fills/impl.cljc b/common/src/app/common/types/fills/impl.cljc index 4d6368703d..20813ee91f 100644 --- a/common/src/app/common/types/fills/impl.cljc +++ b/common/src/app/common/types/fills/impl.cljc @@ -378,7 +378,26 @@ (when (< i size) (cons (read-fill dbuffer mbuffer i) (lazy-seq (next-seq (inc i)))))) - 0))))) + 0))) + + cljs.core/IPrintWithWriter + (-pr-writer [this writer _] + (binding [*print-dup* true] + (cljs.core/-write writer (str "#penpot/fills \"" (pr-str (vec this)) "\"")))))) + +#?(:clj + (defmethod print-method Fills + [o ^java.io.Writer writer] + (.write writer "#penpot/fills \"") + (print-dup (vec o) writer) + (.write writer "\""))) + +#?(:clj + (defmethod print-dup Fills + [o ^java.io.Writer writer] + (.write writer "#penpot/fills \"") + (print-dup (vec o) writer) + (.write writer "\""))) (defn from-plain [fills] diff --git a/common/src/app/common/types/path.cljc b/common/src/app/common/types/path.cljc index 0e5d7d1bc3..34aba833b8 100644 --- a/common/src/app/common/types/path.cljc +++ b/common/src/app/common/types/path.cljc @@ -26,7 +26,9 @@ (def ^:cosnt bool-group-style-properties bool/group-style-properties) (def ^:const bool-style-properties bool/style-properties) -(def ^:const default-bool-fills bool/default-fills) +(defn get-default-bool-fills + [] + (bool/get-default-fills)) (def schema:content impl/schema:content) (def schema:segments impl/schema:segments) diff --git a/common/src/app/common/types/path/bool.cljc b/common/src/app/common/types/path/bool.cljc index 81357002ef..f52cbbf301 100644 --- a/common/src/app/common/types/path/bool.cljc +++ b/common/src/app/common/types/path/bool.cljc @@ -7,16 +7,22 @@ (ns app.common.types.path.bool (:require [app.common.data :as d] + [app.common.flags :as flags] [app.common.geom.point :as gpt] [app.common.geom.rect :as grc] [app.common.math :as mth] [app.common.types.color :as clr] + [app.common.types.fills :as types.fills] [app.common.types.path.helpers :as helpers] [app.common.types.path.segment :as segment] [app.common.types.path.subpath :as subpath])) -(def default-fills - [{:fill-color clr/black}]) +(defn get-default-fills + [] + (let [fills [{:fill-color clr/black}]] + (if (contains? flags/*current* :frontend-binary-fills) + (types.fills/from-plain fills) + fills))) (def group-style-properties #{:shadow :blur}) diff --git a/common/src/app/common/types/shape.cljc b/common/src/app/common/types/shape.cljc index 96cc2eaab3..eaa85e40a1 100644 --- a/common/src/app/common/types/shape.cljc +++ b/common/src/app/common/types/shape.cljc @@ -415,12 +415,14 @@ ;; Valid attributes -(def ^:private allowed-shape-attrs #{:page-id :component-id :component-file :component-root :main-instance - :remote-synced :shape-ref :touched :blocked :collapsed :locked - :hidden :masked-group :fills :proportion :proportion-lock :constraints-h - :constraints-v :fixed-scroll :r1 :r2 :r3 :r4 :opacity :grids :exports - :strokes :blend-mode :interactions :shadow :blur :grow-type :applied-tokens - :plugin-data}) +(def ^:private allowed-shape-attrs + #{:page-id :component-id :component-file :component-root :main-instance + :remote-synced :shape-ref :touched :blocked :collapsed :locked + :hidden :masked-group :fills :proportion :proportion-lock :constraints-h + :constraints-v :fixed-scroll :r1 :r2 :r3 :r4 :opacity :grids :exports + :strokes :blend-mode :interactions :shadow :blur :grow-type :applied-tokens + :plugin-data}) + (def ^:private allowed-shape-geom-attrs #{:x :y :width :height}) (def ^:private allowed-shape-base-attrs #{:id :name :type :selrect :points :transform :transform-inverse :parent-id :frame-id}) (def ^:private allowed-bool-attrs #{:shapes :bool-type :content}) diff --git a/common/src/app/common/types/text.cljc b/common/src/app/common/types/text.cljc index a049b17387..f124abf50b 100644 --- a/common/src/app/common/types/text.cljc +++ b/common/src/app/common/types/text.cljc @@ -8,7 +8,9 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.flags :as flags] [app.common.types.color :as clr] + [app.common.types.fills :as types.fills] [clojure.set :as set] [clojure.walk :as walk] [cuerdas.core :as str])) @@ -84,10 +86,12 @@ (def default-root-attrs {:vertical-align "top"}) +(def default-text-fills + [{:fill-color clr/black + :fill-opacity 1}]) + (def default-text-attrs - {:typography-ref-file nil - :typography-ref-id nil - :font-id "sourcesanspro" + {:font-id "sourcesanspro" :font-family "sourcesanspro" :font-variant-id "regular" :font-size "14" @@ -98,12 +102,22 @@ :text-transform "none" :text-align "left" :text-decoration "none" - :text-direction "ltr" - :fills [{:fill-color clr/black - :fill-opacity 1}]}) + :text-direction "ltr"}) -(def default-attrs - (merge default-root-attrs default-text-attrs)) +(defn get-default-text-fills + "Return calculated default text fills" + [] + (if (contains? flags/*current* :frontend-binary-fills) + (types.fills/from-plain default-text-fills) + default-text-fills)) + +(defn get-default-text-attrs + "Return calculated default text attrs. + + NOTE: is implemented as function because it needs resolve at runtime + the activated flag for properly encode the fills" + [] + (assoc default-text-attrs :fills (get-default-text-fills))) (def typography-fields [:font-id @@ -117,9 +131,9 @@ :text-transform]) (def default-typography - (merge - {:name "Source Sans Pro Regular"} - (select-keys default-text-attrs typography-fields))) + (-> default-text-attrs + (select-keys typography-fields) + (assoc :name "Source Sans Pro Regular"))) (defn node-seq ([root] (node-seq identity root)) diff --git a/frontend/src/app/main/data/helpers.cljs b/frontend/src/app/main/data/helpers.cljs index 9a97d36e16..ee3d406c53 100644 --- a/frontend/src/app/main/data/helpers.cljs +++ b/frontend/src/app/main/data/helpers.cljs @@ -78,6 +78,23 @@ (filter selectable?) selected))))) +(defn split-text-shapes + "Split text shapes from non-text shapes" + [objects ids] + (loop [ids (seq ids) + text-ids [] + shape-ids []] + (if-let [id (first ids)] + (let [shape (get objects id)] + (if (cfh/text-shape? shape) + (recur (rest ids) + (conj text-ids id) + shape-ids) + (recur (rest ids) + text-ids + (conj shape-ids id)))) + [text-ids shape-ids]))) + ;; DEPRECATED (defn lookup-selected-raw [state] diff --git a/frontend/src/app/main/data/workspace/bool.cljs b/frontend/src/app/main/data/workspace/bool.cljs index 9819813869..fe493660c5 100644 --- a/frontend/src/app/main/data/workspace/bool.cljs +++ b/frontend/src/app/main/data/workspace/bool.cljs @@ -36,7 +36,7 @@ head (cond-> head (and (contains? head :svg-attrs) (empty? (:fills head))) - (assoc :fills path/default-bool-fills)) + (assoc :fills (path/get-default-bool-fills))) shape {:id shape-id @@ -62,7 +62,7 @@ head (if (= type :difference) (first shapes) (last shapes)) head (cond-> head (and (contains? head :svg-attrs) (empty? (:fills head))) - (assoc :fills path/default-bool-fills))] + (assoc :fills (path/get-default-bool-fills)))] (-> group (assoc :type :bool) (assoc :bool-type type) diff --git a/frontend/src/app/main/data/workspace/clipboard.cljs b/frontend/src/app/main/data/workspace/clipboard.cljs index 55fe89ec6b..202d1082da 100644 --- a/frontend/src/app/main/data/workspace/clipboard.cljs +++ b/frontend/src/app/main/data/workspace/clipboard.cljs @@ -925,7 +925,7 @@ (let [paragraphs (->> (str/lines text) (map str/trim) (mapv #(hash-map :type "paragraph" - :children [(merge txt/default-text-attrs {:text %})])))] + :children [(merge (txt/get-default-text-attrs) {:text %})])))] ;; if text is composed only by line breaks paragraphs is an empty list and should be nil (when (d/not-empty? paragraphs) {:type "root" diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs index 7637b9c3ef..8ed474cb22 100644 --- a/frontend/src/app/main/data/workspace/colors.cljs +++ b/frontend/src/app/main/data/workspace/colors.cljs @@ -18,7 +18,6 @@ [app.common.types.text :as txt] [app.config :as cfg] [app.main.broadcast :as mbc] - [app.main.data.event :as ev] [app.main.data.helpers :as dsh] [app.main.data.modal :as md] [app.main.data.workspace.layout :as layout] @@ -103,11 +102,7 @@ (defn assoc-shape-fill [shape position fill] - (update shape :fills - (fn [fills] - (if (nil? fills) - [fill] - (assoc fills position fill))))) + (update shape :fills types.fills/assoc position fill)) (defn transform-fill* "A lower-level companion function for `transform-fill`" @@ -167,17 +162,28 @@ (assoc-in [attr index] second) (assoc-in [attr new-index] first)))) +(defn- swap-fills-index + [fills index new-index] + (let [first (get fills index) + second (get fills new-index)] + (-> fills + (assoc index second) + (assoc new-index first)))) + (defn reorder-fills [ids index new-index] (ptk/reify ::reorder-fills ptk/WatchEvent (watch [_ state _] - (let [objects (dsh/lookup-page-objects state) + (let [objects + (dsh/lookup-page-objects state) - is-text? #(= :text (:type (get objects %))) - text-ids (filter is-text? ids) - shape-ids (remove is-text? ids) - transform-attrs #(swap-attrs % :fills index new-index)] + [text-ids shape-ids] + (dsh/split-text-shapes objects ids) + + transform-attrs + (fn [object] + (update object :fills types.fills/update swap-fills-index index new-index))] (rx/concat (rx/from (map #(dwt/update-text-with-function % transform-attrs) text-ids)) @@ -207,7 +213,7 @@ (ptk/reify ::change-fill-and-clear ptk/WatchEvent (watch [_ state _] - (let [change-fn (fn [shape attrs] (assoc shape :fills [attrs])) + (let [change-fn (fn [shape attrs] (assoc shape :fills (types.fills/create attrs))) undo-id (js/Symbol)] (rx/concat (rx/of (dwu/start-undo-transaction undo-id)) @@ -225,8 +231,7 @@ (watch [_ state _] (let [change-fn (fn [shape attrs] - (-> shape - (update :fills #(into [attrs] %)))) + (update shape :fills types.fills/prepend attrs)) undo-id (js/Symbol)] (rx/concat @@ -247,13 +252,13 @@ ptk/WatchEvent (watch [_ state _] (let [detach-fn - (fn [values index] - (update values index dissoc :fill-color-ref-id :fill-color-ref-file)) + (fn [fills index] + (update fills index dissoc :fill-color-ref-id :fill-color-ref-file)) change-fn ;; The `node` can be a shape or a text content node (fn [node] - (update node :fills detach-fn position)) + (update node :fills types.fills/update detach-fn position)) undo-id (js/Symbol)] @@ -275,17 +280,17 @@ ptk/WatchEvent (watch [_ state _] (let [remove-fill-by-index - (fn [values index] + (fn [fills index] (into [] (comp (map-indexed (fn [i o] (when (not= i index) o))) (filter some?)) - values)) + fills)) change-fn ;; The `node` can be a shape or a text content node (fn [node] - (update node :fills remove-fill-by-index position)) + (update node :fills types.fills/update remove-fill-by-index position)) undo-id (js/Symbol)] @@ -303,7 +308,7 @@ (ptk/reify ::remove-all-fills ptk/WatchEvent (watch [_ state _] - (let [change-fn (fn [node] (assoc node :fills [])) + (let [change-fn (fn [node] (assoc node :fills (types.fills/create))) undo-id (js/Symbol)] (rx/concat (rx/of (dwu/start-undo-transaction undo-id)) @@ -576,16 +581,26 @@ :fill-color-ref-file (:ref-file color) :fill-color-gradient (:gradient color)})) -(defn change-text-color +(defn- change-text-color [old-color new-color index node] - (let [fills (map #(dissoc % :fill-color-ref-id :fill-color-ref-file) (:fills node)) - parsed-color (-> (color-att->text old-color) - (dissoc :fill-color-ref-id :fill-color-ref-file)) - parsed-new-color (color-att->text new-color) - has-color? (d/index-of fills parsed-color)] - (cond-> node - (some? has-color?) - (assoc-in [:fills index] parsed-new-color)))) + (update node :fills types.fills/update + (fn [fills] + (let [fills' + (map #(dissoc % :fill-color-ref-id :fill-color-ref-file) fills) + + parsed-color + (-> (color-att->text old-color) + (dissoc :fill-color-ref-id :fill-color-ref-file)) + + parsed-new-color + (color-att->text new-color) + + has-color? + (d/index-of fills' parsed-color)] + + (cond-> fills + (some? has-color?) + (assoc index parsed-new-color)))))) (def ^:private schema:change-color-operation [:map @@ -1114,39 +1129,6 @@ (assoc :type :image) (dissoc :editing-stop :stops :gradient))))))) -(defn select-color - [position add-color] - ;; FIXME: revisit - (ptk/reify ::select-color - ptk/WatchEvent - (watch [_ state _] - (let [selected (dsh/lookup-selected state) - shapes (dsh/lookup-shapes state selected) - shape (first shapes) - fills (if (cfh/text-shape? shape) - (:fills (dwt/current-text-values - {:editor-state (dm/get-in state [:workspace-editor-state (:id shape)]) - :shape shape - :attrs (conj txt/text-fill-attrs :fills)})) - (:fills shape)) - fill (first fills) - single? (and (= 1 (count selected)) - (= 1 (count fills))) - data (if single? - (d/without-nils {:color (:fill-color fill) - :opacity (:fill-opacity fill) - :gradient (:fill-color-gradient fill)}) - {:color "#406280" - :opacity 1})] - (rx/of (md/show :colorpicker - {:x (:x position) - :y (:y position) - :on-accept add-color - :data data - :position :right}) - (ptk/event ::ev/event {::ev/name "add-asset-to-library" - :asset-type "color"})))))) - (defn- stroke->color-att [stroke file-id libraries] (let [ref-file (:stroke-color-ref-file stroke) diff --git a/frontend/src/app/main/data/workspace/media.cljs b/frontend/src/app/main/data/workspace/media.cljs index eafd055708..3cb250afc5 100644 --- a/frontend/src/app/main/data/workspace/media.cljs +++ b/frontend/src/app/main/data/workspace/media.cljs @@ -16,6 +16,7 @@ [app.common.media :as media] [app.common.schema :as sm] [app.common.types.container :as ctn] + [app.common.types.fills :as types.fills] [app.common.types.shape :as cts] [app.common.uuid :as uuid] [app.config :as cf] @@ -63,18 +64,22 @@ ptk/WatchEvent (watch [_ _ _] (let [{:keys [name width height id mtype]} image + + fills (types.fills/create + {:fill-opacity 1 + :fill-image {:width width + :height height + :mtype mtype + :id id + :keep-aspect-ratio true}}) + shape {:name name :width width :height height :x (mth/round (- x (/ width 2))) :y (mth/round (- y (/ height 2))) - :fills [{:fill-opacity 1 - :fill-image {:name name - :width width - :height height - :mtype mtype - :id id - :keep-aspect-ratio true}}]}] + :fills fills}] + (rx/of (dwsh/create-and-add-shape :rect x y shape)))))) (defn svg-uploaded @@ -299,7 +304,7 @@ :name (:name root-svg-shape) :frame-id uuid/zero :parent-id uuid/zero - :fills []}) + :fills (types.fills/create)}) root-svg-shape (-> root-svg-shape @@ -335,19 +340,21 @@ :frame-id uuid/zero :parent-id uuid/zero}) + img-fills (types.fills/create + {:fill-opacity 1 + :fill-image {:id id + :width width + :height height + :mtype mtype + :keep-aspect-ratio true}}) + img-shape (cts/setup-shape {:type :rect :x (:x pos) :y (:y pos) :width width :height height - :fills [{:fill-opacity 1 - :fill-image {:name name - :id id - :width width - :height height - :mtype mtype - :keep-aspect-ratio true}}] + :fills img-fills :name name :frame-id (:id frame-shape) :parent-id (:id frame-shape)})] diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 3b474956a8..5043bd4543 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -196,8 +196,8 @@ ptk/UpdateEvent (update [_ state] (let [text-state (some->> content ted/import-content) - attrs (d/merge txt/default-text-attrs - (get-in state [:workspace-global :default-font])) + attrs (merge (txt/get-default-text-attrs) + (get-in state [:workspace-global :default-font])) editor (cond-> (ted/create-editor-state text-state decorator) (and (nil? content) (some? attrs)) (ted/update-editor-current-block-data attrs))] @@ -237,7 +237,9 @@ (defn- to-new-fills [data] - [(d/without-nils (select-keys data types.fills/fill-attrs))]) + ;; FIXME: maybe export this as a specific helper ? + (types.fills/create + (d/without-nils (select-keys data types.fills/fill-attrs)))) (defn- shape-current-values [shape pred attrs] @@ -245,7 +247,10 @@ nodes (->> (txt/node-seq pred root) (map (fn [node] (if (txt/is-text-node? node) - (let [fills + (let [default-text-attrs + (txt/get-default-text-attrs) + + fills (cond (types.fills/has-valid-fill-attrs? node) (to-new-fills node) @@ -254,8 +259,9 @@ (:fills node) :else - (:fills txt/default-text-attrs))] - (-> (merge txt/default-text-attrs node) + (:fills default-text-attrs))] + + (-> (merge default-text-attrs node) (assoc :fills fills))) node))))] (attrs/get-attrs-multi nodes attrs))) @@ -290,7 +296,9 @@ [{:keys [editor-state attrs]}] (let [result (-> (ted/get-editor-current-inline-styles editor-state) (select-keys attrs)) - result (if (empty? result) txt/default-text-attrs result)] + result (if (empty? result) + (txt/get-default-text-attrs) + result)] result)) (defn current-text-values @@ -469,21 +477,21 @@ (let [color-attrs (not-empty (select-keys node types.fills/fill-attrs))] (cond-> node (nil? (:fills node)) - (assoc :fills []) + (assoc :fills (types.fills/create)) ;; Migrate old colors and remove the old fromat color-attrs (-> (dissoc :fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient) - (update :fills conj color-attrs)) + (update :fills types.fills/update conj color-attrs)) ;; We don't have the fills attribute. It's an old text without color ;; so need to be black (and (nil? (:fills node)) (empty? color-attrs)) - (assoc :fills (:fills txt/default-text-attrs)) + (assoc :fills (txt/get-default-text-fills)) ;; Remove duplicates from the fills :always - (update :fills (comp vec distinct))))) + (update :fills types.fills/update distinct)))) (defn migrate-content [content] @@ -905,7 +913,7 @@ (ptk/reify ::v2-update-text-editor-styles ptk/UpdateEvent (update [_ state] - (let [merged-styles (merge txt/default-text-attrs + (let [merged-styles (merge (txt/get-default-text-attrs) (get-in state [:workspace-global :default-font]) new-styles)] (update-in state [:workspace-v2-editor-state id] (fnil merge {}) merged-styles))))) diff --git a/frontend/src/app/main/fonts.cljs b/frontend/src/app/main/fonts.cljs index a49c0beca8..9f1d216cd1 100644 --- a/frontend/src/app/main/fonts.cljs +++ b/frontend/src/app/main/fonts.cljs @@ -295,7 +295,7 @@ (let [current-font (if (some? font-id) (select-keys node [:font-id :font-variant-id]) - (select-keys txt/default-text-attrs [:font-id :font-variant-id]))] + (select-keys txt/default-typography [:font-id :font-variant-id]))] (conj result current-font))) #{}))) diff --git a/frontend/src/app/main/ui/inspect/attributes/text.cljs b/frontend/src/app/main/ui/inspect/attributes/text.cljs index 5b689ce94d..5dab13e6b5 100644 --- a/frontend/src/app/main/ui/inspect/attributes/text.cljs +++ b/frontend/src/app/main/ui/inspect/attributes/text.cljs @@ -174,7 +174,7 @@ (let [style-text-blocks (->> (:content shape) (txt/content->text+styles) (remove (fn [[_ text]] (str/empty? (str/trim text)))) - (mapv (fn [[style text]] (vector (merge txt/default-text-attrs style) text))))] + (mapv (fn [[style text]] (vector (merge (txt/get-default-text-attrs) style) text))))] (for [[idx [full-style text]] (map-indexed vector style-text-blocks)] [:& typography-block {:key idx diff --git a/frontend/src/app/main/ui/shapes/text.cljs b/frontend/src/app/main/ui/shapes/text.cljs index d25190872e..0b1d47e602 100644 --- a/frontend/src/app/main/ui/shapes/text.cljs +++ b/frontend/src/app/main/ui/shapes/text.cljs @@ -17,7 +17,7 @@ (defn- load-fonts! [content] (let [extract-fn (juxt :font-id :font-variant-id) - default (extract-fn txt/default-text-attrs)] + default (extract-fn txt/default-typography)] (->> (tree-seq map? :children content) (into #{default} (keep extract-fn)) (run! (fn [[font-id variant-id]] diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 04c5b16dc7..e691e22952 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -53,11 +53,11 @@ line-height (if (and (some? line-height) (not= "" line-height)) line-height - (:line-height txt/default-text-attrs)) + (:line-height txt/default-typography)) text-align (:text-align data "start") base #js {;; Fix a problem when exporting HTML - :fontSize 0 ;;(str (:font-size data (:font-size txt/default-text-attrs)) "px") + :fontSize 0 :lineHeight line-height :margin 0}] @@ -75,7 +75,7 @@ text-transform (:text-transform data) font-id (or (:font-id data) - (:font-id txt/default-text-attrs)) + (:font-id txt/default-typography)) font-variant-id (:font-variant-id data) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs index b33c697ccf..8a42dde614 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs @@ -41,7 +41,7 @@ (defn- get-fonts [content] (let [extract-fn (juxt :font-id :font-variant-id) - default (extract-fn txt/default-text-attrs)] + default (extract-fn txt/default-typography)] (->> (tree-seq map? :children content) (into #{default} (keep extract-fn))))) @@ -67,7 +67,7 @@ style-defaults (styles/get-style-defaults - (merge txt/default-text-attrs txt/default-root-attrs default-font)) + (merge (txt/get-default-text-attrs) txt/default-root-attrs default-font)) options #js {:styleDefaults style-defaults diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs index 1c4c51036e..ac1f35506f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs @@ -217,7 +217,7 @@ (mf/use-fn (mf/deps values) (fn [ids attrs] - (st/emit! (dwt/save-font (-> (merge txt/default-text-attrs values attrs) + (st/emit! (dwt/save-font (-> (merge (txt/get-default-text-attrs) values attrs) (select-keys txt/text-node-attrs))) (dwt/update-all-attrs ids attrs)))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index 93e3c171e6..2faae0ddca 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -235,9 +235,9 @@ [{:keys [values on-change on-blur show-recent full-size-selector]}] (let [{:keys [font-id font-size font-variant-id]} values - font-id (or font-id (:font-id txt/default-text-attrs)) - font-size (or font-size (:font-size txt/default-text-attrs)) - font-variant-id (or font-variant-id (:font-variant-id txt/default-text-attrs)) + font-id (or font-id (:font-id txt/default-typography)) + font-size (or font-size (:font-size txt/default-typography)) + font-variant-id (or font-variant-id (:font-variant-id txt/default-typography)) fonts (mf/deref fonts/fontsdb) font (get fonts font-id) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs index 2401a50a56..2429021307 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/multiple.cljs @@ -203,6 +203,9 @@ [shapes objects attr-group] (let [attrs (group->attrs attr-group) + default-text-attrs + (txt/get-default-text-attrs) + merge-attrs (fn [v1 v2] (cond @@ -233,7 +236,7 @@ (let [shape-attrs (select-keys shape attrs) content-attrs - (attrs/get-text-attrs-multi shape txt/default-text-attrs attrs) + (attrs/get-text-attrs-multi shape default-text-attrs attrs) new-values (-> values diff --git a/frontend/src/app/util/text/content/to_dom.cljs b/frontend/src/app/util/text/content/to_dom.cljs index 6ae521476c..061aba9b6f 100644 --- a/frontend/src/app/util/text/content/to_dom.cljs +++ b/frontend/src/app/util/text/content/to_dom.cljs @@ -73,12 +73,12 @@ ;; it affects to the height calculation the browser does font-size (if (some #(not= "" (:text %)) (:children paragraph)) "0" - (:font-size styles (:font-size txt/default-text-attrs))) + (:font-size styles (:font-size txt/default-typography))) line-height (:line-height styles) line-height (if (and (some? line-height) (not= "" line-height)) line-height - (:line-height txt/default-text-attrs))] + (:line-height txt/default-typography))] (-> styles (assoc :font-size font-size :line-height line-height)))) diff --git a/frontend/src/debug.cljs b/frontend/src/debug.cljs index e934f851b5..aa3e4d09cb 100644 --- a/frontend/src/debug.cljs +++ b/frontend/src/debug.cljs @@ -12,6 +12,7 @@ [app.common.files.validate :as cfv] [app.common.json :as json] [app.common.logging :as l] + [app.common.pprint :as pp] [app.common.transit :as t] [app.common.types.file :as ctf] [app.common.uuid :as uuid] @@ -197,6 +198,14 @@ (logjs "selected" result) nil)) + +(defn ^:export dump-selected-edn + [] + (let [objects (dsh/lookup-page-objects @st/state) + result (->> (get-selected @st/state) (map #(get objects %)))] + (pp/pprint result {:length 30 :level 30}) + nil)) + (defn ^:export preview-selected [] (st/emit! (dp/open-preview-selected))) diff --git a/frontend/test/frontend_tests/logic/components_and_tokens.cljs b/frontend/test/frontend_tests/logic/components_and_tokens.cljs index 2add7ecf4e..7b1751a496 100644 --- a/frontend/test/frontend_tests/logic/components_and_tokens.cljs +++ b/frontend/test/frontend_tests/logic/components_and_tokens.cljs @@ -412,7 +412,7 @@ (t/is (= (get c-frame1' :opacity) 0.9)) (t/is (= (get-in c-frame1' [:strokes 0 :stroke-width]) 8)) (t/is (= (get-in c-frame1' [:strokes 0 :stroke-color]) "#ff0000")) - (t/is (= (get-in c-frame1' [:fills 0 :fill-color]) "#ff0000")) + (t/is (= (-> c-frame1' :fills (nth 0) :fill-color) "#ff0000")) (t/is (mth/close? (get c-frame1' :width) 200)) (t/is (mth/close? (get c-frame1' :height) 200)) diff --git a/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs b/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs index 0998a7f22b..03af45b67c 100644 --- a/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs +++ b/frontend/test/frontend_tests/tokens/logic/token_actions_test.cljs @@ -219,19 +219,21 @@ secondary-target (toht/get-token file' "color.secondary") rect-1' (cths/get-shape file' :rect-1) rect-2' (cths/get-shape file' :rect-2)] + (t/testing "regular color" (t/is (some? (:applied-tokens rect-1'))) (t/is (= (:fill (:applied-tokens rect-1')) (:name primary-target))) - (t/is (= (get-in rect-1' [:fills 0 :fill-color]) "#ff0000")) - + (t/is (= (-> rect-1' :fills (nth 0) :fill-color) "#ff0000")) (t/is (= (:stroke-color (:applied-tokens rect-1')) (:name primary-target))) (t/is (= (get-in rect-1' [:strokes 0 :stroke-color]) "#ff0000"))) + (t/testing "color with alpha channel" (t/is (some? (:applied-tokens rect-2'))) (t/is (= (:fill (:applied-tokens rect-2')) (:name secondary-target))) - (t/is (= (get-in rect-2' [:fills 0 :fill-color]) "#ff0000")) - (t/is (= (get-in rect-2' [:fills 0 :fill-opacity]) 0.5)) + (let [fills (get rect-2' :fills)] + (t/is (= (-> fills (nth 0) :fill-color) "#ff0000")) + (t/is (= (-> fills (nth 0) :fill-opacity) 0.5))) (t/is (= (:stroke-color (:applied-tokens rect-2')) (:name secondary-target))) (t/is (= (get-in rect-2' [:strokes 0 :stroke-color]) "#ff0000")) @@ -758,4 +760,4 @@ (t/is (nil? (:typography-ref-id paragraph-3))) (t/is (nil? (:typography-ref-file paragraph-3))) (t/is (nil? (:typography-ref-id text-node-3))) - (t/is (nil? (:typography-ref-file text-node-3)))))))))) \ No newline at end of file + (t/is (nil? (:typography-ref-file text-node-3))))))))))