mirror of
https://github.com/penpot/penpot.git
synced 2025-03-13 16:21:57 -05:00
✨ Fixes exports and preview
This commit is contained in:
parent
e961492192
commit
929d620c60
15 changed files with 255 additions and 199 deletions
|
@ -26,7 +26,9 @@
|
|||
[app.main.ui.shapes.path :as path]
|
||||
[app.main.ui.shapes.rect :as rect]
|
||||
[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
|
||||
|
||||
|
@ -55,8 +57,14 @@
|
|||
(mf/fnc frame-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(let [childs (mapv #(get objects %) (:shapes shape))
|
||||
shape (geom/transform-shape shape)]
|
||||
[:& frame-shape {:shape shape :childs childs}]))))
|
||||
shape (geom/transform-shape shape)
|
||||
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
|
||||
[objects]
|
||||
|
@ -79,20 +87,24 @@
|
|||
(when (and shape (not (:hidden shape)))
|
||||
(let [shape (geom/transform-shape frame shape)
|
||||
opts #js {:shape shape}
|
||||
filter-id (filters/get-filter-id)]
|
||||
[:g {:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
(case (:type shape)
|
||||
:curve [:> path/path-shape opts]
|
||||
:text [:> text/text-shape opts]
|
||||
:icon [:> icon/icon-shape opts]
|
||||
:rect [:> rect/rect-shape opts]
|
||||
:path [:> path/path-shape opts]
|
||||
:image [:> image/image-shape opts]
|
||||
:circle [:> circle/circle-shape opts]
|
||||
:frame [:> frame-wrapper {:shape shape}]
|
||||
:group [:> group-wrapper {:shape shape :frame frame}]
|
||||
nil)])))))
|
||||
render-id (mf/use-memo #(str (uuid/next)))]
|
||||
[:& (mf/provider muc/render-ctx) {:value render-id}
|
||||
[: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)
|
||||
:curve [:> path/path-shape opts]
|
||||
:text [:> text/text-shape opts]
|
||||
:icon [:> icon/icon-shape opts]
|
||||
:rect [:> rect/rect-shape opts]
|
||||
:path [:> path/path-shape opts]
|
||||
:image [:> image/image-shape opts]
|
||||
:circle [:> circle/circle-shape opts]
|
||||
:frame [:> frame-wrapper {:shape shape}]
|
||||
:group [:> group-wrapper {:shape shape :frame frame}]
|
||||
nil)]])))))
|
||||
|
||||
(mf/defc page-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
|
|
@ -12,3 +12,5 @@
|
|||
[rumext.alpha :as mf]))
|
||||
|
||||
(def embed-ctx (mf/create-context false))
|
||||
|
||||
(def render-ctx (mf/create-context nil))
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
|
||||
(ns app.main.ui.shapes.attrs
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.util.object :as obj]))
|
||||
[app.util.object :as obj]
|
||||
[app.main.ui.context :as muc]))
|
||||
|
||||
(defn- stroke-type->dasharray
|
||||
[style]
|
||||
|
@ -24,16 +26,16 @@
|
|||
(obj/merge! attrs #js {:rx (:rx shape)
|
||||
:ry (:ry shape)}))
|
||||
|
||||
(defn add-fill [attrs shape]
|
||||
(let [fill-color-gradient-id (str "fill-color-gradient_" (:render-id shape))]
|
||||
(defn add-fill [attrs shape render-id]
|
||||
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id)]
|
||||
(if (:fill-color-gradient shape)
|
||||
(obj/merge! attrs #js {:fill (str/format "url(#%s)" fill-color-gradient-id)})
|
||||
(obj/merge! attrs #js {:fill (or (:fill-color shape) "transparent")
|
||||
:fillOpacity (:fill-opacity shape nil)}))))
|
||||
|
||||
(defn add-stroke [attrs shape]
|
||||
(defn add-stroke [attrs shape render-id]
|
||||
(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 (:stroke-color-gradient shape)
|
||||
(obj/merge! attrs
|
||||
|
@ -49,7 +51,8 @@
|
|||
|
||||
(defn extract-style-attrs
|
||||
([shape]
|
||||
(-> (obj/new)
|
||||
(add-border-radius shape)
|
||||
(add-fill shape)
|
||||
(add-stroke shape))))
|
||||
(let [render-id (mf/use-ctx muc/render-ctx)]
|
||||
(-> (obj/new)
|
||||
(add-border-radius shape)
|
||||
(add-fill shape render-id)
|
||||
(add-stroke shape render-id)))))
|
||||
|
|
|
@ -123,45 +123,42 @@
|
|||
|
||||
[filter-x filter-y filter-width filter-height] (get-filters-bounds shape filters)]
|
||||
(when (seq filters)
|
||||
[:defs
|
||||
[:filter {:id filter-id
|
||||
:x filter-x :y filter-y
|
||||
:width filter-width :height filter-height
|
||||
:filterUnits "userSpaceOnUse"
|
||||
:color-interpolation-filters "sRGB"}
|
||||
[:filter {:id filter-id
|
||||
:x filter-x :y filter-y
|
||||
:width filter-width :height filter-height
|
||||
:filterUnits "userSpaceOnUse"
|
||||
:color-interpolation-filters "sRGB"}
|
||||
|
||||
(let [;; Add as a paramter the input filter
|
||||
drop-shadow-filters (->> filters (filter #(= :drop-shadow (:style %))))
|
||||
drop-shadow-filters (->> drop-shadow-filters
|
||||
(map #(str "filter" (:id %)))
|
||||
(cons "BackgroundImageFix")
|
||||
(map add-in-filter drop-shadow-filters))
|
||||
(let [;; Add as a paramter the input filter
|
||||
drop-shadow-filters (->> filters (filter #(= :drop-shadow (:style %))))
|
||||
drop-shadow-filters (->> drop-shadow-filters
|
||||
(map #(str "filter" (:id %)))
|
||||
(cons "BackgroundImageFix")
|
||||
(map add-in-filter drop-shadow-filters))
|
||||
|
||||
inner-shadow-filters (->> filters (filter #(= :inner-shadow (:style %))))
|
||||
inner-shadow-filters (->> inner-shadow-filters
|
||||
inner-shadow-filters (->> filters (filter #(= :inner-shadow (:style %))))
|
||||
inner-shadow-filters (->> inner-shadow-filters
|
||||
(map #(str "filter" (:id %)))
|
||||
(cons "shape")
|
||||
(map add-in-filter inner-shadow-filters))]
|
||||
|
||||
[:*
|
||||
[:feFlood {:flood-opacity 0 :result "BackgroundImageFix"}]
|
||||
(for [{:keys [id type] :as filter} drop-shadow-filters]
|
||||
[:& drop-shadow-filter {:key id
|
||||
[:*
|
||||
[:feFlood {:flood-opacity 0 :result "BackgroundImageFix"}]
|
||||
(for [{:keys [id type] :as filter} drop-shadow-filters]
|
||||
[:& drop-shadow-filter {:key id
|
||||
:filter-id filter-id
|
||||
:filter filter
|
||||
:shape shape}])
|
||||
|
||||
[:feBlend {:mode "normal"
|
||||
:in "SourceGraphic"
|
||||
:in2 (if (seq drop-shadow-filters)
|
||||
(str "filter" (:id (last drop-shadow-filters)))
|
||||
"BackgroundImageFix")
|
||||
:result "shape"}]
|
||||
|
||||
(for [{:keys [id type] :as filter} inner-shadow-filters]
|
||||
[:& inner-shadow-filter {:key id
|
||||
:filter-id filter-id
|
||||
:filter filter
|
||||
:shape shape}])
|
||||
|
||||
[:feBlend {:mode "normal"
|
||||
:in "SourceGraphic"
|
||||
:in2 (if (seq drop-shadow-filters)
|
||||
(str "filter" (:id (last drop-shadow-filters)))
|
||||
"BackgroundImageFix")
|
||||
:result "shape"}]
|
||||
|
||||
(for [{:keys [id type] :as filter} inner-shadow-filters]
|
||||
[:& inner-shadow-filter {:key id
|
||||
:filter-id filter-id
|
||||
:filter filter
|
||||
:shape shape}])
|
||||
])
|
||||
]])))
|
||||
:shape shape}])])])))
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[cuerdas.core :as str]
|
||||
[app.util.object :as obj]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.ui.context :as muc]
|
||||
[app.common.geom.point :as gpt]))
|
||||
|
||||
(mf/defc linear-gradient [{:keys [id gradient shape]}]
|
||||
|
@ -32,7 +33,8 @@
|
|||
(mf/defc radial-gradient [{:keys [id gradient shape]}]
|
||||
(let [{:keys [x y width height]} shape]
|
||||
[: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))))
|
||||
|
||||
gradient-vec (gpt/to-vec (gpt/point (* width (:start-x gradient))
|
||||
|
@ -72,13 +74,13 @@
|
|||
[props]
|
||||
(let [attr (obj/get props "attr")
|
||||
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)
|
||||
gradient (get shape attr)
|
||||
gradient-props #js {:id id
|
||||
:gradient gradient
|
||||
:shape shape}]
|
||||
(case (:type gradient)
|
||||
:linear [:> linear-gradient gradient-props]
|
||||
:radial [:> radial-gradient gradient-props])))
|
||||
(when gradient
|
||||
(case (:type gradient)
|
||||
:linear [:> linear-gradient gradient-props]
|
||||
:radial [:> radial-gradient gradient-props]))))
|
||||
|
|
|
@ -68,9 +68,10 @@
|
|||
|
||||
fill-color (obj/get data "fill-color" fill)
|
||||
fill-opacity (obj/get data "fill-opacity" opacity)
|
||||
fill-color-gradient (obj/get data "fill-color-gradient" opacity)
|
||||
fill-color-gradient (-> (js->clj fill-color-gradient :keywordize-keys true)
|
||||
(update :type keyword))
|
||||
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-file (obj/get data "fill-color-ref-file")
|
||||
|
@ -83,14 +84,9 @@
|
|||
fontsdb (deref fonts/fontsdb)
|
||||
|
||||
base #js {:textDecoration text-decoration
|
||||
;:color (str/format "rgba(%s, %s, %s, %s)" r g b a)
|
||||
:textTransform text-transform
|
||||
:lineHeight (or line-height "inherit")
|
||||
|
||||
:background background
|
||||
:WebkitTextFillColor "transparent"
|
||||
:WebkitBackgroundClip "text"
|
||||
}]
|
||||
"--text-color" background}]
|
||||
|
||||
(when (and (string? letter-spacing)
|
||||
(pos? (alength letter-spacing)))
|
||||
|
@ -179,8 +175,7 @@
|
|||
|
||||
(if (string? text)
|
||||
(let [style (generate-text-styles (clj->js node))]
|
||||
[:span {:style style
|
||||
:key (str index "-" (:fill-color node))} (if (= text "") "\u00A0" text)])
|
||||
[:span.text-node {:style style} (if (= text "") "\u00A0" text)])
|
||||
(let [children (map-indexed (fn [index node]
|
||||
(mf/element text-node {:index index :node node :key index}))
|
||||
children)]
|
||||
|
@ -192,13 +187,15 @@
|
|||
{:key index
|
||||
:style style
|
||||
:xmlns "http://www.w3.org/1999/xhtml"}
|
||||
(when (not (nil? @embeded-fonts))
|
||||
[:style @embeded-fonts])
|
||||
[:*
|
||||
[:style ".text-node { background: var(--text-color); -webkit-text-fill-color: transparent; -webkit-background-clip: text;"]
|
||||
(when (not (nil? @embeded-fonts))
|
||||
[:style @embeded-fonts])]
|
||||
children])
|
||||
|
||||
"paragraph-set"
|
||||
(let [style #js {:display "inline-block"}]
|
||||
[:div.paragraphs {:key index :style style} children])
|
||||
[:div.paragraphs {:key index :style style} children])
|
||||
|
||||
"paragraph"
|
||||
(let [style (generate-paragraph-styles (clj->js node))]
|
||||
|
|
|
@ -29,7 +29,10 @@
|
|||
[app.util.object :as obj]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[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
|
||||
[event {:keys [interactions] :as shape}]
|
||||
|
@ -56,25 +59,29 @@
|
|||
(mf/deps shape)
|
||||
#(on-mouse-down % shape))
|
||||
|
||||
filter-id (filters/get-filter-id)]
|
||||
render-id (mf/use-memo #(str (uuid/next)))]
|
||||
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")
|
||||
:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
[:& component {:shape shape
|
||||
:frame frame
|
||||
:childs childs
|
||||
:is-child-selected? true}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:rect {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:stroke-width 1
|
||||
:fill-opacity 0.2}])])))
|
||||
[:& (mf/provider muc/render-ctx) {:value render-id}
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")
|
||||
: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}]]
|
||||
[:& component {:shape shape
|
||||
:frame frame
|
||||
:childs childs
|
||||
:is-child-selected? true}]
|
||||
(when (and (:interactions shape) show-interactions?)
|
||||
[:rect {:x (- x 1)
|
||||
:y (- y 1)
|
||||
:width (+ width 2)
|
||||
:height (+ height 2)
|
||||
:fill "#31EFB8"
|
||||
:stroke "#31EFB8"
|
||||
:stroke-width 1
|
||||
:fill-opacity 0.2}])]])))
|
||||
|
||||
(defn frame-wrapper
|
||||
[shape-container show-interactions?]
|
||||
|
|
|
@ -369,15 +369,7 @@
|
|||
(reset! dirty? (not= data new-data))
|
||||
(reset! last-change new-data)
|
||||
(when on-change
|
||||
(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?)))
|
||||
]
|
||||
(on-change new-data)))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[promesa.core :as p]
|
||||
[beicon.core :as rx]
|
||||
[goog.events :as events]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.util.timers :as timers]
|
||||
|
@ -53,6 +54,19 @@
|
|||
[:& shape-wrapper {:shape 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/wrap-props false}
|
||||
[props]
|
||||
|
@ -64,6 +78,8 @@
|
|||
canvas-ref (mf/use-ref nil)
|
||||
fetch-pending (mf/deref (mdf/pending-ref))
|
||||
|
||||
update-canvas-stream (rx/subject)
|
||||
|
||||
handle-keydown
|
||||
(fn [event]
|
||||
(when (and (kbd/esc? event))
|
||||
|
@ -117,26 +133,30 @@
|
|||
#(events/unlistenByKey listener))))
|
||||
|
||||
(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 []
|
||||
(try
|
||||
(let [canvas-node (mf/ref-val canvas-ref)
|
||||
canvas-context (.getContext canvas-node "2d")
|
||||
svg-node (mf/ref-val svg-ref)]
|
||||
(timers/schedule 100
|
||||
#(let [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))))
|
||||
(catch :default e (.error js/console e)))))
|
||||
(let [sub (->> update-canvas-stream
|
||||
(rx/debounce 10)
|
||||
(rx/subs #(draw-picker-canvas (mf/ref-val svg-ref)
|
||||
(mf/ref-val canvas-ref))))]
|
||||
|
||||
#(rx/dispose! sub))))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps svg-ref canvas-ref)
|
||||
(fn []
|
||||
(when (and svg-ref canvas-ref)
|
||||
|
||||
(let [config (clj->js {:attributes true
|
||||
:childList true
|
||||
: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
|
||||
|
@ -154,6 +174,7 @@
|
|||
:width (:width vport 0)
|
||||
:height (:height vport 0)
|
||||
:style {:display "none"}}]
|
||||
|
||||
[:& (mf/provider muc/embed-ctx) {:value true}
|
||||
[:svg.viewport
|
||||
{:ref svg-ref
|
||||
|
|
|
@ -284,7 +284,9 @@
|
|||
|
||||
(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
|
||||
{:editing editing-spot
|
||||
:from-p from-p
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[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
|
||||
[event {:keys [id type] :as shape}]
|
||||
|
@ -75,22 +76,15 @@
|
|||
#(on-context-menu % shape))
|
||||
render-id (mf/use-memo #(str (uuid/next)))]
|
||||
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:on-context-menu on-context-menu
|
||||
:filter (filters/filter-str (str "filter_" render-id) shape)}
|
||||
[:& (mf/provider muc/render-ctx) {:value render-id}
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:on-context-menu on-context-menu
|
||||
: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}]
|
||||
|
||||
(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)}]])))
|
||||
[:& component {:shape shape}]]])))
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
[app.common.geom.shapes :as geom]
|
||||
[app.util.dom :as dom]
|
||||
[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?
|
||||
[np op]
|
||||
|
@ -115,7 +117,7 @@
|
|||
(fn []
|
||||
(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)
|
||||
[:g {:class (when selected? "selected")
|
||||
|
@ -128,18 +130,14 @@
|
|||
:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down}]
|
||||
|
||||
[:g.frame {:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
|
||||
(when (:fill-color-gradient shape)
|
||||
[:& grad/gradient {:attr :fill-color-gradient
|
||||
:shape shape}])
|
||||
[:& (mf/provider muc/render-ctx) {:value render-id}
|
||||
[:g.frame {: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}]]
|
||||
|
||||
(when (:stroke-color-gradient shape)
|
||||
[:& grad/gradient {:attr :stroke-color-gradient
|
||||
:shape shape}])
|
||||
|
||||
[:& frame-shape
|
||||
{:shape shape
|
||||
:childs children}]]])))))
|
||||
[:& frame-shape
|
||||
{:shape shape
|
||||
:childs children}]]]])))))
|
||||
|
||||
|
|
|
@ -23,7 +23,10 @@
|
|||
[app.main.data.workspace.drawing :as dr]
|
||||
[app.util.dom :as dom]
|
||||
[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/wrap-props false}
|
||||
|
@ -45,21 +48,18 @@
|
|||
(dom/prevent-default event)
|
||||
(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)))]
|
||||
|
||||
[:g.shape {:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-context-menu on-context-menu
|
||||
:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
[:& (mf/provider muc/render-ctx) {:value render-id}
|
||||
[:g.shape {:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-context-menu on-context-menu
|
||||
: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}]]
|
||||
|
||||
(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
|
||||
:background? true}]]))
|
||||
[:& path/path-shape {:shape shape
|
||||
:background? true}]]]))
|
||||
|
||||
|
|
|
@ -34,7 +34,10 @@
|
|||
[app.util.color :as uc]
|
||||
[app.util.timers :as timers]
|
||||
["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
|
||||
goog.events.EventType
|
||||
goog.events.KeyCodes))
|
||||
|
@ -80,7 +83,7 @@
|
|||
(when selected?
|
||||
(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/deps shape edition selected? current-transform)
|
||||
|
@ -91,23 +94,27 @@
|
|||
(nil? current-transform))]
|
||||
(timers/schedule #(reset! render-editor check?)))))
|
||||
|
||||
[:g.shape {:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-context-menu on-context-menu
|
||||
:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
[:*
|
||||
(when @render-editor
|
||||
[:g {:opacity 0
|
||||
:style {:pointer-events "none"}}
|
||||
;; We only render the component for its side-effect
|
||||
[:& text-shape-edit {:shape shape
|
||||
:read-only? true}]])
|
||||
[:& (mf/provider muc/render-ctx) {:value render-id}
|
||||
[:g.shape {:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-context-menu on-context-menu
|
||||
: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}]]
|
||||
[:*
|
||||
(when @render-editor
|
||||
[:g {:opacity 0
|
||||
:style {:pointer-events "none"}}
|
||||
;; We only render the component for its side-effect
|
||||
[:& text-shape-edit {:shape shape
|
||||
:read-only? true}]])
|
||||
|
||||
(if edition?
|
||||
[:& text-shape-edit {:shape shape}]
|
||||
[:& text/text-shape {:shape shape
|
||||
:selected? selected?}])]]))
|
||||
(if edition?
|
||||
[:& text-shape-edit {:shape shape}]
|
||||
[:& text/text-shape {:shape shape
|
||||
:selected? selected?}])]]]))
|
||||
|
||||
;; --- Text Editor Rendering
|
||||
|
||||
|
@ -158,17 +165,25 @@
|
|||
|
||||
fill-color (obj/get data "fill-color" fill)
|
||||
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-file (obj/get data "fill-color-ref-file")
|
||||
|
||||
[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)
|
||||
|
||||
base #js {:textDecoration text-decoration
|
||||
:color (str/format "rgba(%s, %s, %s, %s)" r g b a)
|
||||
:textTransform text-transform
|
||||
:lineHeight (or line-height "inherit")}]
|
||||
:lineHeight (or line-height "inherit")
|
||||
"--text-color" background}]
|
||||
|
||||
(when (and (string? letter-spacing)
|
||||
(pos? (alength letter-spacing)))
|
||||
|
@ -243,7 +258,9 @@
|
|||
childs (obj/get props "children")
|
||||
data (obj/get props "leaf")
|
||||
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]))
|
||||
|
||||
(defn- render-element
|
||||
|
@ -284,6 +301,14 @@
|
|||
children-count (->> node :children (map content-size) (reduce +))]
|
||||
(+ 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/wrap [mf/memo]}
|
||||
[{:keys [shape read-only?] :or {read-only? false} :as props}]
|
||||
|
@ -364,7 +389,8 @@
|
|||
(fn [val]
|
||||
(when (not read-only?)
|
||||
(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
|
||||
(st/emit! (dw/update-shape id {:content (assoc content :ts (js->clj (.now js/Date)))}))
|
||||
(reset! state val)
|
||||
|
@ -419,7 +445,8 @@
|
|||
:x x :y y
|
||||
:width (if (= :auto-width grow-type) 10000 width)
|
||||
: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
|
||||
:value @state
|
||||
:on-change on-change}
|
||||
|
|
|
@ -290,6 +290,8 @@
|
|||
:shape shape
|
||||
:attrs text-fill-attrs})
|
||||
|
||||
fill-values (d/update-in-when fill-values [:fill-color-gradient :type] keyword)
|
||||
|
||||
fill-values (cond-> fill-values
|
||||
;; Keep for backwards compatibility
|
||||
(:fill fill-values) (assoc :fill-color (:fill fill-values))
|
||||
|
|
Loading…
Add table
Reference in a new issue