Changes to text editor

This commit is contained in:
alonso.torres 2022-02-17 14:53:46 +01:00
parent d83459f674
commit 618d22d214
9 changed files with 115 additions and 149 deletions

View file

@ -1,62 +1,61 @@
foreignObject {
.text-editor,
.rich-text {
color: $color-black;
height: 100%;
white-space: pre-wrap;
font-family: sourcesanspro;
div {
line-height: inherit;
user-select: text;
}
.text-editor,
.rich-text {
color: $color-black;
height: 100%;
white-space: pre-wrap;
font-family: sourcesanspro;
span {
line-height: inherit;
}
div {
line-height: inherit;
user-select: text;
}
.text-editor {
.DraftEditor-root {
height: 100%;
display: flex;
flex-direction: column;
}
&.align-top {
.DraftEditor-root {
justify-content: flex-start;
}
}
&.align-center {
.DraftEditor-root {
justify-content: center;
}
}
&.align-bottom {
.DraftEditor-root {
justify-content: flex-end;
}
}
span {
line-height: inherit;
}
}
.rich-text .paragraphs {
.text-editor {
.DraftEditor-root {
height: 100%;
display: flex;
flex-direction: column;
}
&.align-top {
&.align-top {
.DraftEditor-root {
justify-content: flex-start;
}
}
&.align-center {
&.align-center {
.DraftEditor-root {
justify-content: center;
}
}
&.align-bottom {
&.align-bottom {
.DraftEditor-root {
justify-content: flex-end;
}
}
}
.rich-text .paragraphs {
height: 100%;
display: flex;
flex-direction: column;
&.align-top {
justify-content: flex-start;
}
&.align-center {
justify-content: center;
}
&.align-bottom {
justify-content: flex-end;
}
}

View file

@ -29,7 +29,6 @@
(def pointer-move (cursor-ref :pointer-move 0 0 10 42))
(def pointer-node (cursor-ref :pointer-node 0 0 10 32))
(def resize-alt (cursor-ref :resize-alt))
(def text (cursor-ref :text))
(def zoom (cursor-ref :zoom))
(def zoom-in (cursor-ref :zoom-in))
(def zoom-out (cursor-ref :zoom-out))
@ -40,6 +39,7 @@
(def resize-ns (cursor-fn :resize-h 90))
(def resize-nwse (cursor-fn :resize-h 135))
(def rotate (cursor-fn :rotate 90))
(def text (cursor-fn :text 0))
;;
(def resize-ew-2 (cursor-fn :resize-h-2 0))

View file

@ -80,34 +80,38 @@
"z")}))
attrs))
(defn add-fill [attrs shape render-id index]
(let [
fill-attrs (cond
(contains? shape :fill-image)
(let [fill-image-id (str "fill-image-" render-id)]
{:fill (str/format "url(#%s)" fill-image-id)})
(defn add-fill
([attrs shape render-id]
(add-fill attrs shape render-id 0))
(contains? shape :fill-color-gradient)
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id "_" index)]
{:fill (str/format "url(#%s)" fill-color-gradient-id)})
([attrs shape render-id index]
(let [fill-attrs
(cond
(contains? shape :fill-image)
(let [fill-image-id (str "fill-image-" render-id)]
{:fill (str/format "url(#%s)" fill-image-id)})
(contains? shape :fill-color)
{:fill (:fill-color shape)}
(contains? shape :fill-color-gradient)
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id "_" index)]
{:fill (str/format "url(#%s)" fill-color-gradient-id)})
;; If contains svg-attrs the origin is svg. If it's not svg origin
;; we setup the default fill as transparent (instead of black)
(and (not (contains? shape :svg-attrs))
(not (#{:svg-raw :group} (:type shape))))
{:fill "none"}
(contains? shape :fill-color)
{:fill (:fill-color shape)}
:else
{})
;; If contains svg-attrs the origin is svg. If it's not svg origin
;; we setup the default fill as transparent (instead of black)
(and (not (contains? shape :svg-attrs))
(not (#{:svg-raw :group} (:type shape))))
{:fill "none"}
fill-attrs (cond-> fill-attrs
(contains? shape :fill-opacity)
(assoc :fillOpacity (:fill-opacity shape)))]
:else
{})
(obj/merge! attrs (clj->js fill-attrs))))
fill-attrs (cond-> fill-attrs
(contains? shape :fill-opacity)
(assoc :fillOpacity (:fill-opacity shape)))]
(obj/merge! attrs (clj->js fill-attrs)))))
(defn add-stroke [attrs shape render-id]
(let [stroke-style (:stroke-style shape :none)

View file

@ -38,19 +38,8 @@
stroke-width (case (:stroke-alignment shape :center)
:center (/ (:stroke-width shape 0) 2)
:outer (:stroke-width shape 0)
0)
margin (gsh/shape-stroke-margin shape stroke-width)
bounding-box (-> (gsh/points->selrect (:points shape))
(update :x - (+ stroke-width margin))
(update :y - (+ stroke-width margin))
(update :width + (* 2 (+ stroke-width margin)))
(update :height + (* 2 (+ stroke-width margin))))]
[:mask {:id stroke-mask-id
:x (:x bounding-box)
:y (:y bounding-box)
:width (:width bounding-box)
:height (:height bounding-box)
:maskUnits "userSpaceOnUse"}
0)]
[:mask {:id stroke-mask-id}
[:use {:xlinkHref (str "#" shape-id)
:style #js {:fill "none" :stroke "white" :strokeWidth (* stroke-width 2)}}]

View file

@ -19,11 +19,12 @@
(let [valign (:vertical-align node "top")
base #js {:height "100%"
:width "100%"
:fontFamily "sourcesanspro"}]
:fontFamily "sourcesanspro"
:display "flex"}]
(cond-> base
(= valign "top") (obj/set! "justifyContent" "flex-start")
(= valign "center") (obj/set! "justifyContent" "center")
(= valign "bottom") (obj/set! "justifyContent" "flex-end"))))
(= valign "top") (obj/set! "alignItems" "flex-start")
(= valign "center") (obj/set! "alignItems" "center")
(= valign "bottom") (obj/set! "alignItems" "flex-end"))))
(defn generate-paragraph-set-styles
[{:keys [grow-type] :as shape}]
@ -39,7 +40,6 @@
#js {:display "inline-flex"
:flexDirection "column"
:justifyContent "inherit"
:minHeight (when-not (or auto-width? auto-height?) "100%")
:minWidth (when-not auto-width? "100%")
:marginRight "1px"
:verticalAlign "top"}))

