0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-23 23:18:48 -05:00

♻️ Refactor text shape.

This commit is contained in:
Andrey Antukh 2020-01-08 15:01:39 +01:00
parent 020625392a
commit b0da06bad4
4 changed files with 56 additions and 168 deletions

View file

@ -18,10 +18,6 @@
[uxbox.main.ui.shapes.rect :as rect]
[uxbox.main.ui.shapes.text :as text]))
(defn- render-html
[component]
(.renderToStaticMarkup js/ReactDOMServer component))
(mf/defc background
[]
[:rect
@ -51,15 +47,12 @@
:circle [:& circle/circle-shape {:shape shape}])))
(mf/defc page-svg
[{:keys [data width height] :as props}]
[{:keys [data] :as props}]
(let [shapes-by-id (:shapes-by-id data)
shapes (map #(get shapes-by-id %) (:shapes data []))
canvas (map #(get shapes-by-id %) (:canvas data []))
dim (calculate-dimensions data)]
[:svg {
;; :width width
;; :height height
:view-box (str "0 0 " (:width dim) " " (:height dim))
[:svg {:view-box (str "0 0 " (:width dim) " " (:height dim))
:version "1.1"
:xmlnsXlink "http://www.w3.org/1999/xlink"
:xmlns "http://www.w3.org/2000/svg"}
@ -70,6 +63,10 @@
(for [item shapes]
[:& shape-wrapper {:shape item :key (:id item)}])]]))
;; (defn- render-html
;; [component]
;; (.renderToStaticMarkup js/ReactDOMServer component))
;; (defn render
;; [{:keys [data] :as page}]
;; (try

View file

@ -67,27 +67,12 @@
;; --- Grid Item Thumbnail
;; (mf/defc grid-item-thumbnail
;; [{:keys [file] :as props}]
;; (let [url (mf/use-memo
;; {:fn #(let [content (exports/render file)
;; blob (js/Blob. #js [content] #js {:type "image/svg+xml"})]
;; (js/URL.createObjectURL blob))
;; :deps (mf/deps (:id file))})]
;; (mf/use-effect
;; {:fn (fn []
;; #(js/URL.revokeObjectURL url))
;; :deps (mf/deps (:id file))})
;; [:div.grid-item-th
;; [:img.img-th {:src url}]]))
(mf/defc grid-item-thumbnail
[{:keys [file] :as props}]
[:div.grid-item-th
[:& exports/page-svg {:data (:data file)
:width "290"
:height "150"}]])
:width "290"
:height "150"}]])
;; --- Grid Item

View file

@ -60,17 +60,6 @@
:dotted "5,5"
:dashed "10,10"))
;; (defn- rename-attr
;; [[key value :as pair]]
;; (case key
;; :stroke-color [:stroke value]
;; :fill-color [:fill value]
;; pair))
;; (defn- rename-attrs
;; [attrs]
;; (into {} (map rename-attr) attrs))
(defn- transform-stroke-attrs
[{:keys [stroke-style] :or {stroke-style :none} :as attrs}]
(case stroke-style

View file

@ -18,18 +18,8 @@
[uxbox.main.ui.shapes.attrs :as attrs]
[uxbox.main.ui.shapes.common :as common]
[uxbox.util.color :as color]
[uxbox.util.data :refer [classnames normalize-props]]
[uxbox.util.dom :as dom]
[uxbox.util.geom.matrix :as gmt]
[cljsjs.react.dom.server]))
(defn- render-html
[component]
(.renderToStaticMarkup js/ReactDOMServer component))
;; TODO: this code need a good refactor
[uxbox.util.geom.matrix :as gmt]))
;; --- Events
@ -44,8 +34,8 @@
;; --- Text Wrapper
(declare text-shape-html)
(declare text-shape-wrapper)
(declare text-shape-edit)
(declare text-shape)
(mf/defc text-wrapper
[{:keys [shape] :as props}]
@ -65,7 +55,7 @@
:on-mouse-down on-mouse-down}
(if edition?
[:& text-shape-edit {:shape shape}]
[:& text-shape-wrapper {:shape shape}])])))
[:& text-shape {:shape shape}])])))
;; --- Text Styles Helpers
@ -79,7 +69,9 @@
text-align
line-height
letter-spacing
user-select]
user-select
width
height]
:or {fill-color "#000000"
fill-opacity 1
font-family "sourcesanspro"
@ -94,17 +86,23 @@
(let [color (-> fill-color
(color/hex->rgba fill-opacity)
(color/rgb->str))]
(merge
{:fontSize (str font-size "px")
:color color
:whiteSpace "pre-wrap"
:textAlign text-align
:fontFamily font-family
:fontWeight font-weight
:fontStyle font-style}
(when user-select {:userSelect "auto"})
(when line-height {:lineHeight line-height})
(when letter-spacing {:letterSpacing letter-spacing}))))
(rumext.util/map->obj
(merge
{:fontSize (str font-size "px")
:color color
:width width
:height height
:whiteSpace "pre-wrap"
:textAlign text-align
:fontFamily font-family
:fontWeight font-weight
:fontStyle font-style
:margin "0px"
:padding "0px"
:border "0px"}
(when user-select {:userSelect "auto"})
(when line-height {:lineHeight line-height})
(when letter-spacing {:letterSpacing letter-spacing})))))
;; --- Text Shape Edit
@ -123,115 +121,34 @@
(.focus dom)
own))
:will-unmount
(fn [own]
(let [dom (mf/ref-val (::container own))
shape (get-in own [::mf/props :shape])
content (dom/get-value dom)]
(st/emit! (udw/update-shape (:id shape) {:content content}))
own))
:render
(fn [own {:keys [shape] :as props}]
(let [{:keys [id x1 y1 content width height]} (geom/size shape)
style (make-style shape)
on-input (fn [ev]
(let [content (dom/event->inner-text ev)]
#_(st/emit! (udw/update-shape-attrs id {:content content}))))]
[:foreignObject {:x x1 :y y1 :width width :height height}
[:div {:style (normalize-props style)
:ref (::container own)
:on-input on-input
:contentEditable true}]])))
(let [{:keys [id x y content width height]} shape]
[:foreignObject {:x x :y y :width width :height height}
[:textarea {:style (make-style shape)
:ref (::container own)}]])))
;; --- Text Shape Wrapper
(mf/def text-shape-wrapper
:mixins [mf/memo]
(mf/defc text-shape
[{:keys [shape] :as props}]
(let [{:keys [id rotation modifier-mtx]} shape
shape (cond
(gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx)
:else shape)
:init
(fn [own props]
(assoc own ::fobject (mf/create-ref)))
;; NOTE: this is a hack for the browser rendering.
;;
;; Without forcing rerender, when the shape is displaced
;; and only x and y attrs are updated in dom, the whole content
;; of the foreignObject becomes sometimes partially or
;; completelly invisible. The complete dom rerender fixes that
;; problem.
:did-mount
(fn [own]
(let [shape (get-in own [::mf/props :shape])
dom (mf/ref-node (::fobject own))
html (render-html (text-shape-html shape))]
(set! (.-innerHTML dom) html))
own)
:render
(fn [own {:keys [shape] :as props}]
(let [{:keys [id modifiers]} shape
{:keys [displacement resize]} modifiers
xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement)
resize (gmt/multiply resize))
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
(geom/size))
moving? (boolean displacement)]
[:foreignObject {:x x1
:y y1
:class (classnames :move-cursor moving?)
:id (str id)
:ref (::fobject own)
:width width
:height height}])))
;; --- Text Shape Html
(mf/def text-shape-html
:mixins [mf/memo]
:render
(fn [own {:keys [content] :as shape}]
(let [style (make-style shape)]
[:div {:style style} content])))
;; --- Text Shape Html
(mf/def text-shape
:mixins [mf/memo]
:key-fn pr-str
:init
(fn [own props]
(assoc own ::fobject (mf/create-ref)))
;; NOTE: this is a hack for the browser rendering.
;;
;; Without forcing rerender, when the shape is displaced
;; and only x and y attrs are updated in dom, the whole content
;; of the foreignObject becomes sometimes partially or
;; completelly invisible. The complete dom rerender fixes that
;; problem.
:did-mount
(fn [own]
(let [shape (::mf/props own)
dom (mf/ref-node (::fobject own))
html (render-html (text-shape-html shape))]
(set! (.-innerHTML dom) html))
own)
:render
(fn [own {:keys [id content modifiers] :as shape}]
(let [{:keys [displacement resize]} modifiers
xfmt (cond-> (gmt/matrix)
displacement (gmt/multiply displacement)
resize (gmt/multiply resize))
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
(geom/size))
moving? (boolean displacement)
style (make-style shape)]
[:foreignObject {:x x1
:y y1
:class (classnames :move-cursor moving?)
:id (str id)
:ref (::fobject own)
:width width
:height height}
[:div {:style style}
[:p content]]])))
{:keys [x y width height content]} shape]
[:foreignObject {:x x
:y y
:id (str id)
:width width
:height height}
[:div {:style (make-style shape)} content]]))