diff --git a/common/src/app/common/spec/shape.cljc b/common/src/app/common/spec/shape.cljc index 54853d259..45239f83e 100644 --- a/common/src/app/common/spec/shape.cljc +++ b/common/src/app/common/spec/shape.cljc @@ -202,9 +202,9 @@ (s/def :internal.shape.text/content (s/nilable (s/or :text-container - (s/keys :req-un [:internal.shape.text/type - :internal.shape.text/children] - :opt-un [:internal.shape.text/key]) + (s/keys :req-un [:internal.shape.text/type] + :opt-un [:internal.shape.text/key + :internal.shape.text/children]) :text-content (s/keys :req-un [:internal.shape.text/text])))) diff --git a/common/src/app/common/text.cljc b/common/src/app/common/text.cljc index a48f525d4..b58f6b79a 100644 --- a/common/src/app/common/text.cljc +++ b/common/src/app/common/text.cljc @@ -26,8 +26,8 @@ :text-transform "none" :text-align "left" :text-decoration "none" - :fill-color clr/black - :fill-opacity 1}) + :fills [{:fill-color clr/black + :fill-opacity 1}]}) (def typography-fields [:font-id diff --git a/frontend/resources/styles/main/partials/dashboard-header.scss b/frontend/resources/styles/main/partials/dashboard-header.scss index 4027e6de3..911e67c00 100644 --- a/frontend/resources/styles/main/partials/dashboard-header.scss +++ b/frontend/resources/styles/main/partials/dashboard-header.scss @@ -110,7 +110,7 @@ .dashboard-buttons { display: flex; - justify-content: end; + justify-content: flex-end; align-items: center; } diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs index 4ee3fee66..af28baa57 100644 --- a/frontend/src/app/main/data/workspace/colors.cljs +++ b/frontend/src/app/main/data/workspace/colors.cljs @@ -113,81 +113,89 @@ (defn transform-fill [state ids color transform] - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id) + (let [objects (wsh/lookup-page-objects state) is-text? #(= :text (:type (get objects %))) text-ids (filter is-text? ids) - shape-ids (filter (comp not is-text?) ids) + shape-ids (remove is-text? ids) - attrs (cond-> {:fill-color nil - :fill-color-gradient nil - :fill-color-ref-file nil - :fill-color-ref-id nil - :fill-opacity nil} + attrs + (cond-> {} + (contains? color :color) + (assoc :fill-color (:color color)) - (contains? color :color) - (assoc :fill-color (:color color)) + (contains? color :id) + (assoc :fill-color-ref-id (:id color)) - (contains? color :id) - (assoc :fill-color-ref-id (:id color)) + (contains? color :file-id) + (assoc :fill-color-ref-file (:file-id color)) - (contains? color :file-id) - (assoc :fill-color-ref-file (:file-id color)) + (contains? color :gradient) + (assoc :fill-color-gradient (:gradient color)) - (contains? color :gradient) - (assoc :fill-color-gradient (:gradient color)) + (contains? color :opacity) + (assoc :fill-opacity (:opacity color)) - (contains? color :opacity) - (assoc :fill-opacity (:opacity color))) - ;; Not nil attrs - clean-attrs (d/without-nils attrs)] + :always + (d/without-nils)) + + transform-attrs #(transform % attrs)] (rx/concat - (rx/from (map #(dwt/update-text-attrs {:id % :attrs attrs}) text-ids)) - (rx/of (dch/update-shapes - shape-ids - #(transform % clean-attrs)))))) + (rx/from (map #(dwt/update-text-with-function % transform-attrs) text-ids)) + (rx/of (dch/update-shapes shape-ids transform-attrs))))) (defn swap-fills [shape index new-index] (let [first (get-in shape [:fills index]) second (get-in shape [:fills new-index])] (-> shape (assoc-in [:fills index] second) - (assoc-in [:fills new-index] first)) - )) + (assoc-in [:fills new-index] first)))) (defn reorder-fills [ids index new-index] (ptk/reify ::reorder-fills ptk/WatchEvent - (watch [_ _ _] - (rx/of (dch/update-shapes - ids - #(swap-fills % index new-index)))))) + (watch [_ state _] + (let [objects (wsh/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-fills % index new-index)] + + (rx/concat + (rx/from (map #(dwt/update-text-with-function % transform-attrs) text-ids)) + (rx/of (dch/update-shapes shape-ids transform-attrs))))))) (defn change-fill [ids color position] (ptk/reify ::change-fill ptk/WatchEvent (watch [_ state _] - (let [change (fn [shape attrs] (assoc-in shape [:fills position] (into {} attrs)))] - (transform-fill state ids color change))))) + (let [change (fn [shape attrs] + (-> shape + (cond-> (not (contains? shape :fills)) + (assoc :fills [])) + (assoc-in [:fills position] (into {} attrs))))] + (transform-fill state ids color change))))) (defn change-fill-and-clear [ids color] (ptk/reify ::change-fill-and-clear ptk/WatchEvent (watch [_ state _] - (let [set (fn [shape attrs] (assoc shape :fills [attrs]))] - (transform-fill state ids color set))))) + (let [set (fn [shape attrs] (assoc shape :fills [attrs]))] + (transform-fill state ids color set))))) (defn add-fill [ids color] (ptk/reify ::add-fill ptk/WatchEvent (watch [_ state _] - (let [add (fn [shape attrs] (assoc shape :fills (into [attrs] (:fills shape))))] + (let [add (fn [shape attrs] + (-> shape + (update :fills #(into [attrs] %))))] (transform-fill state ids color add))))) (defn remove-fill diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index c643335ba..1cc798798 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -50,12 +50,14 @@ (update state :workspace-editor-state dissoc id))))) (defn finalize-editor-state - [{:keys [id] :as shape}] + [id] (ptk/reify ::finalize-editor-state ptk/WatchEvent (watch [_ state _] (when (dwc/initialized? state) - (let [content (-> (get-in state [:workspace-editor-state id]) + (let [objects (wsh/lookup-page-objects state) + shape (get objects id) + content (-> (get-in state [:workspace-editor-state id]) (ted/get-editor-current-content))] (if (ted/content-has-text? content) (let [content (d/merge (ted/export-content content) @@ -78,8 +80,8 @@ ptk/UpdateEvent (update [_ state] (let [text-state (some->> content ted/import-content) - attrs (get-in state [:workspace-local :defaults :font]) - + attrs (d/merge txt/default-text-attrs + (get-in state [:workspace-local :defaults :font])) editor (cond-> (ted/create-editor-state text-state decorator) (and (nil? content) (some? attrs)) (ted/update-editor-current-block-data attrs))] @@ -95,7 +97,7 @@ (rx/filter (ptk/type? ::rt/navigate) stream) (rx/filter #(= ::finalize-editor-state %) stream)) (rx/take 1) - (rx/map #(finalize-editor-state shape)))))) + (rx/map #(finalize-editor-state id)))))) (defn select-all "Select all content of the current editor. When not editor found this @@ -145,10 +147,10 @@ ;; --- TEXT EDITION IMPL -(defn- update-shape - [shape pred-fn merge-fn attrs] - (let [merge-attrs #(merge-fn % attrs) - transform #(txt/transform-nodes pred-fn merge-attrs %)] +(defn- update-text-content + [shape pred-fn update-fn attrs] + (let [update-attrs #(update-fn % attrs) + transform #(txt/transform-nodes pred-fn update-attrs %)] (-> shape (update :content transform)))) @@ -160,7 +162,11 @@ (let [objects (wsh/lookup-page-objects state) shape (get objects id) - update-fn #(update-shape % txt/is-root-node? attrs/merge attrs) + update-fn + (fn [shape] + (if (some? (:content shape)) + (update-text-content shape txt/is-root-node? attrs/merge attrs) + (assoc shape :content (attrs/merge {:type "root"} attrs)))) shape-ids (cond (cph/text-shape? shape) [id] (cph/group-shape? shape) (cph/get-children-ids objects id))] @@ -187,7 +193,7 @@ node attrs)) - update-fn #(update-shape % txt/is-paragraph-node? merge-fn attrs) + update-fn #(update-text-content % txt/is-paragraph-node? merge-fn attrs) shape-ids (cond (cph/text-shape? shape) [id] (cph/group-shape? shape) (cph/get-children-ids objects id))] @@ -209,12 +215,57 @@ update-node? (fn [node] (or (txt/is-text-node? node) (txt/is-paragraph-node? node))) - - update-fn #(update-shape % update-node? attrs/merge attrs) shape-ids (cond (cph/text-shape? shape) [id] (cph/group-shape? shape) (cph/get-children-ids objects id))] - (rx/of (dch/update-shapes shape-ids update-fn))))))) + (rx/of (dch/update-shapes shape-ids #(update-text-content % update-node? attrs/merge attrs)))))))) + +(defn migrate-content + [content] + (txt/transform-nodes + #(or (txt/is-text-node? %) (txt/is-paragraph-node? %)) + (fn [node] + (let [color-attrs (select-keys node [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient])] + (cond-> node + (d/not-empty? color-attrs) + (-> (dissoc :fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient) + (assoc :fills [color-attrs]))))) + content)) + +(defn update-text-with-function + [id update-node-fn] + (ptk/reify ::update-text-with-function + ptk/UpdateEvent + (update [_ state] + (d/update-in-when state [:workspace-editor-state id] ted/update-editor-current-inline-styles-fn update-node-fn)) + + ptk/WatchEvent + (watch [_ state _] + (when (nil? (get-in state [:workspace-editor-state id])) + (let [objects (wsh/lookup-page-objects state) + shape (get objects id) + + update-node? + (fn [node] + (or (txt/is-text-node? node) + (txt/is-paragraph-node? node))) + + shape-ids + (cond + (cph/text-shape? shape) [id] + (cph/group-shape? shape) (cph/get-children-ids objects id)) + + update-content + (fn [content] + (->> content + (migrate-content) + (txt/transform-nodes update-node? update-node-fn))) + + update-shape + (fn [shape] + (d/update-when shape :content update-content))] + + (rx/of (dch/update-shapes shape-ids update-shape))))))) ;; --- RESIZE UTILS diff --git a/frontend/src/app/main/ui/shapes/attrs.cljs b/frontend/src/app/main/ui/shapes/attrs.cljs index c969e2f4e..d1abb8d81 100644 --- a/frontend/src/app/main/ui/shapes/attrs.cljs +++ b/frontend/src/app/main/ui/shapes/attrs.cljs @@ -205,7 +205,7 @@ (= :image (:type shape)) (> (count (:fills shape)) 1) (some #(some? (:fill-color-gradient %)) (:fills shape))) - (obj/set! styles "fill" (str "url(#fill-" render-id ")")) + (obj/set! styles "fill" (str "url(#fill-0-" render-id ")")) ;; imported svgs can have fill and fill-opacity attributes (obj/contains? svg-styles "fill") @@ -227,9 +227,8 @@ (add-style-attrs shape))) (defn extract-fill-attrs - [shape index] - (let [render-id (mf/use-ctx muc/render-ctx) - fill-styles (-> (obj/get shape "style" (obj/new)) + [shape render-id index] + (let [fill-styles (-> (obj/get shape "style" (obj/new)) (add-fill shape render-id index))] (-> (obj/new) (obj/set! "style" fill-styles)))) diff --git a/frontend/src/app/main/ui/shapes/fills.cljs b/frontend/src/app/main/ui/shapes/fills.cljs index 5012c1ae9..f6f8f67a8 100644 --- a/frontend/src/app/main/ui/shapes/fills.cljs +++ b/frontend/src/app/main/ui/shapes/fills.cljs @@ -20,45 +20,54 @@ [props] (let [shape (obj/get props "shape") - render-id (obj/get props "render-id") - {:keys [x y width height]} (:selrect shape) - {:keys [metadata]} shape - fill-id (str "fill-" render-id) - has-image (or metadata (:fill-image shape)) - uri (if metadata - (cfg/resolve-file-media metadata) - (cfg/resolve-file-media (:fill-image shape))) - embed (embed/use-data-uris [uri]) - transform (gsh/transform-matrix shape) - pattern-attrs (cond-> #js {:id fill-id - :patternUnits "userSpaceOnUse" - :x x - :y y - :height height - :width width - :data-loading (str (not (contains? embed uri)))} - (= :path (:type shape)) - (obj/set! "patternTransform" transform))] + render-id (obj/get props "render-id")] - [:* - (for [[index value] (-> (d/enumerate (:fills shape [])) reverse)] - (cond (some? (:fill-color-gradient value)) - (case (:type (:fill-color-gradient value)) - :linear [:> grad/linear-gradient #js {:id (str (name :fill-color-gradient) "_" render-id "_" index) - :gradient (:fill-color-gradient value) - :shape shape}] - :radial [:> grad/radial-gradient #js {:id (str (name :fill-color-gradient) "_" render-id "_" index) - :gradient (:fill-color-gradient value) - :shape shape}]))) + (when (or (some? (:fill-image shape)) + (#{:image :text} (:type shape)) + (> (count (:fills shape)) 1) + (some :fill-color-gradient (:fills shape))) - [:> :pattern pattern-attrs - [:g - (for [[index value] (-> (d/enumerate (:fills shape [])) reverse)] - [:> :rect (-> (attrs/extract-fill-attrs value index) - (obj/set! "width" width) - (obj/set! "height" height))]) + (let [{:keys [x y width height]} (:selrect shape) + {:keys [metadata]} shape + + has-image (or metadata (:fill-image shape)) + uri (if metadata + (cfg/resolve-file-media metadata) + (cfg/resolve-file-media (:fill-image shape))) + embed (embed/use-data-uris [uri]) + transform (gsh/transform-matrix shape) + pattern-attrs (cond-> #js {:patternUnits "userSpaceOnUse" + :x x + :y y + :height height + :width width + :data-loading (str (not (contains? embed uri)))} + (= :path (:type shape)) + (obj/set! "patternTransform" transform))] - (when has-image - [:image {:xlinkHref (get embed uri uri) - :width width - :height height}])]]])) + [:* + (for [[_shape-index shape] (d/enumerate (or (:position-data shape) [shape]))] + (for [[fill-index value] (-> (d/enumerate (:fills shape [])) reverse)] + (cond (some? (:fill-color-gradient value)) + (case (d/name (:type (:fill-color-gradient value))) + "linear" [:> grad/linear-gradient #js {:id (str "fill-color-gradient_" render-id "_" fill-index) + :gradient (:fill-color-gradient value) + :shape shape}] + "radial" [:> grad/radial-gradient #js {:id (str "fill-color-gradient_" render-id "_" fill-index) + :gradient (:fill-color-gradient value) + :shape shape}])))) + + (for [[shape-index shape] (d/enumerate (or (:position-data shape) [shape]))] + (let [fill-id (str "fill-" shape-index "-" render-id)] + [:> :pattern (-> (obj/clone pattern-attrs) + (obj/set! "id" fill-id)) + [:g + (for [[fill-index value] (-> (d/enumerate (:fills shape [])) reverse)] + [:> :rect (-> (attrs/extract-fill-attrs value render-id fill-index) + (obj/set! "width" width) + (obj/set! "height" height))]) + + (when has-image + [:image {:xlinkHref (get embed uri uri) + :width width + :height height}])]]))])))) diff --git a/frontend/src/app/main/ui/shapes/mask.cljs b/frontend/src/app/main/ui/shapes/mask.cljs index a9b58db4c..9a0470901 100644 --- a/frontend/src/app/main/ui/shapes/mask.cljs +++ b/frontend/src/app/main/ui/shapes/mask.cljs @@ -37,7 +37,7 @@ (fn [data] (-> data (dissoc :fill-color :fill-opacity :fill-color-gradient) - (assoc :fill-color "#FFFFFF" :fill-opacity 1)))] + (assoc :fills [{:fill-color "#FFFFFF" :fill-opacity 1}])))] (-> shape (d/update-when :position-data #(mapv update-color %)) (assoc :stroke-color "#FFFFFF" :stroke-opacity 1)))) diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index 5a036c82f..d81e98606 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -63,10 +63,6 @@ [:& defs/svg-defs {:shape shape :render-id render-id}] [:& filters/filters {:shape shape :filter-id filter-id}] [:& grad/gradient {:shape shape :attr :stroke-color-gradient}] - (when (or (some? (:fill-image shape)) - (= :image (:type shape)) - (> (count (:fills shape)) 1) - (some :fill-color-gradient (:fills shape))) - [:& fills/fills {:shape shape :render-id render-id}]) + [:& fills/fills {:shape shape :render-id render-id}] [:& frame/frame-clip-def {:shape shape :render-id render-id}]] children]])) diff --git a/frontend/src/app/main/ui/shapes/text/fo_text.cljs b/frontend/src/app/main/ui/shapes/text/fo_text.cljs index eb39b1edf..52f9915bb 100644 --- a/frontend/src/app/main/ui/shapes/text/fo_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/fo_text.cljs @@ -194,13 +194,16 @@ grow-type (obj/get props "grow-type") ;; This is only needed in workspace ;; We add 8px to add a padding for the exporter ;; width (+ width 8) + [colors color-mapping color-mapping-inverse] (retrieve-colors shape) plain-colors? (mf/use-ctx muc/text-plain-colors-ctx) content (cond-> content plain-colors? - (remap-colors color-mapping))] + (remap-colors color-mapping)) + + ] [:foreignObject {:x x diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index e23225338..9f4dda7c3 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -88,9 +88,10 @@ :overflowWrap "initial"} base (-> base - (obj/set! "--fill-color" fill-color) - (obj/set! "--fill-color-gradient" (transit/encode-str (:fill-color-gradient data))) - (obj/set! "--fill-opacity" fill-opacity))] + (obj/set! "--fills" (transit/encode-str (:fills data))) + #_(obj/set! "--fill-color" fill-color) + #_(obj/set! "--fill-color-gradient" (transit/encode-str (:fill-color-gradient data))) + #_(obj/set! "--fill-opacity" fill-opacity))] (when (and (string? letter-spacing) (pos? (alength letter-spacing))) diff --git a/frontend/src/app/main/ui/shapes/text/svg_text.cljs b/frontend/src/app/main/ui/shapes/text/svg_text.cljs index e41564a95..26731e181 100644 --- a/frontend/src/app/main/ui/shapes/text/svg_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/svg_text.cljs @@ -59,7 +59,8 @@ :fontStyle (:font-style data) :direction (if (:rtl? data) "rtl" "ltr") :whiteSpace "pre"} - (attrs/add-fill data (get-gradient-id index)))})] + (obj/set! "fill" (str "url(#fill-" index "-" render-id ")")) + #_(attrs/add-fill data (get-gradient-id index)))})] [:& shape-custom-stroke {:shape shape :index index} [:> :text props (:text data)]]))]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index 6e035fb94..8bff9737b 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -155,6 +155,11 @@ show-svg-text? (or (some? position-data) (some? @local-position-data)) + shape + (cond-> shape + (some? @local-position-data) + (assoc :position-data @local-position-data)) + update-position-data (fn [] (when (some? @local-position-data) @@ -171,7 +176,7 @@ (fn [] ;; Timer to update the shape. We do this so a lot of changes won't produce ;; a lot of updates (kind of a debounce) - (let [sid (timers/schedule 100 update-position-data)] + (let [sid (timers/schedule 50 update-position-data)] (fn [] (rx/dispose! sid))))) @@ -217,9 +222,5 @@ :key (str id edition?)}]] (when show-svg-text? - (let [shape - (cond-> shape - (some? @local-position-data) - (assoc :position-data @local-position-data))] - [:g.text-svg {:pointer-events "none"} - [:& svg/text-shape {:shape shape}]]))]])) + [:g.text-svg {:pointer-events "none"} + [:& svg/text-shape {:shape shape}]])]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 5d4b45552..52139e778 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -210,7 +210,11 @@ {:ref self-ref :style {:cursor (cur/text (:rotation shape)) :width (:width shape) - :height (:height shape)} + :height (:height shape) + ;; We hide the editor when is blurred because otherwise the selection won't let us see + ;; the underlying text. Use opacity because display or visibility won't allow to recover + ;; focus afterwards. + :opacity (when @blurred 0)} :on-click on-click :class (dom/classnames :align-top (= (:vertical-align content "top") "top") diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs index ba0595fff..8cda5adfa 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/fill.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace.sidebar.options.menus.fill (:require - [app.common.attrs :as attrs] [app.common.colors :as clr] [app.common.data :as d] [app.common.pages :as cp] @@ -17,7 +16,6 @@ [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] - [cuerdas.core :as str] [rumext.alpha :as mf])) (def fill-attrs @@ -51,40 +49,6 @@ ;; Excluding nil values values (d/without-nils values) - only-shapes? (and (contains? values :fills) - ;; texts have :fill-* attributes, the rest of the shapes have :fills - (= (count (filter #(str/starts-with? (d/name %) "fill-") (keys values))) 0)) - - shapes-and-texts? (and (contains? values :fills) - ;; texts have :fill-* attributes, the rest of the shapes have :fills - (> (count (filter #(str/starts-with? (d/name %) "fill-") (keys values))) 0)) - - ;; Texts still have :fill-* attributes and the rest of the shapes just :fills so we need some extra calculation when multiple selection happens to detect them - plain-values (if (vector? (:fills values)) - (concat (:fills values) [(dissoc values :fills)]) - values) - - plain-values (attrs/get-attrs-multi plain-values [:fill-color :fill-opacity :fill-color-ref-id :fill-color-ref-file :fill-color-gradient]) - - plain-values (if (empty? plain-values) - values - plain-values) - - ;; We must control some rare situations like - ;; - Selecting texts and shapes with different fills - ;; - Selecting a text and a shape with empty fills - plain-values (if (and shapes-and-texts? - (or - (= (:fills values) :multiple) - (= 0 (count (:fills values))))) - {:fills :multiple - :fill-color :multiple - :fill-opacity :multiple - :fill-color-ref-id :multiple - :fill-color-ref-file :multiple - :fill-color-gradient :multiple} - plain-values) - hide-fill-on-export? (:hide-fill-on-export values false) checkbox-ref (mf/use-ref) @@ -110,12 +74,6 @@ (fn [index] (st/emit! (dc/reorder-fills ids index new-index))))) - on-change-mixed-shapes - (mf/use-callback - (mf/deps ids) - (fn [color] - (st/emit! (dc/change-fill-and-clear ids color)))) - on-remove (fn [index] (fn [] @@ -155,43 +113,33 @@ [:div.element-set [:div.element-set-title [:span label] - (when (and (not disable-remove?) (not (= :multiple (:fills values))) only-shapes?) + (when (and (not disable-remove?) (not (= :multiple (:fills values)))) [:div.add-page {:on-click on-add} i/close])] [:div.element-set-content - (if only-shapes? - (cond - (= :multiple (:fills values)) - [:div.element-set-options-group - [:div.element-set-label (tr "settings.multiple")] - [:div.element-set-actions - [:div.element-set-actions-button {:on-click on-remove-all} - i/minus]]] + (cond + (= :multiple (:fills values)) + [:div.element-set-options-group + [:div.element-set-label (tr "settings.multiple")] + [:div.element-set-actions + [:div.element-set-actions-button {:on-click on-remove-all} + i/minus]]] - (seq (:fills values)) - [:& h/sortable-container {} - (for [[index value] (d/enumerate (:fills values []))] - [:& color-row {:color {:color (:fill-color value) - :opacity (:fill-opacity value) - :id (:fill-color-ref-id value) - :file-id (:fill-color-ref-file value) - :gradient (:fill-color-gradient value)} - :index index - :title (tr "workspace.options.fill") - :on-change (on-change index) - :on-reorder (on-reorder index) - :on-detach (on-detach index) - :on-remove (on-remove index)}])]) - - [:& color-row {:color {:color (:fill-color plain-values) - :opacity (:fill-opacity plain-values) - :id (:fill-color-ref-id plain-values) - :file-id (:fill-color-ref-file plain-values) - :gradient (:fill-color-gradient plain-values)} - :title (tr "workspace.options.fill") - :on-change on-change-mixed-shapes - :on-detach (on-detach 0)}]) + (seq (:fills values)) + [:& h/sortable-container {} + (for [[index value] (d/enumerate (:fills values []))] + [:& color-row {:color {:color (:fill-color value) + :opacity (:fill-opacity value) + :id (:fill-color-ref-id value) + :file-id (:fill-color-ref-file value) + :gradient (:fill-color-gradient value)} + :index index + :title (tr "workspace.options.fill") + :on-change (on-change index) + :on-reorder (on-reorder index) + :on-detach (on-detach index) + :on-remove (on-remove index)}])]) (when (or (= type :frame) (and (= type :multiple) (some? hide-fill-on-export?))) 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 24c98f971..fd0c3502d 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 @@ -347,5 +347,3 @@ [:div.row-flex [:> grow-options opts] [:div.align-icons]]]])) - - diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs index fa1990b2a..8e7803c1c 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace.sidebar.options.shapes.text (:require - [app.common.colors :as clr] [app.common.data :as d] [app.main.data.workspace.texts :as dwt] [app.main.refs :as refs] @@ -30,19 +29,16 @@ layer-values (select-keys shape layer-attrs) - fill-values (dwt/current-text-values - {:editor-state editor-state - :shape shape - :attrs text-fill-attrs}) + fill-values (-> (dwt/current-text-values + {:editor-state editor-state + :shape shape + :attrs (conj text-fill-attrs :fills)}) + (d/update-in-when [:fill-color-gradient :type] keyword)) - fill-values (d/update-in-when fill-values [:fill-color-gradient :type] keyword) - - fill-values (cond-> fill-values - (not (contains? fill-values :fill-color)) (assoc :fill-color clr/black) - (not (contains? fill-values :fill-opacity)) (assoc :fill-opacity 1) - ;; Keep for backwards compatibility - (:fill fill-values) (assoc :fill-color (:fill fill-values)) - (:opacity fill-values) (assoc :fill-opacity (:fill fill-values))) + fill-values (if (not (contains? fill-values :fills)) + ;; Old fill format + {:fills [fill-values]} + fill-values) stroke-values (select-keys shape stroke-attrs) @@ -79,8 +75,7 @@ [:& fill-menu {:ids ids :type type - :values fill-values - :disable-remove? true}] + :values fill-values}] [:& stroke-menu {:ids ids :type type diff --git a/frontend/src/app/util/text_editor.cljs b/frontend/src/app/util/text_editor.cljs index f1d0a7735..5cf866a9e 100644 --- a/frontend/src/app/util/text_editor.cljs +++ b/frontend/src/app/util/text_editor.cljs @@ -95,6 +95,13 @@ selected (impl/getSelectedBlocks state)] (reduce update-blocks state selected))) +(defn update-editor-current-inline-styles-fn + [state update-fn] + (let [attrs (-> (.getCurrentInlineStyle ^js state) + (txt/styles-to-attrs) + (update-fn))] + (impl/applyInlineStyle state (txt/attrs-to-styles attrs)))) + (defn editor-split-block [state] (impl/splitBlockPreservingData state)) diff --git a/frontend/src/app/util/text_svg_position.cljs b/frontend/src/app/util/text_svg_position.cljs index ee9a0f0ba..5e62e3e82 100644 --- a/frontend/src/app/util/text_svg_position.cljs +++ b/frontend/src/app/util/text_svg_position.cljs @@ -119,7 +119,5 @@ :text-transform (str (get "text-transform")) :text-decoration (str (get "text-decoration")) :font-style (str (get "font-style")) - :fill-color (or (get "--fill-color") "#000000") - :fill-color-gradient (transit/decode-str (get "--fill-color-gradient")) - :fill-opacity (d/parse-double (or (get "--fill-opacity") "1")) + :fills (transit/decode-str (get "--fills")) :text text}))))))))))