From c0173c499af7058cd3922787ce75f7a55d25e26e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 24 Apr 2020 13:19:38 +0200 Subject: [PATCH] :tada: Add fill and opacity to texts. --- .../src/uxbox/main/data/workspace/texts.cljs | 54 +++++-- frontend/src/uxbox/main/ui/modal.cljs | 2 + frontend/src/uxbox/main/ui/shapes/text.cljs | 12 +- .../ui/workspace/sidebar/options/text.cljs | 140 +++++++++++++----- .../src/uxbox/main/ui/workspace/viewport.cljs | 1 + frontend/src/uxbox/util/interop.cljs | 12 +- 6 files changed, 166 insertions(+), 55 deletions(-) diff --git a/frontend/src/uxbox/main/data/workspace/texts.cljs b/frontend/src/uxbox/main/data/workspace/texts.cljs index 1dfb67bc1..14ad941b1 100644 --- a/frontend/src/uxbox/main/data/workspace/texts.cljs +++ b/frontend/src/uxbox/main/data/workspace/texts.cljs @@ -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})) diff --git a/frontend/src/uxbox/main/ui/modal.cljs b/frontend/src/uxbox/main/ui/modal.cljs index 2c6d3dd4e..369df3aa4 100644 --- a/frontend/src/uxbox/main/ui/modal.cljs +++ b/frontend/src/uxbox/main/ui/modal.cljs @@ -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) diff --git a/frontend/src/uxbox/main/ui/shapes/text.cljs b/frontend/src/uxbox/main/ui/shapes/text.cljs index a2fa2dcdb..91949369f 100644 --- a/frontend/src/uxbox/main/ui/shapes/text.cljs +++ b/frontend/src/uxbox/main/ui/shapes/text.cljs @@ -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" diff --git a/frontend/src/uxbox/main/ui/workspace/sidebar/options/text.cljs b/frontend/src/uxbox/main/ui/workspace/sidebar/options/text.cljs index 4ec9d6ed3..c65b73bc0 100644 --- a/frontend/src/uxbox/main/ui/workspace/sidebar/options/text.cljs +++ b/frontend/src/uxbox/main/ui/workspace/sidebar/options/text.cljs @@ -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}] diff --git a/frontend/src/uxbox/main/ui/workspace/viewport.cljs b/frontend/src/uxbox/main/ui/workspace/viewport.cljs index b0aeae012..0fc2203ac 100644 --- a/frontend/src/uxbox/main/ui/workspace/viewport.cljs +++ b/frontend/src/uxbox/main/ui/workspace/viewport.cljs @@ -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)}] diff --git a/frontend/src/uxbox/util/interop.cljs b/frontend/src/uxbox/util/interop.cljs index ae76b74a6..1f9a20a58 100644 --- a/frontend/src/uxbox/util/interop.cljs +++ b/frontend/src/uxbox/util/interop.cljs @@ -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)