View file

@ -24,9 +24,8 @@
(let [render-id (mf/use-ctx muc/render-ctx)
{:keys [id x y width height position-data] :as shape} (obj/get props "shape")
clip-id (str "clip-text" id "_" render-id)
group-props (-> #js {:transform (gsh/transform-matrix shape)
:clipPath (str "url(#" clip-id ")")}
transform (str (gsh/transform-matrix shape))
group-props (-> #js {:transform transform}
(attrs/add-style-attrs shape render-id))
get-gradient-id
(fn [index]
@ -43,9 +42,6 @@
[:& shape-custom-stroke {:shape shape}
[:> :g group-props
[:defs
[:clipPath {:id clip-id}
[:rect.text-clip {:x x :y y :width width :height height}]]]
(for [[index data] (d/enumerate position-data)]
(let [props (-> #js {:x (:x data)
:y (:y data)

View file

@ -131,7 +131,6 @@
handle-change-foreign-object
(fn [node]
(when (some? node)
(prn "change!")
(let [position-data (utp/calc-position-data node)
parent (dom/get-parent node)
parent-transform (dom/get-attribute parent "transform")
@ -174,7 +173,7 @@
;; and updates the selrect accordingly
[:*
[:g.text-shape {:ref on-change-node
:opacity (when (or edition? (some? (:position-data shape))) 0.2)
:opacity (when (or edition? (some? (:position-data shape))) 0)
:pointer-events "none"}
;; The `:key` prop here is mandatory because the

View file

@ -7,6 +7,7 @@
(ns app.main.ui.workspace.shapes.text.editor
(:require
["draft-js" :as draft]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh]
[app.common.text :as txt]
[app.main.data.workspace :as dw]
@ -211,7 +212,7 @@
[:div.text-editor
{:ref self-ref
:style {:cursor cur/text
:style {:cursor (cur/text (:rotation shape))
:width (:width shape)
:height (:height shape)}
:on-click on-click
@ -231,61 +232,34 @@
:ref on-editor
:editor-state state}]]))
(mf/defc text-shape-edit
{::mf/wrap [mf/memo]
::mf/wrap-props false
::mf/forward-ref true}
[props _]
(let [{:keys [id x y width height grow-type] :as shape} (obj/get props "shape")
transform (str (gsh/transform-matrix shape))
(defn translate-point-from-viewport
"Translate a point in the viewport into client coordinates"
[pt viewport zoom]
(let [vbox (.. ^js viewport -viewBox -baseVal)
box (gpt/point (.-x vbox) (.-y vbox))
zoom (gpt/point zoom)]
(-> (gpt/subtract pt box)
(gpt/multiply zoom))))
clip-id (str "clip-" id)
(mf/defc text-editor-viewport
{::mf/wrap-props false}
[props]
(let [shape (obj/get props "shape")
viewport-ref (obj/get props "viewport-ref")
zoom (obj/get props "zoom")
;; local-position-data (mf/use-state nil)
position
(-> (gpt/point (-> shape :selrect :x)
(-> shape :selrect :y))
(translate-point-from-viewport (mf/ref-val viewport-ref) zoom))]
;;handle-change-foreign-object
;;(mf/use-callback
;; (fn [node]
;; (when node
;; (let [position-data (utp/calc-position-data node)]
;; (reset! local-position-data position-data)))))
;;
;;[shape-ref on-change-node] (use-mutable-observer handle-change-foreign-object)
[:div {:style {:position "absolute"
:left (str (:x position) "px")
:top (str (:y position) "px")
:pointer-events "all"
:transform (str (gsh/transform-matrix shape nil (gpt/point 0 0)))
:transform-origin "center center"}}
;;handle-interaction
;;(mf/use-callback
;; (fn []
;; (handle-change-foreign-object (mf/ref-val shape-ref))))
]
#_(mf/use-effect
(mf/use-callback handle-interaction)
(fn []
(let [keys [(events/listen js/document EventType.KEYUP handle-interaction)
(events/listen js/document EventType.KEYDOWN handle-interaction)
(events/listen js/document EventType.MOUSEDOWN handle-interaction)]]
#(doseq [key keys]
(events/unlistenByKey key)))))
[:*
#_[:> shape-container {:shape shape
:pointer-events "none"}
[:& svg/text-shape {:shape (cond-> shape
(some? @local-position-data)
(assoc :position-data @local-position-data))}]]
[:g.text-editor {:clip-path (str "url(#" clip-id ")")
;; :ref on-change-node
:key (str "editor-" id)}
[:defs
;; This clippath will cut the huge foreign object we use to calculate the automatic resize
[:clipPath {:id clip-id}
[:rect {:x x :y y
:width (+ width 8) :height (+ height 8)
:transform transform}]]]
[:foreignObject {:transform transform
:x x :y y
:width (if (#{:auto-width} grow-type) 100000 width)
:height (if (#{:auto-height :auto-width} grow-type) 100000 height)}
[:& text-shape-edit-html {:shape shape :key (str id)}]]]]))
[:div {:style {:transform (str "scale(" zoom ")")
:transform-origin "top left"}}
[:& text-shape-edit-html {:shape shape :key (str (:id shape))}]]]))

View file

@ -110,6 +110,8 @@
;; Only when we have all the selected shapes in one frame
selected-frame (when (= (count selected-frames) 1) (get base-objects (first selected-frames)))
editing-shape (when edition (get base-objects edition))
create-comment? (= :comments drawing-tool)
drawing-path? (or (and edition (= :draw (get-in edit-path [edition :edit-mode])))
(and (some? drawing-obj) (= :path (:type drawing-obj))))
@ -159,6 +161,8 @@
show-artboard-names? (contains? layout :display-artboard-names)
show-rules? (and (contains? layout :rules) (not (contains? layout :hide-ui)))
show-text-editor? (and editing-shape (= :text (:type editing-shape)))
disabled-guides? (or drawing-tool transform)]
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?)
@ -176,6 +180,10 @@
[:& wtr/frame-renderer {:objects base-objects
:background background}]
(when show-text-editor?
[:& editor/text-editor-viewport {:shape editing-shape
:viewport-ref viewport-ref
:zoom zoom}])
(when show-comments?
[:& comments/comments-layer {:vbox vbox
:vport vport
@ -268,9 +276,6 @@
:hover-shape @hover
:zoom zoom}])
(when text-editing?
[:& editor/text-shape-edit {:shape (get base-objects edition)}])
[:& widgets/frame-titles
{:objects objects-modified
:selected selected