mirror of
https://github.com/penpot/penpot.git
synced 2025-01-24 07:29:08 -05:00
🔧 Minor refactor on text shapes.
This commit is contained in:
parent
2b81832b67
commit
54809d05e2
1 changed files with 148 additions and 115 deletions
|
@ -5,22 +5,22 @@
|
||||||
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
|
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
|
||||||
|
|
||||||
(ns uxbox.main.ui.shapes.text
|
(ns uxbox.main.ui.shapes.text
|
||||||
(:require [cuerdas.core :as str]
|
(:require
|
||||||
[lentes.core :as l]
|
[cuerdas.core :as str]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[potok.core :as ptk]
|
[lentes.core :as l]
|
||||||
[uxbox.main.store :as st]
|
[rumext.core :as mx]
|
||||||
[uxbox.main.geom :as geom]
|
[rumext.alpha :as mf]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.data.shapes :as uds]
|
||||||
[uxbox.main.data.shapes :as uds]
|
[uxbox.main.geom :as geom]
|
||||||
[uxbox.main.ui.shapes.common :as common]
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.util.color :as color]
|
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||||
[uxbox.util.data :refer [classnames normalize-props]]
|
[uxbox.main.ui.shapes.common :as common]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.color :as color]
|
||||||
[uxbox.util.geom.matrix :as gmt]
|
[uxbox.util.data :refer [classnames normalize-props]]
|
||||||
[rumext.core :as mx :include-macros true])
|
[uxbox.util.dom :as dom]
|
||||||
(:import goog.events.EventType))
|
[uxbox.util.geom.matrix :as gmt]))
|
||||||
|
|
||||||
;; --- Events
|
;; --- Events
|
||||||
|
|
||||||
|
@ -39,29 +39,29 @@
|
||||||
(declare text-shape-wrapper)
|
(declare text-shape-wrapper)
|
||||||
(declare text-shape-edit)
|
(declare text-shape-edit)
|
||||||
|
|
||||||
(mx/defcs text-component
|
(mf/def text-component
|
||||||
{:mixins [mx/static mx/reactive]}
|
:mixins [mf/memo mx/reactive]
|
||||||
[own {:keys [id x1 y1 content group] :as shape}]
|
:render
|
||||||
(let [modifiers (mx/react (refs/selected-modifiers id))
|
(fn [own {:keys [id x1 y1 content group] :as shape}]
|
||||||
selected (mx/react refs/selected-shapes)
|
(let [modifiers (mx/react (refs/selected-modifiers id))
|
||||||
edition? (= (mx/react refs/selected-edition) id)
|
selected (mx/react refs/selected-shapes)
|
||||||
selected? (and (contains? selected id)
|
edition? (= (mx/react refs/selected-edition) id)
|
||||||
(= (count selected) 1))
|
selected? (and (contains? selected id)
|
||||||
shape (assoc shape :modifiers modifiers)]
|
(= (count selected) 1))
|
||||||
(letfn [(on-mouse-down [event]
|
shape (assoc shape :modifiers modifiers)]
|
||||||
(handle-mouse-down event shape selected))
|
(letfn [(on-mouse-down [event]
|
||||||
(on-double-click [event]
|
(handle-mouse-down event shape selected))
|
||||||
;; TODO: handle grouping event propagation
|
(on-double-click [event]
|
||||||
;; TODO: handle actions locking properly
|
;; TODO: handle grouping event propagation
|
||||||
(dom/stop-propagation event)
|
;; TODO: handle actions locking properly
|
||||||
(st/emit! (uds/start-edition-mode id)))]
|
(dom/stop-propagation event)
|
||||||
[:g.shape {:class (when selected? "selected")
|
(st/emit! (uds/start-edition-mode id)))]
|
||||||
:ref "main"
|
[:g.shape {:class (when selected? "selected")
|
||||||
:on-double-click on-double-click
|
:on-double-click on-double-click
|
||||||
:on-mouse-down on-mouse-down}
|
:on-mouse-down on-mouse-down}
|
||||||
(if edition?
|
(if edition?
|
||||||
(text-shape-edit shape)
|
(text-shape-edit shape)
|
||||||
(text-shape-wrapper shape))])))
|
(text-shape-wrapper shape))]))))
|
||||||
|
|
||||||
;; --- Text Styles Helpers
|
;; --- Text Styles Helpers
|
||||||
|
|
||||||
|
@ -104,97 +104,130 @@
|
||||||
|
|
||||||
;; --- Text Shape Edit
|
;; --- Text Shape Edit
|
||||||
|
|
||||||
(defn- text-shape-edit-did-mount
|
(mf/def text-shape-edit
|
||||||
[own]
|
:mixins [mf/memo]
|
||||||
(let [[shape] (::mx/props own)
|
|
||||||
dom (mx/ref-node own "container")]
|
|
||||||
(set! (.-textContent dom) (:content shape ""))
|
|
||||||
(.focus dom)
|
|
||||||
own))
|
|
||||||
|
|
||||||
(mx/defc text-shape-edit
|
:init
|
||||||
{:did-mount text-shape-edit-did-mount
|
(fn [own props]
|
||||||
:mixins [mx/static]}
|
(assoc own ::container (mf/create-ref)))
|
||||||
[{:keys [id x1 y1 content] :as shape}]
|
|
||||||
(let [{:keys [width height]} (geom/size shape)
|
:did-mount
|
||||||
style (make-style shape)
|
(fn [own]
|
||||||
props {:x x1 :y y1 :width width :height height}]
|
(let [shape (::mf/props own)
|
||||||
(letfn [(on-input [ev]
|
dom (mx/ref-node (::container own))]
|
||||||
(let [content (dom/event->inner-text ev)]
|
(set! (.-textContent dom) (:content shape ""))
|
||||||
(st/emit! (uds/update-text id content))))]
|
(.focus dom)
|
||||||
[:foreignObject props
|
own))
|
||||||
|
|
||||||
|
:render
|
||||||
|
(fn [own {:keys [id x1 y1 content] :as shape}]
|
||||||
|
(let [{:keys [width height]} (geom/size shape)
|
||||||
|
style (make-style shape)
|
||||||
|
on-input (fn [ev]
|
||||||
|
(let [content (dom/event->inner-text ev)]
|
||||||
|
(st/emit! (uds/update-text id content))))]
|
||||||
|
[:foreignObject {:x x1 :y y1 :width width :height height}
|
||||||
[:div {:style (normalize-props style)
|
[:div {:style (normalize-props style)
|
||||||
:ref "container"
|
:ref (::container own)
|
||||||
:on-input on-input
|
:on-input on-input
|
||||||
:contentEditable true}]])))
|
:contentEditable true}]])))
|
||||||
|
|
||||||
;; --- Text Shape Wrapper
|
;; --- Text Shape Wrapper
|
||||||
|
|
||||||
;; NOTE: this is a hack for the browser rendering.
|
(mf/def text-shape-wrapper
|
||||||
;;
|
:mixins [mf/memo]
|
||||||
;; Without forcing rerender, when the shape is displaced
|
:key-fn pr-str
|
||||||
;; 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.
|
|
||||||
|
|
||||||
(defn text-shape-wrapper-did-mount
|
:init
|
||||||
[own]
|
(fn [own props]
|
||||||
(let [[shape] (::mx/props own)
|
(assoc own ::fobject (mf/create-ref)))
|
||||||
dom (mx/ref-node own "fobject")
|
|
||||||
html (dom/render-to-html (text-shape-html shape))]
|
;; NOTE: this is a hack for the browser rendering.
|
||||||
(set! (.-innerHTML dom) html))
|
;;
|
||||||
|
;; 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 (dom/render-to-html (text-shape-html shape))]
|
||||||
|
(set! (.-innerHTML dom) html))
|
||||||
own)
|
own)
|
||||||
|
|
||||||
(mx/defc text-shape-wrapper
|
:render
|
||||||
{:did-mount text-shape-wrapper-did-mount
|
(fn [own {:keys [id modifiers] :as shape}]
|
||||||
:key-fn #(pr-str %1)}
|
(let [{:keys [displacement resize]} modifiers
|
||||||
[{:keys [id modifiers] :as shape}]
|
xfmt (cond-> (gmt/matrix)
|
||||||
(let [{:keys [displacement resize]} modifiers
|
displacement (gmt/multiply displacement)
|
||||||
xfmt (cond-> (gmt/matrix)
|
resize (gmt/multiply resize))
|
||||||
displacement (gmt/multiply displacement)
|
|
||||||
resize (gmt/multiply resize))
|
|
||||||
|
|
||||||
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
|
{:keys [x1 y1 width height] :as shape} (-> (geom/transform shape xfmt)
|
||||||
(geom/size))
|
(geom/size))
|
||||||
moving? (boolean displacement)]
|
moving? (boolean displacement)]
|
||||||
[:foreignObject {:x x1
|
[:foreignObject {:x x1
|
||||||
:y y1
|
:y y1
|
||||||
:class (classnames :move-cursor moving?)
|
:class (classnames :move-cursor moving?)
|
||||||
:id (str id)
|
:id (str id)
|
||||||
:ref "fobject"
|
:ref (::fobject own)
|
||||||
:width width
|
:width width
|
||||||
:height height}]))
|
:height height}])))
|
||||||
|
|
||||||
;; --- Text Shape Html
|
;; --- Text Shape Html
|
||||||
|
|
||||||
(mx/defc text-shape-html
|
(mf/def text-shape-html
|
||||||
[{:keys [content] :as shape}]
|
:mixins [mf/memo]
|
||||||
(let [style (make-style shape)]
|
:render
|
||||||
[:div {:style style} content]))
|
(fn [own {:keys [content] :as shape}]
|
||||||
|
(let [style (make-style shape)]
|
||||||
|
[:div {:style style} content])))
|
||||||
|
|
||||||
;; --- Text Shape Html
|
;; --- Text Shape Html
|
||||||
|
|
||||||
(mx/defc text-shape
|
(mf/def text-shape
|
||||||
{:mixins [mx/static]
|
:mixins [mf/memo]
|
||||||
:did-mount text-shape-wrapper-did-mount
|
:key-fn pr-str
|
||||||
:key-fn #(pr-str %1)}
|
|
||||||
[{: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)
|
:init
|
||||||
(geom/size))
|
(fn [own props]
|
||||||
moving? (boolean displacement)
|
(assoc own ::fobject (mf/create-ref)))
|
||||||
style (make-style shape)]
|
|
||||||
[:foreignObject {:x x1
|
;; NOTE: this is a hack for the browser rendering.
|
||||||
:y y1
|
;;
|
||||||
:class (classnames :move-cursor moving?)
|
;; Without forcing rerender, when the shape is displaced
|
||||||
:id (str id)
|
;; and only x and y attrs are updated in dom, the whole content
|
||||||
:ref "fobject"
|
;; of the foreignObject becomes sometimes partially or
|
||||||
:width width
|
;; completelly invisible. The complete dom rerender fixes that
|
||||||
:height height}
|
;; problem.
|
||||||
[:div {:style style}
|
|
||||||
[:p content]]]))
|
:did-mount
|
||||||
|
(fn [own]
|
||||||
|
(let [shape (::mf/props own)
|
||||||
|
dom (mf/ref-node (::fobject own))
|
||||||
|
html (dom/render-to-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]]])))
|
||||||
|
|
Loading…
Add table
Reference in a new issue