mirror of
https://github.com/penpot/penpot.git
synced 2025-07-26 01:57:23 +02:00
✨ Improvements over text shape
This commit is contained in:
parent
62a2713c03
commit
df70cd5c50
6 changed files with 80 additions and 37 deletions
|
@ -1456,7 +1456,8 @@
|
||||||
"a" #(st/emit! (select-for-drawing :frame))
|
"a" #(st/emit! (select-for-drawing :frame))
|
||||||
"b" #(st/emit! (select-for-drawing :rect))
|
"b" #(st/emit! (select-for-drawing :rect))
|
||||||
"e" #(st/emit! (select-for-drawing :circle))
|
"e" #(st/emit! (select-for-drawing :circle))
|
||||||
"t" #(st/emit! (select-for-drawing :text))
|
"t" #(st/emit! dwtxt/start-edit-if-selected
|
||||||
|
(select-for-drawing :text))
|
||||||
"ctrl+c" #(st/emit! copy-selected)
|
"ctrl+c" #(st/emit! copy-selected)
|
||||||
"ctrl+v" #(st/emit! paste)
|
"ctrl+v" #(st/emit! paste)
|
||||||
"escape" #(st/emit! :interrupt deselect-all)
|
"escape" #(st/emit! :interrupt deselect-all)
|
||||||
|
|
|
@ -186,3 +186,23 @@
|
||||||
(defn update-root-attrs
|
(defn update-root-attrs
|
||||||
[options]
|
[options]
|
||||||
(update-attrs (assoc options :pred is-root-node? :split false)))
|
(update-attrs (assoc options :pred is-root-node? :split false)))
|
||||||
|
|
||||||
|
(defn update-overflow-text [id value]
|
||||||
|
(ptk/reify ::update-overflow-text
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [page-id (:current-page-id state)]
|
||||||
|
(update-in state [:workspace-data :pages-index page-id :objects id] assoc :overflow-text value)))))
|
||||||
|
|
||||||
|
|
||||||
|
(def start-edit-if-selected
|
||||||
|
(ptk/reify ::start-edit-if-selected
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [page-id (:current-page-id state)
|
||||||
|
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||||
|
selected (->> state :workspace-local :selected (map #(get objects %)))]
|
||||||
|
(cond-> state
|
||||||
|
(and (= 1 (count selected))
|
||||||
|
(= (-> selected first :type) :text))
|
||||||
|
(assoc-in [:workspace-local :edition] (-> selected first :id)))))))
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
[app.common.pages-helpers :as cph]
|
[app.common.pages-helpers :as cph]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
|
[app.main.data.workspace.texts :as dwt]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.snap :as snap]
|
[app.main.snap :as snap]
|
||||||
|
@ -139,8 +140,12 @@
|
||||||
layout (:workspace-layout state)
|
layout (:workspace-layout state)
|
||||||
page-id (:current-page-id state)
|
page-id (:current-page-id state)
|
||||||
objects (dwc/lookup-page-objects state page-id)
|
objects (dwc/lookup-page-objects state page-id)
|
||||||
resizing-shapes (map #(get objects %) ids)]
|
resizing-shapes (map #(get objects %) ids)
|
||||||
|
text-shapes-ids (->> resizing-shapes
|
||||||
|
(filter #(= :text (:type %)))
|
||||||
|
(map :id))]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
|
(rx/of (dwc/update-shapes text-shapes-ids #(assoc % :grow-type :fixed)))
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
(rx/with-latest vector ms/mouse-position-shift)
|
(rx/with-latest vector ms/mouse-position-shift)
|
||||||
(rx/map normalize-proportion-lock)
|
(rx/map normalize-proportion-lock)
|
||||||
|
|
|
@ -126,7 +126,7 @@
|
||||||
:on-mouse-down on-rotate}]))
|
:on-mouse-down on-rotate}]))
|
||||||
|
|
||||||
(mf/defc resize-point-handler
|
(mf/defc resize-point-handler
|
||||||
[{:keys [cx cy zoom position on-resize transform rotation color]}]
|
[{:keys [cx cy zoom position on-resize transform rotation color overflow-text]}]
|
||||||
(let [{cx' :x cy' :y} (gpt/transform (gpt/point cx cy) transform)
|
(let [{cx' :x cy' :y} (gpt/transform (gpt/point cx cy) transform)
|
||||||
rot-square (case position
|
rot-square (case position
|
||||||
:top-left 0
|
:top-left 0
|
||||||
|
@ -140,7 +140,7 @@
|
||||||
:vectorEffect "non-scaling-stroke"
|
:vectorEffect "non-scaling-stroke"
|
||||||
}
|
}
|
||||||
:fill "#FFFFFF"
|
:fill "#FFFFFF"
|
||||||
:stroke color
|
:stroke (if (and (= position :bottom-right) overflow-text) "red" color)
|
||||||
:cx cx'
|
:cx cx'
|
||||||
:cy cy'}]
|
:cy cy'}]
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@
|
||||||
(mf/defc controls
|
(mf/defc controls
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [shape (obj/get props "shape")
|
(let [{:keys [overflow-text] :as shape} (obj/get props "shape")
|
||||||
zoom (obj/get props "zoom")
|
zoom (obj/get props "zoom")
|
||||||
color (obj/get props "color")
|
color (obj/get props "color")
|
||||||
on-resize (obj/get props "on-resize")
|
on-resize (obj/get props "on-resize")
|
||||||
|
@ -202,7 +202,8 @@
|
||||||
:on-resize (partial on-resize position)
|
:on-resize (partial on-resize position)
|
||||||
:transform transform
|
:transform transform
|
||||||
:rotation (:rotation shape)
|
:rotation (:rotation shape)
|
||||||
:color color}
|
:color color
|
||||||
|
:overflow-text overflow-text}
|
||||||
props (map->obj (merge common-props props))]
|
props (map->obj (merge common-props props))]
|
||||||
(case type
|
(case type
|
||||||
:rotation (when (not= :frame (:type shape)) [:> rotation-handler props])
|
:rotation (when (not= :frame (:type shape)) [:> rotation-handler props])
|
||||||
|
|
|
@ -61,8 +61,6 @@
|
||||||
selected? (and (contains? selected id)
|
selected? (and (contains? selected id)
|
||||||
(= (count selected) 1))
|
(= (count selected) 1))
|
||||||
|
|
||||||
calculate-size (mf/use-state false)
|
|
||||||
|
|
||||||
on-mouse-down #(handle-mouse-down % shape)
|
on-mouse-down #(handle-mouse-down % shape)
|
||||||
on-context-menu #(common/on-context-menu % shape)
|
on-context-menu #(common/on-context-menu % shape)
|
||||||
|
|
||||||
|
@ -73,18 +71,13 @@
|
||||||
(when selected?
|
(when selected?
|
||||||
(st/emit! (dw/start-edition-mode (:id shape)))))]
|
(st/emit! (dw/start-edition-mode (:id shape)))))]
|
||||||
|
|
||||||
(mf/use-effect
|
|
||||||
(mf/deps grow-type content width height)
|
|
||||||
(fn []
|
|
||||||
(reset! calculate-size true)
|
|
||||||
(timers/schedule 200 (fn [] (reset! calculate-size false)))))
|
|
||||||
|
|
||||||
[: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}
|
||||||
[:*
|
[:*
|
||||||
(when (and (not edition?) @calculate-size)
|
(when (not edition?)
|
||||||
[:g {:opacity 0}
|
[:g {:opacity 0
|
||||||
|
:style {:pointer-events "none"}}
|
||||||
;; We only render the component for its side-effect
|
;; We only render the component for its side-effect
|
||||||
[:& text-shape-edit {:shape shape
|
[:& text-shape-edit {:shape shape
|
||||||
:read-only? true}]])
|
:read-only? true}]])
|
||||||
|
@ -125,7 +118,7 @@
|
||||||
lh (obj/set! "lineHeight" lh))))
|
lh (obj/set! "lineHeight" lh))))
|
||||||
|
|
||||||
(defn- generate-text-styles
|
(defn- generate-text-styles
|
||||||
[data]
|
[data on-load-font]
|
||||||
(let [letter-spacing (obj/get data "letter-spacing")
|
(let [letter-spacing (obj/get data "letter-spacing")
|
||||||
text-decoration (obj/get data "text-decoration")
|
text-decoration (obj/get data "text-decoration")
|
||||||
text-transform (obj/get data "text-transform")
|
text-transform (obj/get data "text-transform")
|
||||||
|
@ -157,7 +150,7 @@
|
||||||
(when (and (string? font-id)
|
(when (and (string? font-id)
|
||||||
(pos? (alength font-id)))
|
(pos? (alength font-id)))
|
||||||
(let [font (get fontsdb font-id)]
|
(let [font (get fontsdb font-id)]
|
||||||
(fonts/ensure-loaded! font-id)
|
(fonts/ensure-loaded! font-id on-load-font)
|
||||||
(let [font-family (or (:family font)
|
(let [font-family (or (:family font)
|
||||||
(obj/get data "fontFamily"))
|
(obj/get data "fontFamily"))
|
||||||
font-variant (d/seek #(= font-variant-id (:id %))
|
font-variant (d/seek #(= font-variant-id (:id %))
|
||||||
|
@ -219,7 +212,8 @@
|
||||||
(let [attrs (obj/get props "attributes")
|
(let [attrs (obj/get props "attributes")
|
||||||
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)
|
on-load-font (obj/get props "on-load-font")
|
||||||
|
style (generate-text-styles data on-load-font)
|
||||||
attrs (obj/set! attrs "style" style)]
|
attrs (obj/set! attrs "style" style)]
|
||||||
[:> :span attrs childs]))
|
[:> :span attrs childs]))
|
||||||
|
|
||||||
|
@ -235,9 +229,10 @@
|
||||||
nil))))
|
nil))))
|
||||||
|
|
||||||
(defn- render-text
|
(defn- render-text
|
||||||
[props]
|
[on-load-font]
|
||||||
(mf/html
|
(fn [props]
|
||||||
[:> editor-text-node props]))
|
(mf/html
|
||||||
|
[:> editor-text-node (obj/merge! props #js {:on-load-font on-load-font})])))
|
||||||
|
|
||||||
;; --- Text Shape Edit
|
;; --- Text Shape Edit
|
||||||
|
|
||||||
|
@ -271,7 +266,7 @@
|
||||||
(when (not read-only?)
|
(when (not read-only?)
|
||||||
(st/emit! dw/clear-edition-mode)))
|
(st/emit! dw/clear-edition-mode)))
|
||||||
|
|
||||||
on-click
|
on-click-outside
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
|
@ -304,7 +299,7 @@
|
||||||
on-mount
|
on-mount
|
||||||
(fn []
|
(fn []
|
||||||
(when (not read-only?)
|
(when (not read-only?)
|
||||||
(let [lkey1 (events/listen js/document EventType.CLICK on-click)
|
(let [lkey1 (events/listen js/document EventType.CLICK on-click-outside)
|
||||||
lkey2 (events/listen js/document EventType.KEYUP on-key-up)]
|
lkey2 (events/listen js/document EventType.KEYUP on-key-up)]
|
||||||
(st/emit! (dwt/assign-editor id editor)
|
(st/emit! (dwt/assign-editor id editor)
|
||||||
dwc/start-undo-transaction)
|
dwc/start-undo-transaction)
|
||||||
|
@ -327,22 +322,42 @@
|
||||||
(let [content (js->clj val :keywordize-keys true)
|
(let [content (js->clj val :keywordize-keys true)
|
||||||
content (first content)]
|
content (first content)]
|
||||||
(st/emit! (dw/update-shape id {:content content}))
|
(st/emit! (dw/update-shape id {:content content}))
|
||||||
(reset! state val)))))]
|
(reset! state val)))))
|
||||||
|
|
||||||
|
loaded-fonts (mf/use-var 0)
|
||||||
|
on-load-font #(swap! loaded-fonts inc)]
|
||||||
|
|
||||||
(mf/use-effect on-mount)
|
(mf/use-effect on-mount)
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps @state)
|
(mf/deps content)
|
||||||
|
(fn []
|
||||||
|
(reset! state (parse-content content))))
|
||||||
|
|
||||||
|
;; Checks the size of the wrapper to update if it were necesary
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps props @loaded-fonts)
|
||||||
(fn []
|
(fn []
|
||||||
(timers/schedule
|
(timers/schedule
|
||||||
#(if (#{:auto-width :auto-height} grow-type)
|
250 ;; We need to wait to the text to be rendered. Is there a better alternative?
|
||||||
(let [self-node (mf/ref-val self-ref)
|
#(let [self-node (mf/ref-val self-ref)
|
||||||
paragraph-node (dom/query self-node ".paragraph-set")]
|
paragraph-node (when self-node (dom/query self-node ".paragraph-set"))]
|
||||||
(when paragraph-node
|
(when paragraph-node
|
||||||
(let [{:keys [width height]} (dom/get-bounding-rect paragraph-node)]
|
(let [{:keys [width height]} (dom/get-bounding-rect paragraph-node)]
|
||||||
(st/emit! (dw/update-shape id (if (= grow-type :auto-width)
|
(cond
|
||||||
{:width width :height height}
|
(and (:overflow-text shape) (not= :fixed (:grow-type shape)))
|
||||||
{:height height}))))))))))
|
(st/emit! (dwt/update-overflow-text id false))
|
||||||
|
|
||||||
|
(and (= :fixed (:grow-type shape)) (not (:overflow-text shape)) (> height (:height shape)))
|
||||||
|
(st/emit! (dwt/update-overflow-text id true))
|
||||||
|
|
||||||
|
(and (= :fixed (:grow-type shape)) (:overflow-text shape) (<= height (:height shape)))
|
||||||
|
(st/emit! (dwt/update-overflow-text id false)))
|
||||||
|
|
||||||
|
(if (#{:auto-width :auto-height} grow-type)
|
||||||
|
(st/emit! (dw/update-shape id (if (= grow-type :auto-width)
|
||||||
|
{:width width :height height}
|
||||||
|
{:height height}))))))))))
|
||||||
|
|
||||||
[:foreignObject {:ref self-ref
|
[:foreignObject {:ref self-ref
|
||||||
:transform (geom/transform-matrix shape)
|
:transform (geom/transform-matrix shape)
|
||||||
|
@ -358,9 +373,10 @@
|
||||||
:spell-check "false"
|
:spell-check "false"
|
||||||
:on-focus on-focus
|
:on-focus on-focus
|
||||||
:class "rich-text"
|
:class "rich-text"
|
||||||
:style {:cursor cur/text}
|
:style {:cursor cur/text
|
||||||
|
:width (:width shape)}
|
||||||
:render-element #(render-element shape %)
|
:render-element #(render-element shape %)
|
||||||
:render-leaf render-text
|
:render-leaf (render-text on-load-font)
|
||||||
:on-mouse-up on-mouse-up
|
:on-mouse-up on-mouse-up
|
||||||
:on-mouse-down on-mouse-down
|
:on-mouse-down on-mouse-down
|
||||||
:on-blur (fn [event]
|
:on-blur (fn [event]
|
||||||
|
|
|
@ -308,7 +308,7 @@
|
||||||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(and (not edition) (= 1 (.-which event)))
|
(and (= 1 (.-which event)))
|
||||||
(if drawing-tool
|
(if drawing-tool
|
||||||
(st/emit! (dd/start-drawing drawing-tool))
|
(st/emit! (dd/start-drawing drawing-tool))
|
||||||
(st/emit! dw/handle-selection))
|
(st/emit! dw/handle-selection))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue