Fixes exports and preview

This commit is contained in:
alonso.torres 2020-10-15 15:44:00 +02:00
parent e961492192
commit 929d620c60
15 changed files with 255 additions and 199 deletions

View file

@ -26,7 +26,9 @@
[app.main.ui.shapes.path :as path] [app.main.ui.shapes.path :as path]
[app.main.ui.shapes.rect :as rect] [app.main.ui.shapes.rect :as rect]
[app.main.ui.shapes.text :as text] [app.main.ui.shapes.text :as text]
[app.main.ui.shapes.group :as group])) [app.main.ui.shapes.group :as group]
[app.main.ui.shapes.gradients :as grad]
[app.main.ui.context :as muc]))
(def ^:private default-color "#E8E9EA") ;; $color-canvas (def ^:private default-color "#E8E9EA") ;; $color-canvas
@ -55,8 +57,14 @@
(mf/fnc frame-wrapper (mf/fnc frame-wrapper
[{:keys [shape] :as props}] [{:keys [shape] :as props}]
(let [childs (mapv #(get objects %) (:shapes shape)) (let [childs (mapv #(get objects %) (:shapes shape))
shape (geom/transform-shape shape)] shape (geom/transform-shape shape)
[:& frame-shape {:shape shape :childs childs}])))) render-id (mf/use-memo #(str (uuid/next)))]
[:& (mf/provider muc/render-ctx) {:value render-id}
[:g.frame
[:defs
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]]
[:& frame-shape {:shape shape :childs childs}]]]))))
(defn group-wrapper-factory (defn group-wrapper-factory
[objects] [objects]
@ -79,9 +87,13 @@
(when (and shape (not (:hidden shape))) (when (and shape (not (:hidden shape)))
(let [shape (geom/transform-shape frame shape) (let [shape (geom/transform-shape frame shape)
opts #js {:shape shape} opts #js {:shape shape}
filter-id (filters/get-filter-id)] render-id (mf/use-memo #(str (uuid/next)))]
[:g {:filter (filters/filter-str filter-id shape)} [:& (mf/provider muc/render-ctx) {:value render-id}
[:& filters/filters {:filter-id filter-id :shape shape}] [:g {:filter (filters/filter-str (str "filter_" render-id) shape)}
[:defs
[:& filters/filters {:shape shape}]
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]]
(case (:type shape) (case (:type shape)
:curve [:> path/path-shape opts] :curve [:> path/path-shape opts]
:text [:> text/text-shape opts] :text [:> text/text-shape opts]
@ -92,7 +104,7 @@
:circle [:> circle/circle-shape opts] :circle [:> circle/circle-shape opts]
:frame [:> frame-wrapper {:shape shape}] :frame [:> frame-wrapper {:shape shape}]
:group [:> group-wrapper {:shape shape :frame frame}] :group [:> group-wrapper {:shape shape :frame frame}]
nil)]))))) nil)]])))))
(mf/defc page-svg (mf/defc page-svg
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}

View file

@ -12,3 +12,5 @@
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(def embed-ctx (mf/create-context false)) (def embed-ctx (mf/create-context false))
(def render-ctx (mf/create-context nil))

View file

@ -9,8 +9,10 @@
(ns app.main.ui.shapes.attrs (ns app.main.ui.shapes.attrs
(:require (:require
[rumext.alpha :as mf]
[cuerdas.core :as str] [cuerdas.core :as str]
[app.util.object :as obj])) [app.util.object :as obj]
[app.main.ui.context :as muc]))
(defn- stroke-type->dasharray (defn- stroke-type->dasharray
[style] [style]
@ -24,16 +26,16 @@
(obj/merge! attrs #js {:rx (:rx shape) (obj/merge! attrs #js {:rx (:rx shape)
:ry (:ry shape)})) :ry (:ry shape)}))
(defn add-fill [attrs shape] (defn add-fill [attrs shape render-id]
(let [fill-color-gradient-id (str "fill-color-gradient_" (:render-id shape))] (let [fill-color-gradient-id (str "fill-color-gradient_" render-id)]
(if (:fill-color-gradient shape) (if (:fill-color-gradient shape)
(obj/merge! attrs #js {:fill (str/format "url(#%s)" fill-color-gradient-id)}) (obj/merge! attrs #js {:fill (str/format "url(#%s)" fill-color-gradient-id)})
(obj/merge! attrs #js {:fill (or (:fill-color shape) "transparent") (obj/merge! attrs #js {:fill (or (:fill-color shape) "transparent")
:fillOpacity (:fill-opacity shape nil)})))) :fillOpacity (:fill-opacity shape nil)}))))
(defn add-stroke [attrs shape] (defn add-stroke [attrs shape render-id]
(let [stroke-style (:stroke-style shape :none) (let [stroke-style (:stroke-style shape :none)
stroke-color-gradient-id (str "stroke-color-gradient_" (:render-id shape))] stroke-color-gradient-id (str "stroke-color-gradient_" render-id)]
(if (not= stroke-style :none) (if (not= stroke-style :none)
(if (:stroke-color-gradient shape) (if (:stroke-color-gradient shape)
(obj/merge! attrs (obj/merge! attrs
@ -49,7 +51,8 @@
(defn extract-style-attrs (defn extract-style-attrs
([shape] ([shape]
(let [render-id (mf/use-ctx muc/render-ctx)]
(-> (obj/new) (-> (obj/new)
(add-border-radius shape) (add-border-radius shape)
(add-fill shape) (add-fill shape render-id)
(add-stroke shape)))) (add-stroke shape render-id)))))

View file

@ -123,7 +123,6 @@
[filter-x filter-y filter-width filter-height] (get-filters-bounds shape filters)] [filter-x filter-y filter-width filter-height] (get-filters-bounds shape filters)]
(when (seq filters) (when (seq filters)
[:defs
[:filter {:id filter-id [:filter {:id filter-id
:x filter-x :y filter-y :x filter-x :y filter-y
:width filter-width :height filter-height :width filter-width :height filter-height
@ -162,6 +161,4 @@
[:& inner-shadow-filter {:key id [:& inner-shadow-filter {:key id
:filter-id filter-id :filter-id filter-id
:filter filter :filter filter
:shape shape}]) :shape shape}])])])))
])
]])))

