diff --git a/common/app/common/pages.cljc b/common/app/common/pages.cljc index 2cd0ebf20..348d98b47 100644 --- a/common/app/common/pages.cljc +++ b/common/app/common/pages.cljc @@ -55,7 +55,7 @@ (>= % min-safe-int) (<= % max-safe-int))) - +;; GRADIENTS (s/def :internal.gradient.stop/color ::string) (s/def :internal.gradient.stop/opacity ::safe-number) @@ -85,6 +85,63 @@ :internal.gradient/width :internal.gradient/stops])) + +;;; COLORS + +(s/def :internal.color/name ::string) +(s/def :internal.color/value (s/nilable ::string)) +(s/def :internal.color/color (s/nilable ::string)) +(s/def :internal.color/opacity (s/nilable ::safe-number)) +(s/def :internal.color/gradient (s/nilable ::gradient)) + +(s/def ::color + (s/keys :opt-un [::id + :internal.color/name + :internal.color/value + :internal.color/color + :internal.color/opacity + :internal.color/gradient])) + + + +;;; SHADOW EFFECT + +(s/def :internal.shadow/id uuid?) +(s/def :internal.shadow/style #{:drop-shadow :inner-shadow}) +(s/def :internal.shadow/color ::color) +(s/def :internal.shadow/offset-x ::safe-number) +(s/def :internal.shadow/offset-y ::safe-number) +(s/def :internal.shadow/blur ::safe-number) +(s/def :internal.shadow/spread ::safe-number) +(s/def :internal.shadow/hidden boolean?) + +(s/def :internal.shadow/shadow + (s/keys :req-un [:internal.shadow/id + :internal.shadow/style + :internal.shadow/color + :internal.shadow/offset-x + :internal.shadow/offset-y + :internal.shadow/blur + :internal.shadow/spread + :internal.shadow/hidden])) + +(s/def ::shadow + (s/coll-of :internal.shadow/shadow :kind vector?)) + + +;;; BLUR EFFECT + +(s/def :internal.blur/id uuid?) +(s/def :internal.blur/type #{:layer-blur}) +(s/def :internal.blur/value ::safe-number) +(s/def :internal.blur/hidden boolean?) + +(s/def ::blur + (s/keys :req-un [:internal.blur/id + :internal.blur/type + :internal.blur/value + :internal.blur/hidden])) + ;; Page Options (s/def :internal.page.grid.color/value string?) (s/def :internal.page.grid.color/opacity ::safe-number) @@ -175,6 +232,8 @@ (s/def :internal.shape/width ::safe-number) (s/def :internal.shape/height ::safe-number) (s/def :internal.shape/index integer?) +(s/def :internal.shape/shadow ::shadow) +(s/def :internal.shape/blur ::blur) (s/def :internal.shape/x1 ::safe-number) (s/def :internal.shape/y1 ::safe-number) @@ -246,7 +305,9 @@ :internal.shape/interactions :internal.shape/selrect :internal.shape/points - :internal.shape/masked-group?])) + :internal.shape/masked-group? + :internal.shape/shadow + :internal.shape/blur])) (def component-sync-attrs {:fill-color :fill-group :fill-color-ref-file :fill-group @@ -295,20 +356,6 @@ :internal.page/objects])) -(s/def :internal.color/name ::string) -(s/def :internal.color/value (s/nilable ::string)) -(s/def :internal.color/color (s/nilable ::string)) -(s/def :internal.color/opacity (s/nilable ::safe-number)) -(s/def :internal.color/gradient (s/nilable ::gradient)) - -(s/def ::color - (s/keys :req-un [::id - :internal.color/name] - :opt-un [:internal.color/value - :internal.color/color - :internal.color/opacity - :internal.color/gradient])) - (s/def ::recent-color (s/keys :opt-un [:internal.color/value :internal.color/color diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json index d0a00813f..43ccfefff 100644 --- a/frontend/resources/locales.json +++ b/frontend/resources/locales.json @@ -2271,6 +2271,24 @@ }, "unused" : true }, + "workspace.options.blur-options.background-blur" : { + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/blur.cljs:78" ], + "translations" : { + "en" : "Background" + } + }, + "workspace.options.blur-options.layer-blur" : { + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/blur.cljs:77" ], + "translations" : { + "en" : "Layer" + } + }, + "workspace.options.blur-options.title" : { + "used-in" : [ "src/app/main/ui/workspace/sidebar/options/blur.cljs:107" ], + "translations" : { + "en" : "Blur" + } + }, "workspace.options.canvas-background" : { "used-in" : [ "src/app/main/ui/workspace/sidebar/options/page.cljs:45" ], "translations" : { diff --git a/frontend/resources/styles/main/partials/sidebar-sitemap.scss b/frontend/resources/styles/main/partials/sidebar-sitemap.scss index a94829d0a..b04d09fe7 100644 --- a/frontend/resources/styles/main/partials/sidebar-sitemap.scss +++ b/frontend/resources/styles/main/partials/sidebar-sitemap.scss @@ -163,6 +163,17 @@ } } +.element-set-title-actions { + display: flex; + flex-direction: row; + flex: 1; + justify-content: flex-end; + + .add-page { + margin: 0; + } +} + .collapse-pages { margin-left: $small; diff --git a/frontend/src/app/main/ui/shapes/filters.cljs b/frontend/src/app/main/ui/shapes/filters.cljs index 3fafec419..89a7374f3 100644 --- a/frontend/src/app/main/ui/shapes/filters.cljs +++ b/frontend/src/app/main/ui/shapes/filters.cljs @@ -12,6 +12,7 @@ [rumext.alpha :as mf] [cuerdas.core :as str] [app.util.color :as color] + [app.common.data :as d] [app.common.math :as mth] [app.common.uuid :as uuid])) @@ -21,7 +22,8 @@ (defn filter-str [filter-id shape] - (when (seq (:shadow shape)) + (when (or (seq (->> (:shadow shape) (remove :hidden))) + (and (:blur shape) (-> shape :blur :hidden not))) (str/fmt "url(#$0)" [filter-id]))) (mf/defc color-matrix @@ -34,10 +36,9 @@ :values (str/fmt "0 0 0 0 $0 0 0 0 0 $1 0 0 0 0 $2 0 0 0 $3 0" [r g b a])}])) (mf/defc drop-shadow-filter - [{:keys [filter-id filter shape]}] + [{:keys [filter-in filter-id params]}] - (let [{:keys [x y width height]} (:selrect shape) - {:keys [id in-filter color offset-x offset-y blur spread]} filter] + (let [{:keys [color offset-x offset-y blur spread]} params] [:* [:feColorMatrix {:in "SourceAlpha" :type "matrix" :values "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"}] @@ -45,21 +46,20 @@ [:feMorphology {:radius spread :operator "dilate" :in "SourceAlpha" - :result (str "filter" id)}]) + :result filter-id}]) [:feOffset {:dx offset-x :dy offset-y}] [:feGaussianBlur {:stdDeviation (/ blur 2)}] [:& color-matrix {:color color}] [:feBlend {:mode "normal" - :in2 in-filter - :result (str "filter" id)}]])) + :in2 filter-in + :result filter-id}]])) (mf/defc inner-shadow-filter - [{:keys [filter-id filter shape]}] + [{:keys [filter-in filter-id params]}] - (let [{:keys [x y width height]} (:selrect shape) - {:keys [id in-filter color offset-x offset-y blur spread]} filter] + (let [{:keys [color offset-x offset-y blur spread]} params] [:* [:feColorMatrix {:in "SourceAlpha" :type "matrix" :values "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" @@ -69,7 +69,7 @@ [:feMorphology {:radius spread :operator "erode" :in "SourceAlpha" - :result (str "filter" id)}]) + :result filter-id}]) [:feOffset {:dx offset-x :dy offset-y}] [:feGaussianBlur {:stdDeviation (/ blur 2)}] @@ -82,12 +82,36 @@ [:& color-matrix {:color color}] [:feBlend {:mode "normal" - :in2 in-filter - :result (str "filter" id)}]])) + :in2 filter-in + :result filter-id}]])) -(defn filter-bounds [shape filter] +(mf/defc background-blur-filter + [{:keys [filter-id filter-in params]}] + [:* + [:feGaussianBlur {:in "BackgroundImage" + :stdDeviation (/ (:value params) 2)}] + [:feComposite {:in2 "SourceAlpha" + :operator "in" + :result filter-id}]]) + +(mf/defc layer-blur-filter + [{:keys [filter-id params]}] + + [:feGaussianBlur {:stdDeviation (/ (:value params) 2) + :result filter-id}]) + +(mf/defc image-fix-filter [{:keys [filter-id]}] + [:feFlood {:flood-opacity 0 :result filter-id}]) + +(mf/defc blend-filters [{:keys [filter-id filter-in]}] + [:feBlend {:mode "normal" + :in "SourceGraphic" + :in2 filter-in + :result filter-id}]) + +(defn filter-bounds [shape filter-entry] (let [{:keys [x y width height]} (:selrect shape) - {:keys [offset-x offset-y blur spread] :or {offset-x 0 offset-y 0 blur 0 spread 0}} filter + {:keys [offset-x offset-y blur spread] :or {offset-x 0 offset-y 0 blur 0 spread 0}} (:params filter-entry) filter-x (min x (+ x offset-x (- spread) (- blur) -5)) filter-y (min y (+ y offset-y (- spread) (- blur) -5)) filter-width (+ width (mth/abs offset-x) (* spread 2) (* blur 2) 10) @@ -98,67 +122,83 @@ :y2 (+ filter-y filter-height)})) (defn get-filters-bounds - [shape filters] + [shape filters blur-value] - (let [filter-bounds (->> - filters - (filter #(= :drop-shadow (:style %))) - (map (partial filter-bounds shape) )) + (let [filter-bounds (->> filters + (filter #(= :drop-shadow (:type %))) + (map (partial filter-bounds shape) )) ;; We add the selrect so the minimum size will be the selrect filter-bounds (conj filter-bounds (:selrect shape)) x1 (apply min (map :x1 filter-bounds)) y1 (apply min (map :y1 filter-bounds)) x2 (apply max (map :x2 filter-bounds)) - y2 (apply max (map :y2 filter-bounds))] + y2 (apply max (map :y2 filter-bounds)) + + x1 (- x1 (* blur-value 2)) + x2 (+ x2 (* blur-value 2)) + y1 (- y1 (* blur-value 2)) + y2 (+ y2 (* blur-value 2))] [x1 y1 (- x2 x1) (- y2 y1)])) +(defn blur-filters [type value] + (->> [value] + (remove :hidden) + (filter #(= (:type %) type)) + (map #(hash-map :id (str "filter_" (:id %)) + :type (:type %) + :params %)))) + +(defn shadow-filters [type filters] + (->> filters + (remove :hidden) + (filter #(= (:style %) type)) + (map #(hash-map :id (str "filter_" (:id %)) + :type (:style %) + :params %)))) + +(mf/defc filter-entry [{:keys [entry]}] + (let [props #js {:filter-id (:id entry) + :filter-in (:filter-in entry) + :params (:params entry)}] + (case (:type entry) + :drop-shadow [:> drop-shadow-filter props] + :inner-shadow [:> inner-shadow-filter props] + :background-blur [:> background-blur-filter props] + :layer-blur [:> layer-blur-filter props] + :image-fix [:> image-fix-filter props] + :blend-filters [:> blend-filters props]))) + (mf/defc filters [{:keys [filter-id shape]}] - (let [add-in-filter - (fn [filter in-filter] - (assoc filter :in-filter in-filter)) + (let [filters (d/concat + [] + [{:id "BackgroundImageFix" :type :image-fix}] - filters (->> shape :shadow (filter (comp not :hidden))) + ;; Background blur won't work in current SVG specification + ;; We can revisit this in the future + #_(->> shape :blur (blur-filters :background-blur)) - [filter-x filter-y filter-width filter-height] (get-filters-bounds shape filters)] - (when (seq filters) - [:filter {:id filter-id - :x filter-x :y filter-y - :width filter-width :height filter-height - :filterUnits "userSpaceOnUse" - :color-interpolation-filters "sRGB"} + (->> shape :shadow (shadow-filters :drop-shadow)) + [{:id "shape" :type :blend-filters}] + (->> shape :shadow (shadow-filters :inner-shadow)) + (->> shape :blur (blur-filters :layer-blur))) - (let [;; Add as a paramter the input filter - drop-shadow-filters (->> filters (filter #(= :drop-shadow (:style %)))) - drop-shadow-filters (->> drop-shadow-filters - (map #(str "filter" (:id %))) - (cons "BackgroundImageFix") - (map add-in-filter drop-shadow-filters)) + ;; Adds the previous filter as `filter-in` parameter + filters (map #(assoc %1 :filter-in %2) filters (cons nil (map :id filters))) - inner-shadow-filters (->> filters (filter #(= :inner-shadow (:style %)))) - inner-shadow-filters (->> inner-shadow-filters - (map #(str "filter" (:id %))) - (cons "shape") - (map add-in-filter inner-shadow-filters))] + [filter-x filter-y filter-width filter-height] (get-filters-bounds shape filters (or (-> shape :blur :value) 0))] - [:* - [:feFlood {:flood-opacity 0 :result "BackgroundImageFix"}] - (for [{:keys [id type] :as filter} drop-shadow-filters] - [:& drop-shadow-filter {:key id - :filter-id filter-id - :filter filter - :shape shape}]) + [:* + (when (> (count filters) 2) + [:filter {:id filter-id + :x filter-x + :y filter-y + :width filter-width + :height filter-height + :filterUnits "userSpaceOnUse" + :color-interpolation-filters "sRGB"} - [:feBlend {:mode "normal" - :in "SourceGraphic" - :in2 (if (seq drop-shadow-filters) - (str "filter" (:id (last drop-shadow-filters))) - "BackgroundImageFix") - :result "shape"}] + (for [entry filters] + [:& filter-entry {:entry entry}])])])) - (for [{:keys [id type] :as filter} inner-shadow-filters] - [:& inner-shadow-filter {:key id - :filter-id filter-id - :filter filter - :shape shape}])])]))) diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index 0567c1074..086f37bcb 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -10,12 +10,35 @@ (ns app.main.ui.shapes.shape (:require [rumext.alpha :as mf] + [cuerdas.core :as str] [app.util.object :as obj] [app.common.uuid :as uuid] + [app.common.geom.shapes :as geom] [app.main.ui.shapes.filters :as filters] [app.main.ui.shapes.gradients :as grad] [app.main.ui.context :as muc])) +(mf/defc background-blur [{:keys [shape]}] + (when-let [background-blur-filters (->> shape :blur (remove #(= (:type %) :layer-blur)) (remove :hidden))] + (for [filter background-blur-filters] + [:* + + + [:foreignObject {:key (str "blur_" (:id filter)) + :pointerEvents "none" + :x (:x shape) + :y (:y shape) + :width (:width shape) + :height (:height shape) + :transform (geom/transform-matrix shape)} + [:style ""] + [:div.backround-blur + {:style {:width "100%" + :height "100%" + ;; :backdrop-filter (str/format "blur(%spx)" (:value filter)) + :filter (str/format "blur(4px") + }}]]]))) + (mf/defc shape-container {::mf/wrap-props false} [props] @@ -28,12 +51,23 @@ (obj/clone) (obj/without ["shape" "children"]) (obj/set! "className" "shape") - (obj/set! "filter" (filters/filter-str filter-id shape)))] + (obj/set! "data-type" (:type shape)) + (obj/set! "filter" (filters/filter-str filter-id shape))) + + ;;group-props (if (seq (:blur shape)) + ;; (obj/set! group-props "clip-path" (str/fmt "url(#%s)" (str "blur_" render-id))) + ;; group-props) + ] [:& (mf/provider muc/render-ctx) {:value render-id} [:> :g group-props [:defs - [:& filters/filters {:shape shape :filter-id filter-id}] - [:& grad/gradient {:shape shape :attr :fill-color-gradient}] - [:& grad/gradient {:shape shape :attr :stroke-color-gradient}]] + [:& filters/filters {:shape shape :filter-id filter-id}] + [:& grad/gradient {:shape shape :attr :fill-color-gradient}] + [:& grad/gradient {:shape shape :attr :stroke-color-gradient}] + #_(when (:blur shape) + [:clipPath {:id (str "blur_" render-id)} + children])] + + [:& background-blur {:shape shape}] children]])) diff --git a/frontend/src/app/main/ui/workspace/shapes/group.cljs b/frontend/src/app/main/ui/workspace/shapes/group.cljs index d17f9c664..bb91982dd 100644 --- a/frontend/src/app/main/ui/workspace/shapes/group.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/group.cljs @@ -16,6 +16,7 @@ [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.workspace.shapes.common :as common] + [app.main.ui.shapes.shape :refer [shape-container]] [app.main.ui.shapes.group :as group] [app.util.dom :as dom] [app.main.streams :as ms] @@ -72,11 +73,10 @@ (dom/prevent-default event) (st/emit! (dw/select-inside-group (:id shape) @ms/mouse-position))))] - [:g.shape - {:on-mouse-down on-mouse-down - :on-context-menu on-context-menu - :on-double-click on-double-click} - + [:> shape-container {:shape shape + :on-mouse-down on-mouse-down + :on-context-menu on-context-menu + :on-double-click on-double-click} [:& group-shape {:frame frame :shape shape diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/blur.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/blur.cljs new file mode 100644 index 000000000..b6999bd0d --- /dev/null +++ b/frontend/src/app/main/ui/workspace/sidebar/options/blur.cljs @@ -0,0 +1,70 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2020 UXBOX Labs SL + +(ns app.main.ui.workspace.sidebar.options.blur + (:require + [rumext.alpha :as mf] + [app.common.data :as d] + [app.common.uuid :as uuid] + [app.main.data.workspace.common :as dwc] + [app.main.store :as st] + [app.main.ui.icons :as i] + [app.main.ui.workspace.sidebar.options.common :refer [advanced-options]] + [app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]] + [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] + [app.util.dom :as dom] + [app.util.i18n :as i18n :refer [t]])) + +(defn create-blur [] + (let [id (uuid/next)] + {:id id + :type :layer-blur + :value 4 + :hidden false})) + +(mf/defc blur-menu [{:keys [ids values]}] + (let [locale (i18n/use-locale) + blur (:blur values) + has-value? (not (nil? blur)) + + change! (fn [update-fn] (st/emit! (dwc/update-shapes ids update-fn))) + + handle-add + (fn [] + (change! #(assoc % :blur (create-blur)))) + + handle-delete + (fn [] + (change! #(dissoc % :blur))) + + handle-change + (fn [value] + (change! #(assoc-in % [:blur :value] value))) + + handle-toggle-visibility + (fn [] + (change! #(update-in % [:blur :hidden] not)))] + + [:div.element-set + [:div.element-set-title + [:span (t locale "workspace.options.blur-options.title")] + [:div.element-set-title-actions + (if has-value? + [:div.add-page {:on-click handle-toggle-visibility} (if (:hidden blur) i/eye-closed i/eye)]) + (if has-value? + [:div.add-page {:on-click handle-delete} i/minus] + [:div.add-page {:on-click handle-add} i/close])]] + + (when has-value? + [:div.element-set-content + [:& input-row {:label "Value" + :class "pixels" + :min 0 + :value (:value blur) + :on-change handle-change}]])])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/circle.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/circle.cljs index 3986c025c..b184f5518 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/circle.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/circle.cljs @@ -13,7 +13,8 @@ [app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] - [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]])) + [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] + [app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]])) (mf/defc options [{:keys [shape] :as props}] @@ -33,5 +34,6 @@ :type type :values stroke-values}] [:& shadow-menu {:ids ids - :type type - :values (select-keys shape [:shadow])}]])) + :values (select-keys shape [:shadow])}] + [:& blur-menu {:ids ids + :values (select-keys shape [:blur])}]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs index b1a56c0ef..d469acee2 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/fill.cljs @@ -63,7 +63,7 @@ (mf/deps ids) (fn [event] (st/emit! (dc/change-fill ids {:color cp/default-color - :opacity 1})))) + :opacity 1})))) on-delete (mf/use-callback diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs index 78642b1b9..5adaf5c97 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/frame.cljs @@ -23,7 +23,8 @@ [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.frame-grid :refer [frame-grid]] - [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]])) + [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] + [app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]])) (declare +size-presets+) @@ -204,16 +205,17 @@ (let [ids [(:id shape)] type (:type shape) stroke-values (select-keys shape stroke-attrs)] - [:* - [:& measures-menu {:shape shape}] - [:& fill-menu {:ids ids - :type type - :values (select-keys shape fill-attrs)}] - [:& stroke-menu {:ids ids + [:* + [:& measures-menu {:shape shape}] + [:& fill-menu {:ids ids :type type - :values stroke-values}] - [:& shadow-menu {:ids ids - :type type - :values (select-keys shape [:shadow])}] - [:& frame-grid {:shape shape}]])) + :values (select-keys shape fill-attrs)}] + [:& stroke-menu {:ids ids + :type type + :values stroke-values}] + [:& shadow-menu {:ids ids + :values (select-keys shape [:shadow])}] + [:& blur-menu {:ids ids + :values (select-keys shape [:blur])}] + [:& frame-grid {:shape shape}]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs index 8cba6c38c..0d6254a87 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/group.cljs @@ -18,6 +18,7 @@ [app.main.ui.workspace.sidebar.options.multiple :refer [get-shape-attrs]] [app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] + [app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs text-font-attrs @@ -138,6 +139,10 @@ [:& fill-menu {:ids ids-with-children :type type :values fill-values}] + + [:& blur-menu {:ids [id] + :values (select-keys shape [:blur])}] + (when-not (empty? other-ids) [:& stroke-menu {:ids other-ids :type type diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/image.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/image.cljs index ba9402205..d8733c7a9 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/image.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/image.cljs @@ -10,7 +10,9 @@ (ns app.main.ui.workspace.sidebar.options.image (:require [rumext.alpha :as mf] - [app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]])) + [app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] + [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] + [app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]])) (mf/defc options [{:keys [shape] :as props}] @@ -20,4 +22,9 @@ [:* [:& measures-menu {:ids ids :type type - :values measure-values}]])) + :values measure-values}] + [:& shadow-menu {:ids ids + :values (select-keys shape [:shadow])}] + + [:& blur-menu {:ids ids + :values (select-keys shape [:blur])}]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs index 9405ff784..0f01f9522 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/path.cljs @@ -13,7 +13,8 @@ [app.common.data :as d] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] - [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]])) + [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] + [app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]])) (mf/defc options [{:keys [shape] :as props}] @@ -28,5 +29,6 @@ :type type :values stroke-values}] [:& shadow-menu {:ids ids - :type type - :values (select-keys shape [:shadow])}]])) + :values (select-keys shape [:shadow])}] + [:& blur-menu {:ids ids + :values (select-keys shape [:blur])}]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rect.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rect.cljs index 8e43aeac1..a5c8c6fb1 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rect.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rect.cljs @@ -13,7 +13,8 @@ [app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] [app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]] - [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]])) + [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] + [app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]])) (mf/defc options {::mf/wrap [mf/memo]} @@ -30,10 +31,13 @@ [:& fill-menu {:ids ids :type type :values fill-values}] + [:& stroke-menu {:ids ids :type type :values stroke-values}] - [:& shadow-menu {:ids ids - :type type - :values (select-keys shape [:shadow])}]])) + [:& shadow-menu {:ids ids + :values (select-keys shape [:shadow])}] + + [:& blur-menu {:ids ids + :values (select-keys shape [:blur])}]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs index ceedd32f0..54756d4da 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs @@ -16,7 +16,6 @@ [app.main.store :as st] [app.main.ui.icons :as i] [app.main.ui.workspace.sidebar.options.common :refer [advanced-options]] - [app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]] [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [t]])) @@ -25,8 +24,7 @@ (let [id (uuid/next)] {:id id :style :drop-shadow - :color "#000000" - :opacity 0.2 + :color {:color "#000000" :opacity 0.2} :offset-x 4 :offset-y 4 :blur 4 @@ -183,7 +181,7 @@ :on-open #(st/emit! dwc/start-undo-transaction) :on-close #(st/emit! dwc/commit-undo-transaction)}]]]])) (mf/defc shadow-menu - [{:keys [ids type values] :as props}] + [{:keys [ids values] :as props}] (let [locale (i18n/use-locale) on-add-shadow diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs index 160c19322..cde0071ed 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/text.cljs @@ -25,6 +25,7 @@ [app.main.ui.workspace.sidebar.options.fill :refer [fill-menu]] [app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]] [app.main.ui.workspace.sidebar.options.typography :refer [typography-entry typography-options]] + [app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]] [app.util.dom :as dom] [app.main.fonts :as fonts] [app.util.i18n :as i18n :refer [tr t]] @@ -318,8 +319,9 @@ :values fill-values :editor editor}] [:& shadow-menu {:ids ids - :type type :values (select-keys shape [:shadow])}] + [:& blur-menu {:ids ids + :values (select-keys shape [:blur])}] [:& text-menu {:ids ids :type type :values text-values