mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 03:21:26 -05: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]
|
||||
["slate" :as slate :refer [Editor Transforms Text]]))
|
||||
|
||||
(declare set-nodes!)
|
||||
(declare is-text?)
|
||||
|
||||
(defn assign-editor
|
||||
[editor]
|
||||
(ptk/reify ::assign-editor
|
||||
|
@ -93,14 +90,20 @@
|
|||
at]
|
||||
:as opts}]
|
||||
(when editor
|
||||
(let [options #js {:match pred
|
||||
:universal universal?}
|
||||
_ (when at (unchecked-set options "at" at))
|
||||
(let [options #js {:match pred :universal universal?}
|
||||
default-loc #js {:path #js [0 0] :offset 0}]
|
||||
|
||||
result (.nodes Editor editor options)
|
||||
match (ffirst (es6-iterator-seq result))]
|
||||
(when (object? match)
|
||||
(unchecked-get match attr)))))
|
||||
(cond
|
||||
(object? at)
|
||||
(unchecked-set options "at" at)
|
||||
|
||||
(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
|
||||
[editor {:keys [at default]}]
|
||||
|
@ -145,6 +148,24 @@
|
|||
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
|
||||
|
||||
|
||||
|
@ -214,5 +235,16 @@
|
|||
#js {:match is-text?
|
||||
: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
|
||||
[event parent-ref]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
(let [parent (mf/ref-val parent-ref)
|
||||
current (dom/get-target event)]
|
||||
(when (dom/equals? parent current)
|
||||
|
|
|
@ -154,10 +154,14 @@
|
|||
|
||||
font-family (unchecked-get data "fontFamily")
|
||||
font-size (unchecked-get data "fontSize")
|
||||
fill (unchecked-get data "fill")
|
||||
opacity (unchecked-get data "opacity")
|
||||
|
||||
fontsdb (mf/deref fonts/fontsdb)
|
||||
|
||||
base #js {:textDecoration text-decoration
|
||||
:color fill
|
||||
:opacity opacity
|
||||
:textTransform text-transform}]
|
||||
|
||||
(when (and (string? letter-spacing)
|
||||
|
@ -250,10 +254,12 @@
|
|||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(let [sidebar (dom/get-element "settings-bar")
|
||||
cpicker (dom/get-element-by-class "colorpicker-tooltip")
|
||||
self (mf/ref-val self-ref)
|
||||
target (dom/get-target event)]
|
||||
(when-not (or (.contains sidebar target)
|
||||
(.contains self target))
|
||||
(.contains self target)
|
||||
(and cpicker (.contains cpicker target)))
|
||||
(on-close))))
|
||||
|
||||
on-keyup
|
||||
|
@ -332,7 +338,9 @@
|
|||
:height height}
|
||||
|
||||
[:> rslate/Slate {:editor editor
|
||||
:value content}
|
||||
:value content
|
||||
:on-change (constantly nil)}
|
||||
|
||||
[:> rslate/Editable {:auto-focus "false"
|
||||
:read-only "true"
|
||||
:class "rich-text"
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
(ns uxbox.main.ui.workspace.sidebar.options.text
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.common.data :as d]
|
||||
|
@ -17,6 +18,8 @@
|
|||
[uxbox.main.data.workspace.texts :as dwt]
|
||||
[uxbox.main.store :as st]
|
||||
[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.util.dom :as dom]
|
||||
[uxbox.main.fonts :as fonts]
|
||||
|
@ -77,6 +80,7 @@
|
|||
(dwt/set-font! editor (:id font) (:family font))
|
||||
(dwt/set-font-variant! editor id (:weight variant) (:style variant))))
|
||||
]
|
||||
|
||||
[:*
|
||||
[:div.row-flex
|
||||
[:select.input-select {:value font-id
|
||||
|
@ -116,9 +120,9 @@
|
|||
(mf/defc text-align-options
|
||||
[{:keys [editor] :as props}]
|
||||
(let [on-text-align-change
|
||||
(fn [event type]
|
||||
(js/console.log (dwt/set-text-align! editor type)))]
|
||||
;; --- Align
|
||||
(fn [event type]
|
||||
(dwt/set-text-align! editor type))]
|
||||
;; --- Align
|
||||
|
||||
[:div.row-flex.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
|
@ -146,6 +150,77 @@
|
|||
:on-click #(on-text-align-change % "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
|
||||
[{:keys [editor] :as props}]
|
||||
(let [selection (mf/use-ref)
|
||||
|
@ -164,21 +239,10 @@
|
|||
:min "0"
|
||||
:max "200"
|
||||
: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]
|
||||
(let [val (-> (dom/get-target event)
|
||||
(dom/get-value))
|
||||
sel (mf/ref-val selection)]
|
||||
;; (js/console.log "line-height on-change" sel val)
|
||||
(dwt/set-line-height! editor val sel)))}]]
|
||||
[:div.input-icon
|
||||
[:span.icon-before.tooltip.tooltip-bottom
|
||||
|
@ -190,21 +254,10 @@
|
|||
:min "0"
|
||||
:max "200"
|
||||
: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]
|
||||
(let [val (-> (dom/get-target event)
|
||||
(dom/get-value))
|
||||
sel (mf/ref-val selection)]
|
||||
;; (js/console.log "letter-spacing on-change" sel val)
|
||||
(dwt/set-letter-spacing! editor val sel)))}]]]))
|
||||
|
||||
(mf/defc box-sizing-options
|
||||
|
@ -263,10 +316,10 @@
|
|||
i/minus]
|
||||
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt "Underline"
|
||||
:class (dom/classnames
|
||||
:current (dwt/text-decoration-enabled? editor "underline"))
|
||||
:on-click #(on-decoration-change % "underline")}
|
||||
{:alt "Underline"
|
||||
:class (dom/classnames
|
||||
:current (dwt/text-decoration-enabled? editor "underline"))
|
||||
:on-click #(on-decoration-change % "underline")}
|
||||
i/underline]
|
||||
|
||||
[:span.tooltip.tooltip-bottom
|
||||
|
@ -324,19 +377,26 @@
|
|||
editor (:editor (mf/deref refs/workspace-local))
|
||||
locale (i18n/use-locale)]
|
||||
|
||||
[:div.element-set
|
||||
[: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.element-set
|
||||
[:div.element-set-title (t locale "workspace.options.fill")]
|
||||
[:div.element-set-content
|
||||
[:& text-fill-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}]]]))
|
||||
[:div.element-set
|
||||
[: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
|
||||
[{:keys [shape] :as props}]
|
||||
|
|
|
@ -291,6 +291,7 @@
|
|||
:on-mouse-up on-mouse-up
|
||||
:on-drag-over on-drag-over
|
||||
:on-drop on-drop}
|
||||
|
||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||
;; [:& perf/profiler {:label "viewport-frames"}
|
||||
[:& frames {:key (:id page)}]
|
||||
|
|
|
@ -7,11 +7,19 @@
|
|||
(ns uxbox.util.interop
|
||||
"Interop helpers.")
|
||||
|
||||
;; TODO: this can be optimized using es6-iterator-seq
|
||||
(defn iterable->seq
|
||||
"Convert an es6 iterable into cljs Seq."
|
||||
[v]
|
||||
(seq (js/Array.from v)))
|
||||
|
||||
(defn obj-assign!
|
||||
[obj1 obj2]
|
||||
(js/Object.assign obj1 obj2))
|
||||
([a b]
|
||||
(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
Reference in a new issue