View file

@ -13,6 +13,7 @@
[cuerdas.core :as str] [cuerdas.core :as str]
[app.util.object :as obj] [app.util.object :as obj]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.ui.context :as muc]
[app.common.geom.point :as gpt])) [app.common.geom.point :as gpt]))
(mf/defc linear-gradient [{:keys [id gradient shape]}] (mf/defc linear-gradient [{:keys [id gradient shape]}]
@ -32,7 +33,8 @@
(mf/defc radial-gradient [{:keys [id gradient shape]}] (mf/defc radial-gradient [{:keys [id gradient shape]}]
(let [{:keys [x y width height]} shape] (let [{:keys [x y width height]} shape]
[:defs [:defs
(let [translate-vec (gpt/point (+ x (* width (:start-x gradient))) (let [[x y] (if (= (:type shape) :frame) [0 0] [x y])
translate-vec (gpt/point (+ x (* width (:start-x gradient)))
(+ y (* height (:start-y gradient)))) (+ y (* height (:start-y gradient))))
gradient-vec (gpt/to-vec (gpt/point (* width (:start-x gradient)) gradient-vec (gpt/to-vec (gpt/point (* width (:start-x gradient))
@ -72,13 +74,13 @@
[props] [props]
(let [attr (obj/get props "attr") (let [attr (obj/get props "attr")
shape (obj/get props "shape") shape (obj/get props "shape")
render-id (obj/get props "render-id") render-id (mf/use-ctx muc/render-ctx)
id (str (name attr) "_" render-id) id (str (name attr) "_" render-id)
gradient (get shape attr) gradient (get shape attr)
gradient-props #js {:id id gradient-props #js {:id id
:gradient gradient :gradient gradient
:shape shape}] :shape shape}]
(when gradient
(case (:type gradient) (case (:type gradient)
:linear [:> linear-gradient gradient-props] :linear [:> linear-gradient gradient-props]
:radial [:> radial-gradient gradient-props]))) :radial [:> radial-gradient gradient-props]))))

View file

@ -68,9 +68,10 @@
fill-color (obj/get data "fill-color" fill) fill-color (obj/get data "fill-color" fill)
fill-opacity (obj/get data "fill-opacity" opacity) fill-opacity (obj/get data "fill-opacity" opacity)
fill-color-gradient (obj/get data "fill-color-gradient" opacity) fill-color-gradient (obj/get data "fill-color-gradient" nil)
fill-color-gradient (-> (js->clj fill-color-gradient :keywordize-keys true) fill-color-gradient (when fill-color-gradient
(update :type keyword)) (-> (js->clj fill-color-gradient :keywordize-keys true)
(update :type keyword)))
fill-color-ref-id (obj/get data "fill-color-ref-id") fill-color-ref-id (obj/get data "fill-color-ref-id")
fill-color-ref-file (obj/get data "fill-color-ref-file") fill-color-ref-file (obj/get data "fill-color-ref-file")
@ -83,14 +84,9 @@
fontsdb (deref fonts/fontsdb) fontsdb (deref fonts/fontsdb)
base #js {:textDecoration text-decoration base #js {:textDecoration text-decoration
;:color (str/format "rgba(%s, %s, %s, %s)" r g b a)
:textTransform text-transform :textTransform text-transform
:lineHeight (or line-height "inherit") :lineHeight (or line-height "inherit")
"--text-color" background}]
:background background
:WebkitTextFillColor "transparent"
:WebkitBackgroundClip "text"
}]
(when (and (string? letter-spacing) (when (and (string? letter-spacing)
(pos? (alength letter-spacing))) (pos? (alength letter-spacing)))
@ -179,8 +175,7 @@
(if (string? text) (if (string? text)
(let [style (generate-text-styles (clj->js node))] (let [style (generate-text-styles (clj->js node))]
[:span {:style style [:span.text-node {:style style} (if (= text "") "\u00A0" text)])
:key (str index "-" (:fill-color node))} (if (= text "") "\u00A0" text)])
(let [children (map-indexed (fn [index node] (let [children (map-indexed (fn [index node]
(mf/element text-node {:index index :node node :key index})) (mf/element text-node {:index index :node node :key index}))
children)] children)]
@ -192,8 +187,10 @@
{:key index {:key index
:style style :style style
:xmlns "http://www.w3.org/1999/xhtml"} :xmlns "http://www.w3.org/1999/xhtml"}
[:*
[:style ".text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"]
(when (not (nil? @embeded-fonts)) (when (not (nil? @embeded-fonts))
[:style @embeded-fonts]) [:style @embeded-fonts])]
children]) children])
"paragraph-set" "paragraph-set"

View file

@ -29,7 +29,10 @@
[app.util.object :as obj] [app.util.object :as obj]
[app.common.geom.matrix :as gmt] [app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as geom])) [app.common.geom.shapes :as geom]
[app.common.uuid :as uuid]
[app.main.ui.shapes.gradients :as grad]
[app.main.ui.context :as muc]))
(defn on-mouse-down (defn on-mouse-down
[event {:keys [interactions] :as shape}] [event {:keys [interactions] :as shape}]
@ -56,12 +59,16 @@
(mf/deps shape) (mf/deps shape)
#(on-mouse-down % shape)) #(on-mouse-down % shape))
filter-id (filters/get-filter-id)] render-id (mf/use-memo #(str (uuid/next)))]
[:& (mf/provider muc/render-ctx) {:value render-id}
[:g.shape {:on-mouse-down on-mouse-down [:g.shape {:on-mouse-down on-mouse-down
:cursor (when (:interactions shape) "pointer") :cursor (when (:interactions shape) "pointer")
:filter (filters/filter-str filter-id shape)} :filter (filters/filter-str (str "filter_" render-id) shape)}
[:& filters/filters {:filter-id filter-id :shape shape}] [:defs
[:& filters/filters {:shape shape}]
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]]
[:& component {:shape shape [:& component {:shape shape
:frame frame :frame frame
:childs childs :childs childs
@ -74,7 +81,7 @@
:fill "#31EFB8" :fill "#31EFB8"
:stroke "#31EFB8" :stroke "#31EFB8"
:stroke-width 1 :stroke-width 1
:fill-opacity 0.2}])]))) :fill-opacity 0.2}])]])))
(defn frame-wrapper (defn frame-wrapper
[shape-container show-interactions?] [shape-container show-interactions?]

View file

@ -369,15 +369,7 @@
(reset! dirty? (not= data new-data)) (reset! dirty? (not= data new-data))
(reset! last-change new-data) (reset! last-change new-data)
(when on-change (when on-change
(on-change new-data))) (on-change new-data)))]
;; handle-change (fn [new-value new-opacity id file-id shift-clicked?]
;; (when (or (not= new-value value) (not= new-opacity opacity))
;; (reset! dirty? true))
;; (reset! last-change [new-value new-opacity id file-id])
;; (when on-change
;; (on-change new-value new-opacity id file-id shift-clicked?)))
]
(mf/use-effect (mf/use-effect
(fn [] (fn []

View file

@ -13,6 +13,7 @@
[cuerdas.core :as str] [cuerdas.core :as str]
[okulary.core :as l] [okulary.core :as l]
[promesa.core :as p] [promesa.core :as p]
[beicon.core :as rx]
[goog.events :as events] [goog.events :as events]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.util.timers :as timers] [app.util.timers :as timers]
@ -53,6 +54,19 @@
[:& shape-wrapper {:shape item [:& shape-wrapper {:shape item
:key (:id item)}]))]])) :key (:id item)}]))]]))
(defn draw-picker-canvas [svg-node canvas-node]
(let [canvas-context (.getContext canvas-node "2d")
xml (.serializeToString (js/XMLSerializer.) svg-node)
img-src (str "data:image/svg+xml;base64,"
(-> xml js/encodeURIComponent js/unescape js/btoa))
img (js/Image.)
on-error (fn [err] (.error js/console "ERROR" err))
on-load (fn [] (.drawImage canvas-context img 0 0))]
(.addEventListener img "error" on-error)
(.addEventListener img "load" on-load)
(obj/set! img "src" img-src)))
(mf/defc pixel-overlay (mf/defc pixel-overlay
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [props]
@ -64,6 +78,8 @@
canvas-ref (mf/use-ref nil) canvas-ref (mf/use-ref nil)
fetch-pending (mf/deref (mdf/pending-ref)) fetch-pending (mf/deref (mdf/pending-ref))
update-canvas-stream (rx/subject)
handle-keydown handle-keydown
(fn [event] (fn [event]
(when (and (kbd/esc? event)) (when (and (kbd/esc? event))
@ -117,26 +133,30 @@
#(events/unlistenByKey listener)))) #(events/unlistenByKey listener))))
(mf/use-effect (mf/use-effect
;; Everytime we finish retrieving a new URL we redraw the canvas
;; so even if we're not finished the user can start to pick basic
;; shapes
(mf/deps fetch-pending)
(fn [] (fn []
(try (let [sub (->> update-canvas-stream
(let [canvas-node (mf/ref-val canvas-ref) (rx/debounce 10)
canvas-context (.getContext canvas-node "2d") (rx/subs #(draw-picker-canvas (mf/ref-val svg-ref)
svg-node (mf/ref-val svg-ref)] (mf/ref-val canvas-ref))))]
(timers/schedule 100
#(let [xml (.serializeToString (js/XMLSerializer.) svg-node) #(rx/dispose! sub))))
img-src (str "data:image/svg+xml;base64,"
(-> xml js/encodeURIComponent js/unescape js/btoa)) (mf/use-effect
img (js/Image.) (mf/deps svg-ref canvas-ref)
on-error (fn [err] (.error js/console "ERROR" err)) (fn []
on-load (fn [] (.drawImage canvas-context img 0 0))] (when (and svg-ref canvas-ref)
(.addEventListener img "error" on-error)
(.addEventListener img "load" on-load) (let [config (clj->js {:attributes true
(obj/set! img "src" img-src)))) :childList true
(catch :default e (.error js/console e))))) :subtree true
:characterData true})
on-svg-change (fn [mutation-list] (rx/push! update-canvas-stream :update))
observer (js/MutationObserver. on-svg-change)]
(.observe observer (mf/ref-val svg-ref) config)
;; Disconnect on unmount
#(.disconnect observer)))))
[:* [:*
[:div.overlay [:div.overlay
@ -154,6 +174,7 @@
:width (:width vport 0) :width (:width vport 0)
:height (:height vport 0) :height (:height vport 0)
:style {:display "none"}}] :style {:display "none"}}]
[:& (mf/provider muc/embed-ctx) {:value true} [:& (mf/provider muc/embed-ctx) {:value true}
[:svg.viewport [:svg.viewport
{:ref svg-ref {:ref svg-ref

View file

@ -284,7 +284,9 @@
(change! {:width norm-dist})))] (change! {:width norm-dist})))]
(when (and gradient (= id (:shape-id gradient))) (when (and gradient
(= id (:shape-id gradient))
(not= (:type shape) :text))
[:& gradient-handler-transformed [:& gradient-handler-transformed
{:editing editing-spot {:editing editing-spot
:from-p from-p :from-p from-p

View file

@ -20,7 +20,8 @@
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.common.geom.matrix :as gmt] [app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as geom])) [app.common.geom.shapes :as geom]
[app.main.ui.context :as muc]))
(defn- on-mouse-down (defn- on-mouse-down
[event {:keys [id type] :as shape}] [event {:keys [id type] :as shape}]
@ -75,22 +76,15 @@
#(on-context-menu % shape)) #(on-context-menu % shape))
render-id (mf/use-memo #(str (uuid/next)))] render-id (mf/use-memo #(str (uuid/next)))]
[:& (mf/provider muc/render-ctx) {:value render-id}
[:g.shape {:on-mouse-down on-mouse-down [:g.shape {:on-mouse-down on-mouse-down
:on-context-menu on-context-menu :on-context-menu on-context-menu
:filter (filters/filter-str (str "filter_" render-id) shape)} :filter (filters/filter-str (str "filter_" render-id) shape)}
[:defs
[:& filters/filters {:shape shape}]
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]]
[:& filters/filters {:filter-id (str "filter_" render-id) :shape shape}] [:& component {:shape shape}]]])))
(when (:fill-color-gradient shape)
[:& grad/gradient {:attr :fill-color-gradient
:render-id render-id
:shape shape}])
(when (:stroke-color-gradient shape)
[:& grad/gradient {:attr :stroke-color-gradient
:render-id render-id
:shape shape}])
[:& component {:shape (assoc shape :render-id render-id)}]])))

View file

@ -26,7 +26,9 @@
[app.common.geom.shapes :as geom] [app.common.geom.shapes :as geom]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.main.streams :as ms] [app.main.streams :as ms]
[app.util.timers :as ts])) [app.util.timers :as ts]
[app.main.ui.context :as muc]
[app.common.uuid :as uuid]))
(defn- frame-wrapper-factory-equals? (defn- frame-wrapper-factory-equals?
[np op] [np op]
@ -115,7 +117,7 @@
(fn [] (fn []
(st/emit! (dws/change-hover-state (:id shape) false)))) (st/emit! (dws/change-hover-state (:id shape) false))))
filter-id (mf/use-memo filters/get-filter-id)] render-id (mf/use-memo #(str (uuid/next)))]
(when-not (:hidden shape) (when-not (:hidden shape)
[:g {:class (when selected? "selected") [:g {:class (when selected? "selected")
@ -128,18 +130,14 @@
:on-double-click on-double-click :on-double-click on-double-click
:on-mouse-down on-mouse-down}] :on-mouse-down on-mouse-down}]
[:g.frame {:filter (filters/filter-str filter-id shape)} [:& (mf/provider muc/render-ctx) {:value render-id}
[:& filters/filters {:filter-id filter-id :shape shape}] [:g.frame {:filter (filters/filter-str (str "filter_" render-id) shape)}
[:defs
(when (:fill-color-gradient shape) [:& filters/filters {:shape shape}]
[:& grad/gradient {:attr :fill-color-gradient [:& grad/gradient {:shape shape :attr :fill-color-gradient}]
:shape shape}]) [:& grad/gradient {:shape shape :attr :stroke-color-gradient}]]
(when (:stroke-color-gradient shape)
[:& grad/gradient {:attr :stroke-color-gradient
:shape shape}])
[:& frame-shape [:& frame-shape
{:shape shape {:shape shape
:childs children}]]]))))) :childs children}]]]])))))

View file

@ -23,7 +23,10 @@
[app.main.data.workspace.drawing :as dr] [app.main.data.workspace.drawing :as dr]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.main.streams :as ms] [app.main.streams :as ms]
[app.util.timers :as ts])) [app.util.timers :as ts]
[app.common.uuid :as uuid]
[app.main.ui.shapes.gradients :as grad]
[app.main.ui.context :as muc]))
(mf/defc path-wrapper (mf/defc path-wrapper
{::mf/wrap-props false} {::mf/wrap-props false}
@ -45,21 +48,18 @@
(dom/prevent-default event) (dom/prevent-default event)
(st/emit! (dw/start-edition-mode (:id shape))))))) (st/emit! (dw/start-edition-mode (:id shape)))))))
filter-id (mf/use-memo filters/get-filter-id)] render-id (mf/use-memo #(str (uuid/next)))]
[:& (mf/provider muc/render-ctx) {:value render-id}
[:g.shape {:on-double-click on-double-click [:g.shape {:on-double-click on-double-click
:on-mouse-down on-mouse-down :on-mouse-down on-mouse-down
:on-context-menu on-context-menu :on-context-menu on-context-menu
:filter (filters/filter-str filter-id shape)} :filter (filters/filter-str (str "filter_" render-id) shape)}
[:& filters/filters {:filter-id filter-id :shape shape}] [:defs
[:& filters/filters {:shape shape}]
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]]
(when (:fill-color-gradient shape)
[:& grad/gradient {:attr :fill-color-gradient
:shape shape}])
(when (:stroke-color-gradient shape)
[:& grad/gradient {:attr :stroke-color-gradient
:shape shape}])
[:& path/path-shape {:shape shape [:& path/path-shape {:shape shape
:background? true}]])) :background? true}]]]))

View file

@ -34,7 +34,10 @@
[app.util.color :as uc] [app.util.color :as uc]
[app.util.timers :as timers] [app.util.timers :as timers]
["slate" :as slate] ["slate" :as slate]
["slate-react" :as rslate]) ["slate-react" :as rslate]
[app.common.uuid :as uuid]
[app.main.ui.shapes.gradients :as grad]
[app.main.ui.context :as muc])
(:import (:import
goog.events.EventType goog.events.EventType
goog.events.KeyCodes)) goog.events.KeyCodes))
@ -80,7 +83,7 @@
(when selected? (when selected?
(st/emit! (dw/start-edition-mode (:id shape))))) (st/emit! (dw/start-edition-mode (:id shape)))))
filter-id (mf/use-memo filters/get-filter-id)] render-id (mf/use-memo #(str (uuid/next)))]
(mf/use-effect (mf/use-effect
(mf/deps shape edition selected? current-transform) (mf/deps shape edition selected? current-transform)
@ -91,11 +94,15 @@
(nil? current-transform))] (nil? current-transform))]
(timers/schedule #(reset! render-editor check?))))) (timers/schedule #(reset! render-editor check?)))))
[:& (mf/provider muc/render-ctx) {:value render-id}
[:g.shape {:on-double-click on-double-click [:g.shape {:on-double-click on-double-click
:on-mouse-down on-mouse-down :on-mouse-down on-mouse-down
:on-context-menu on-context-menu :on-context-menu on-context-menu
:filter (filters/filter-str filter-id shape)} :filter (filters/filter-str (str "filter_" render-id) shape)}
[:& filters/filters {:filter-id filter-id :shape shape}] [:defs
[:& filters/filters {:shape shape}]
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]]
[:* [:*
(when @render-editor (when @render-editor
[:g {:opacity 0 [:g {:opacity 0
@ -107,7 +114,7 @@
(if edition? (if edition?
[:& text-shape-edit {:shape shape}] [:& text-shape-edit {:shape shape}]
[:& text/text-shape {:shape shape [:& text/text-shape {:shape shape
:selected? selected?}])]])) :selected? selected?}])]]]))
;; --- Text Editor Rendering ;; --- Text Editor Rendering
@ -158,17 +165,25 @@
fill-color (obj/get data "fill-color" fill) fill-color (obj/get data "fill-color" fill)
fill-opacity (obj/get data "fill-opacity" opacity) fill-opacity (obj/get data "fill-opacity" opacity)
fill-color-gradient (obj/get data "fill-color-gradient" nil)
fill-color-gradient (when fill-color-gradient
(-> (js->clj fill-color-gradient :keywordize-keys true)
(update :type keyword)))
fill-color-ref-id (obj/get data "fill-color-ref-id") fill-color-ref-id (obj/get data "fill-color-ref-id")
fill-color-ref-file (obj/get data "fill-color-ref-file") fill-color-ref-file (obj/get data "fill-color-ref-file")
[r g b a] (uc/hex->rgba fill-color fill-opacity) [r g b a] (uc/hex->rgba fill-color fill-opacity)
background (if fill-color-gradient
(uc/gradient->css (js->clj fill-color-gradient))
(str/format "rgba(%s, %s, %s, %s)" r g b a))
fontsdb (deref fonts/fontsdb) fontsdb (deref fonts/fontsdb)
base #js {:textDecoration text-decoration base #js {:textDecoration text-decoration
:color (str/format "rgba(%s, %s, %s, %s)" r g b a)
:textTransform text-transform :textTransform text-transform
:lineHeight (or line-height "inherit")}] :lineHeight (or line-height "inherit")
"--text-color" background}]
(when (and (string? letter-spacing) (when (and (string? letter-spacing)
(pos? (alength letter-spacing))) (pos? (alength letter-spacing)))
@ -243,7 +258,9 @@
childs (obj/get props "children") childs (obj/get props "children")
data (obj/get props "leaf") data (obj/get props "leaf")
style (generate-text-styles data) style (generate-text-styles data)
attrs (obj/set! attrs "style" style)] attrs (-> attrs
(obj/set! "style" style)
(obj/set! "className" "text-node"))]
[:> :span attrs childs])) [:> :span attrs childs]))
(defn- render-element (defn- render-element
@ -284,6 +301,14 @@
children-count (->> node :children (map content-size) (reduce +))] children-count (->> node :children (map content-size) (reduce +))]
(+ current children-count))) (+ current children-count)))
(defn fix-gradients
"Fix for the gradient types that need to be keywords"
[content]
(let [fix-node
(fn [node]
(d/update-in-when node [:fill-color-gradient :type] keyword))]
(ut/map-node fix-node content)))
(mf/defc text-shape-edit (mf/defc text-shape-edit
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [shape read-only?] :or {read-only? false} :as props}] [{:keys [shape read-only?] :or {read-only? false} :as props}]
@ -364,7 +389,8 @@
(fn [val] (fn [val]
(when (not read-only?) (when (not read-only?)
(let [content (js->clj val :keywordize-keys true) (let [content (js->clj val :keywordize-keys true)
content (first content)] content (first content)
content (fix-gradients content)]
;; Append timestamp so we can react to cursor change events ;; Append timestamp so we can react to cursor change events
(st/emit! (dw/update-shape id {:content (assoc content :ts (js->clj (.now js/Date)))})) (st/emit! (dw/update-shape id {:content (assoc content :ts (js->clj (.now js/Date)))}))
(reset! state val) (reset! state val)
@ -419,7 +445,8 @@
:x x :y y :x x :y y
:width (if (= :auto-width grow-type) 10000 width) :width (if (= :auto-width grow-type) 10000 width)
:height height} :height height}
[:style "span { line-height: inherit; }"] [:style "span { line-height: inherit; }
.text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"]
[:> rslate/Slate {:editor editor [:> rslate/Slate {:editor editor
:value @state :value @state
:on-change on-change} :on-change on-change}

View file

@ -290,6 +290,8 @@
:shape shape :shape shape
:attrs text-fill-attrs}) :attrs text-fill-attrs})
fill-values (d/update-in-when fill-values [:fill-color-gradient :type] keyword)
fill-values (cond-> fill-values fill-values (cond-> fill-values
;; Keep for backwards compatibility ;; Keep for backwards compatibility
(:fill fill-values) (assoc :fill-color (:fill fill-values)) (:fill fill-values) (assoc :fill-color (:fill fill-values))