mirror of
https://github.com/penpot/penpot.git
synced 2025-05-23 01:46:11 +02:00
🎉 Add fill and opacity to texts.
This commit is contained in:
parent
fe397f89de
commit
c0173c499a
6 changed files with 166 additions and 55 deletions
|
@ -18,9 +18,6 @@
|
||||||
[uxbox.main.fonts :as fonts]
|
[uxbox.main.fonts :as fonts]
|
||||||
["slate" :as slate :refer [Editor Transforms Text]]))
|
["slate" :as slate :refer [Editor Transforms Text]]))
|
||||||
|
|
||||||
(declare set-nodes!)
|
|
||||||
(declare is-text?)
|
|
||||||
|
|
||||||
(defn assign-editor
|
(defn assign-editor
|
||||||
[editor]
|
[editor]
|
||||||
(ptk/reify ::assign-editor
|
(ptk/reify ::assign-editor
|
||||||
|
@ -93,14 +90,20 @@
|
||||||
at]
|
at]
|
||||||
:as opts}]
|
:as opts}]
|
||||||
(when editor
|
(when editor
|
||||||
(let [options #js {:match pred
|
(let [options #js {:match pred :universal universal?}
|
||||||
:universal universal?}
|
default-loc #js {:path #js [0 0] :offset 0}]
|
||||||
_ (when at (unchecked-set options "at" at))
|
|
||||||
|
|
||||||
result (.nodes Editor editor options)
|
(cond
|
||||||
match (ffirst (es6-iterator-seq result))]
|
(object? at)
|
||||||
(when (object? match)
|
(unchecked-set options "at" at)
|
||||||
(unchecked-get match attr)))))
|
|
||||||
|
(nil? (unchecked-get editor "selection"))
|
||||||
|
(unchecked-set options "at" default-loc))
|
||||||
|
|
||||||
|
(let [result (.nodes Editor editor options)
|
||||||
|
match (ffirst (es6-iterator-seq result))]
|
||||||
|
(when (object? match)
|
||||||
|
(unchecked-get match attr))))))
|
||||||
|
|
||||||
(defn current-line-height
|
(defn current-line-height
|
||||||
[editor {:keys [at default]}]
|
[editor {:keys [at default]}]
|
||||||
|
@ -145,6 +148,24 @@
|
||||||
default))
|
default))
|
||||||
|
|
||||||
|
|
||||||
|
(defn current-fill
|
||||||
|
[editor {:keys [at default]}]
|
||||||
|
(or (current-value editor {:at at
|
||||||
|
:pred is-text?
|
||||||
|
:attr "fill"
|
||||||
|
:universal? true})
|
||||||
|
default))
|
||||||
|
|
||||||
|
|
||||||
|
(defn current-opacity
|
||||||
|
[editor {:keys [at default]}]
|
||||||
|
(or (current-value editor {:at at
|
||||||
|
:pred is-text?
|
||||||
|
:attr "opacity"
|
||||||
|
:universal? true})
|
||||||
|
default))
|
||||||
|
|
||||||
|
|
||||||
;; --- Setters
|
;; --- Setters
|
||||||
|
|
||||||
|
|
||||||
|
@ -214,5 +235,16 @@
|
||||||
#js {:match is-text?
|
#js {:match is-text?
|
||||||
:split true}))
|
:split true}))
|
||||||
|
|
||||||
|
(defn set-fill!
|
||||||
|
[editor val]
|
||||||
|
(set-nodes! editor
|
||||||
|
#js {:fill val}
|
||||||
|
#js {:match is-text?
|
||||||
|
:split true}))
|
||||||
|
|
||||||
|
(defn set-opacity!
|
||||||
|
[editor val]
|
||||||
|
(set-nodes! editor
|
||||||
|
#js {:opacity val}
|
||||||
|
#js {:match is-text?
|
||||||
|
:split true}))
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
(defn- on-parent-clicked
|
(defn- on-parent-clicked
|
||||||
[event parent-ref]
|
[event parent-ref]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(dom/prevent-default event)
|
||||||
(let [parent (mf/ref-val parent-ref)
|
(let [parent (mf/ref-val parent-ref)
|
||||||
current (dom/get-target event)]
|
current (dom/get-target event)]
|
||||||
(when (dom/equals? parent current)
|
(when (dom/equals? parent current)
|
||||||
|
|
|
@ -154,10 +154,14 @@
|
||||||
|
|
||||||
font-family (unchecked-get data "fontFamily")
|
font-family (unchecked-get data "fontFamily")
|
||||||
font-size (unchecked-get data "fontSize")
|
font-size (unchecked-get data "fontSize")
|
||||||
|
fill (unchecked-get data "fill")
|
||||||
|
opacity (unchecked-get data "opacity")
|
||||||
|
|
||||||
fontsdb (mf/deref fonts/fontsdb)
|
fontsdb (mf/deref fonts/fontsdb)
|
||||||
|
|
||||||
base #js {:textDecoration text-decoration
|
base #js {:textDecoration text-decoration
|
||||||
|
:color fill
|
||||||
|
:opacity opacity
|
||||||
:textTransform text-transform}]
|
:textTransform text-transform}]
|
||||||
|
|
||||||
(when (and (string? letter-spacing)
|
(when (and (string? letter-spacing)
|
||||||
|
@ -250,10 +254,12 @@
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [sidebar (dom/get-element "settings-bar")
|
(let [sidebar (dom/get-element "settings-bar")
|
||||||
|
cpicker (dom/get-element-by-class "colorpicker-tooltip")
|
||||||
self (mf/ref-val self-ref)
|
self (mf/ref-val self-ref)
|
||||||
target (dom/get-target event)]
|
target (dom/get-target event)]
|
||||||
(when-not (or (.contains sidebar target)
|
(when-not (or (.contains sidebar target)
|
||||||
(.contains self target))
|
(.contains self target)
|
||||||
|
(and cpicker (.contains cpicker target)))
|
||||||
(on-close))))
|
(on-close))))
|
||||||
|
|
||||||
on-keyup
|
on-keyup
|
||||||
|
@ -332,7 +338,9 @@
|
||||||
:height height}
|
:height height}
|
||||||
|
|
||||||
[:> rslate/Slate {:editor editor
|
[:> rslate/Slate {:editor editor
|
||||||
:value content}
|
:value content
|
||||||
|
:on-change (constantly nil)}
|
||||||
|
|
||||||
[:> rslate/Editable {:auto-focus "false"
|
[:> rslate/Editable {:auto-focus "false"
|
||||||
:read-only "true"
|
:read-only "true"
|
||||||
:class "rich-text"
|
:class "rich-text"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
(ns uxbox.main.ui.workspace.sidebar.options.text
|
(ns uxbox.main.ui.workspace.sidebar.options.text
|
||||||
(:require
|
(:require
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
|
[cuerdas.core :as str]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[uxbox.builtins.icons :as i]
|
[uxbox.builtins.icons :as i]
|
||||||
[uxbox.common.data :as d]
|
[uxbox.common.data :as d]
|
||||||
|
@ -17,6 +18,8 @@
|
||||||
[uxbox.main.data.workspace.texts :as dwt]
|
[uxbox.main.data.workspace.texts :as dwt]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.refs :as refs]
|
||||||
|
[uxbox.main.ui.modal :as modal]
|
||||||
|
[uxbox.main.ui.workspace.colorpicker :refer [colorpicker-modal]]
|
||||||
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measures-menu]]
|
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measures-menu]]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.main.fonts :as fonts]
|
[uxbox.main.fonts :as fonts]
|
||||||
|
@ -77,6 +80,7 @@
|
||||||
(dwt/set-font! editor (:id font) (:family font))
|
(dwt/set-font! editor (:id font) (:family font))
|
||||||
(dwt/set-font-variant! editor id (:weight variant) (:style variant))))
|
(dwt/set-font-variant! editor id (:weight variant) (:style variant))))
|
||||||
]
|
]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:div.row-flex
|
[:div.row-flex
|
||||||
[:select.input-select {:value font-id
|
[:select.input-select {:value font-id
|
||||||
|
@ -116,9 +120,9 @@
|
||||||
(mf/defc text-align-options
|
(mf/defc text-align-options
|
||||||
[{:keys [editor] :as props}]
|
[{:keys [editor] :as props}]
|
||||||
(let [on-text-align-change
|
(let [on-text-align-change
|
||||||
(fn [event type]
|
(fn [event type]
|
||||||
(js/console.log (dwt/set-text-align! editor type)))]
|
(dwt/set-text-align! editor type))]
|
||||||
;; --- Align
|
;; --- Align
|
||||||
|
|
||||||
[:div.row-flex.align-icons
|
[:div.row-flex.align-icons
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
|
@ -146,6 +150,77 @@
|
||||||
:on-click #(on-text-align-change % "justify")}
|
:on-click #(on-text-align-change % "justify")}
|
||||||
i/text-align-justify]]))
|
i/text-align-justify]]))
|
||||||
|
|
||||||
|
|
||||||
|
(mf/defc text-fill-options
|
||||||
|
[{:keys [editor] :as props}]
|
||||||
|
(let [color (dwt/current-fill editor {:default "#000000"})
|
||||||
|
opacity (dwt/current-opacity editor {:default 1})
|
||||||
|
opacity (math/round (* opacity 100))
|
||||||
|
|
||||||
|
on-color-change
|
||||||
|
(fn [color]
|
||||||
|
(dwt/set-fill! editor color))
|
||||||
|
|
||||||
|
on-color-input-change
|
||||||
|
(fn [event]
|
||||||
|
(let [input (dom/get-target event)
|
||||||
|
value (dom/get-value input)]
|
||||||
|
(when (dom/valid? input)
|
||||||
|
(on-color-change value))))
|
||||||
|
|
||||||
|
on-opacity-change
|
||||||
|
(fn [event]
|
||||||
|
(let [value (-> (dom/get-target event)
|
||||||
|
(dom/get-value))]
|
||||||
|
(when (str/numeric? value)
|
||||||
|
(let [value (-> (d/parse-integer value 1)
|
||||||
|
(/ 100))]
|
||||||
|
(dwt/set-opacity! editor value)))))
|
||||||
|
|
||||||
|
show-color-picker
|
||||||
|
(fn [event]
|
||||||
|
(let [x (.-clientX event)
|
||||||
|
y (.-clientY event)
|
||||||
|
props {:x x :y y
|
||||||
|
:on-change on-color-change
|
||||||
|
:default "#ffffff"
|
||||||
|
:value color
|
||||||
|
:transparent? true}]
|
||||||
|
(modal/show! colorpicker-modal props)))]
|
||||||
|
|
||||||
|
[:div.row-flex.color-data
|
||||||
|
[:span.color-th
|
||||||
|
{:style {:background-color color}
|
||||||
|
:on-click show-color-picker
|
||||||
|
}]
|
||||||
|
|
||||||
|
[:div.color-info
|
||||||
|
[:input {:default-value color
|
||||||
|
:pattern "^#(?:[0-9a-fA-F]{3}){1,2}$"
|
||||||
|
:ref (fn [el]
|
||||||
|
(when el
|
||||||
|
(set! (.-value el) color)))
|
||||||
|
:on-change on-color-input-change
|
||||||
|
}]]
|
||||||
|
|
||||||
|
[:div.input-element.percentail
|
||||||
|
[:input.input-text {:type "number"
|
||||||
|
:ref (fn [el]
|
||||||
|
(when el
|
||||||
|
(set! (.-value el) opacity)))
|
||||||
|
:default-value opacity
|
||||||
|
:on-change on-opacity-change
|
||||||
|
:min "0"
|
||||||
|
:max "100"}]]
|
||||||
|
|
||||||
|
[:input.slidebar {:type "range"
|
||||||
|
:min "0"
|
||||||
|
:max "100"
|
||||||
|
:value opacity
|
||||||
|
:step "1"
|
||||||
|
:on-change on-opacity-change
|
||||||
|
}]]))
|
||||||
|
|
||||||
(mf/defc spacing-options
|
(mf/defc spacing-options
|
||||||
[{:keys [editor] :as props}]
|
[{:keys [editor] :as props}]
|
||||||
(let [selection (mf/use-ref)
|
(let [selection (mf/use-ref)
|
||||||
|
@ -164,21 +239,10 @@
|
||||||
:min "0"
|
:min "0"
|
||||||
:max "200"
|
:max "200"
|
||||||
:value lh
|
:value lh
|
||||||
:on-focus (fn [event]
|
|
||||||
(js/console.log "line-height on-focus")
|
|
||||||
;; (mf/set-ref-val! selection (.-selection editor))
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(dom/stop-propagation event))
|
|
||||||
:on-blur (fn [event]
|
|
||||||
;; (js/console.log "line-height on-blur")
|
|
||||||
(mf/set-ref-val! selection nil)
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(dom/stop-propagation event))
|
|
||||||
:on-change (fn [event]
|
:on-change (fn [event]
|
||||||
(let [val (-> (dom/get-target event)
|
(let [val (-> (dom/get-target event)
|
||||||
(dom/get-value))
|
(dom/get-value))
|
||||||
sel (mf/ref-val selection)]
|
sel (mf/ref-val selection)]
|
||||||
;; (js/console.log "line-height on-change" sel val)
|
|
||||||
(dwt/set-line-height! editor val sel)))}]]
|
(dwt/set-line-height! editor val sel)))}]]
|
||||||
[:div.input-icon
|
[:div.input-icon
|
||||||
[:span.icon-before.tooltip.tooltip-bottom
|
[:span.icon-before.tooltip.tooltip-bottom
|
||||||
|
@ -190,21 +254,10 @@
|
||||||
:min "0"
|
:min "0"
|
||||||
:max "200"
|
:max "200"
|
||||||
:value ls
|
:value ls
|
||||||
:on-focus (fn [event]
|
|
||||||
;; (js/console.log "letter-spacing on-focus")
|
|
||||||
(mf/set-ref-val! selection (.-selection editor))
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(dom/stop-propagation event))
|
|
||||||
:on-blur (fn [event]
|
|
||||||
;; (js/console.log "letter-spacing on-blur")
|
|
||||||
(mf/set-ref-val! selection nil)
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(dom/stop-propagation event))
|
|
||||||
:on-change (fn [event]
|
:on-change (fn [event]
|
||||||
(let [val (-> (dom/get-target event)
|
(let [val (-> (dom/get-target event)
|
||||||
(dom/get-value))
|
(dom/get-value))
|
||||||
sel (mf/ref-val selection)]
|
sel (mf/ref-val selection)]
|
||||||
;; (js/console.log "letter-spacing on-change" sel val)
|
|
||||||
(dwt/set-letter-spacing! editor val sel)))}]]]))
|
(dwt/set-letter-spacing! editor val sel)))}]]]))
|
||||||
|
|
||||||
(mf/defc box-sizing-options
|
(mf/defc box-sizing-options
|
||||||
|
@ -263,10 +316,10 @@
|
||||||
i/minus]
|
i/minus]
|
||||||
|
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
{:alt "Underline"
|
{:alt "Underline"
|
||||||
:class (dom/classnames
|
:class (dom/classnames
|
||||||
:current (dwt/text-decoration-enabled? editor "underline"))
|
:current (dwt/text-decoration-enabled? editor "underline"))
|
||||||
:on-click #(on-decoration-change % "underline")}
|
:on-click #(on-decoration-change % "underline")}
|
||||||
i/underline]
|
i/underline]
|
||||||
|
|
||||||
[:span.tooltip.tooltip-bottom
|
[:span.tooltip.tooltip-bottom
|
||||||
|
@ -324,19 +377,26 @@
|
||||||
editor (:editor (mf/deref refs/workspace-local))
|
editor (:editor (mf/deref refs/workspace-local))
|
||||||
locale (i18n/use-locale)]
|
locale (i18n/use-locale)]
|
||||||
|
|
||||||
[:div.element-set
|
[:*
|
||||||
[:div.element-set-title (t locale "workspace.options.font-options")]
|
[:div.element-set
|
||||||
[:div.element-set-content
|
[:div.element-set-title (t locale "workspace.options.fill")]
|
||||||
[:& font-options {:editor editor}]
|
[:div.element-set-content
|
||||||
[:& text-align-options {:editor editor}]
|
[:& text-fill-options {:editor editor}]]]
|
||||||
[:& spacing-options {:editor editor}]
|
|
||||||
|
|
||||||
[:div.row-flex
|
|
||||||
[:& vertical-align-options {:editor editor}]
|
|
||||||
[:& box-sizing-options {:editor editor}]]
|
|
||||||
|
|
||||||
[:& text-decoration-options {:editor editor}]
|
[:div.element-set
|
||||||
[:& text-transform-options {:editor editor}]]]))
|
[:div.element-set-title (t locale "workspace.options.font-options")]
|
||||||
|
[:div.element-set-content
|
||||||
|
[:& font-options {:editor editor}]
|
||||||
|
[:& text-align-options {:editor editor}]
|
||||||
|
[:& spacing-options {:editor editor}]
|
||||||
|
|
||||||
|
[:div.row-flex
|
||||||
|
[:& vertical-align-options {:editor editor}]
|
||||||
|
[:& box-sizing-options {:editor editor}]]
|
||||||
|
|
||||||
|
[:& text-decoration-options {:editor editor}]
|
||||||
|
[:& text-transform-options {:editor editor}]]]]))
|
||||||
|
|
||||||
(mf/defc options
|
(mf/defc options
|
||||||
[{:keys [shape] :as props}]
|
[{:keys [shape] :as props}]
|
||||||
|
|
|
@ -291,6 +291,7 @@
|
||||||
:on-mouse-up on-mouse-up
|
:on-mouse-up on-mouse-up
|
||||||
:on-drag-over on-drag-over
|
:on-drag-over on-drag-over
|
||||||
:on-drop on-drop}
|
:on-drop on-drop}
|
||||||
|
|
||||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||||
;; [:& perf/profiler {:label "viewport-frames"}
|
;; [:& perf/profiler {:label "viewport-frames"}
|
||||||
[:& frames {:key (:id page)}]
|
[:& frames {:key (:id page)}]
|
||||||
|
|
|
@ -7,11 +7,19 @@
|
||||||
(ns uxbox.util.interop
|
(ns uxbox.util.interop
|
||||||
"Interop helpers.")
|
"Interop helpers.")
|
||||||
|
|
||||||
|
;; TODO: this can be optimized using es6-iterator-seq
|
||||||
(defn iterable->seq
|
(defn iterable->seq
|
||||||
"Convert an es6 iterable into cljs Seq."
|
"Convert an es6 iterable into cljs Seq."
|
||||||
[v]
|
[v]
|
||||||
(seq (js/Array.from v)))
|
(seq (js/Array.from v)))
|
||||||
|
|
||||||
(defn obj-assign!
|
(defn obj-assign!
|
||||||
[obj1 obj2]
|
([a b]
|
||||||
(js/Object.assign obj1 obj2))
|
(js/Object.assign a b))
|
||||||
|
([a b & more]
|
||||||
|
(reduce obj-assign! (obj-assign! a b) more)))
|
||||||
|
|
||||||
|
(defn obj-assoc!
|
||||||
|
[obj attr value]
|
||||||
|
(unchecked-set obj attr value)
|
||||||
|
obj)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue