mirror of
https://github.com/penpot/penpot.git
synced 2025-06-14 16:21:37 +02:00
✨ Adds support for drop shadow
This commit is contained in:
parent
23b53faac7
commit
64c0884eb9
15 changed files with 396 additions and 35 deletions
|
@ -48,6 +48,11 @@ $br-big: 8px;
|
|||
}
|
||||
}
|
||||
|
||||
.row-grid-2 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
|
|
@ -364,7 +364,8 @@ ul.slider-dots {
|
|||
position: relative;
|
||||
width: 75px;
|
||||
|
||||
&::after {
|
||||
&::after,
|
||||
.after {
|
||||
color: $color-gray-20;
|
||||
font-size: $fs12;
|
||||
height: 20px;
|
||||
|
@ -374,6 +375,11 @@ ul.slider-dots {
|
|||
width: 20px;
|
||||
}
|
||||
|
||||
.after {
|
||||
width: auto;
|
||||
right: 6px;
|
||||
}
|
||||
|
||||
// Input amounts
|
||||
|
||||
&.pixels {
|
||||
|
|
|
@ -468,8 +468,8 @@
|
|||
}
|
||||
|
||||
.color-th {
|
||||
background-color: $color-gray-10;
|
||||
border: 1px solid $color-gray-10;
|
||||
background-color: $color-gray-30;
|
||||
border: 1px solid $color-gray-30;
|
||||
border-radius: $br-small;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
|
@ -765,6 +765,7 @@
|
|||
top: 0;
|
||||
width: 100%;
|
||||
opacity: 0.4;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.element-set-content .advanced-options {
|
||||
|
@ -775,6 +776,7 @@
|
|||
position: relative;
|
||||
top: 2px;
|
||||
width: calc(100% + 16px);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.btn-options {
|
||||
|
@ -815,7 +817,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
.exports-options {
|
||||
.exports-options,
|
||||
.shadow-options{
|
||||
.element-set-options-group {
|
||||
justify-content: space-between;
|
||||
.delete-icon {
|
||||
|
@ -841,3 +844,35 @@
|
|||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.shadow-options .color-row-wrap {
|
||||
margin-left: 6px;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.element-set-actions-button {
|
||||
display: flex;
|
||||
min-width: 30px;
|
||||
min-height: 30px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: $color-gray-20;
|
||||
}
|
||||
|
||||
&:hover svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
.element-set-actions {
|
||||
display: flex;
|
||||
visibility: hidden;
|
||||
|
||||
}
|
||||
|
||||
.element-set-options-group:hover .element-set-actions {
|
||||
visibility: visible;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"The main logic for SVG export functionality."
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages-helpers :as cph]
|
||||
|
@ -18,6 +19,7 @@
|
|||
[app.common.geom.shapes :as geom]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.main.ui.shapes.filters :as filters]
|
||||
[app.main.ui.shapes.frame :as frame]
|
||||
[app.main.ui.shapes.circle :as circle]
|
||||
[app.main.ui.shapes.icon :as icon]
|
||||
|
@ -77,18 +79,21 @@
|
|||
frame-wrapper (mf/use-memo (mf/deps objects) #(frame-wrapper-factory objects))]
|
||||
(when (and shape (not (:hidden shape)))
|
||||
(let [shape (geom/transform-shape frame shape)
|
||||
opts #js {:shape shape}]
|
||||
(case (:type shape)
|
||||
:curve [:> path/path-shape opts]
|
||||
:text [:> text/text-shape opts]
|
||||
:icon [:> icon/icon-shape opts]
|
||||
:rect [:> rect/rect-shape opts]
|
||||
:path [:> path/path-shape opts]
|
||||
:image [:> image/image-shape opts]
|
||||
:circle [:> circle/circle-shape opts]
|
||||
:frame [:> frame-wrapper {:shape shape}]
|
||||
:group [:> group-wrapper {:shape shape :frame frame}]
|
||||
nil))))))
|
||||
opts #js {:shape shape}
|
||||
filter-id (filters/get-filter-id)]
|
||||
[:g {:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
(case (:type shape)
|
||||
:curve [:> path/path-shape opts]
|
||||
:text [:> text/text-shape opts]
|
||||
:icon [:> icon/icon-shape opts]
|
||||
:rect [:> rect/rect-shape opts]
|
||||
:path [:> path/path-shape opts]
|
||||
:image [:> image/image-shape opts]
|
||||
:circle [:> circle/circle-shape opts]
|
||||
:frame [:> frame-wrapper {:shape shape}]
|
||||
:group [:> group-wrapper {:shape shape :frame frame}]
|
||||
nil)])))))
|
||||
|
||||
(mf/defc page-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
(defn extract-style-attrs
|
||||
[shape]
|
||||
(let [stroke-style (:stroke-style shape :none)
|
||||
attrs #js {:fill (or (:fill-color shape) "transparent")
|
||||
attrs #js {;:filter (when (not= :frame (:type shape)) (str "url(#filter_" (:id shape) ")"))
|
||||
:fill (or (:fill-color shape) "transparent")
|
||||
:fillOpacity (:fill-opacity shape nil)
|
||||
:rx (:rx shape nil)
|
||||
:ry (:ry shape nil)}]
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.shapes.custom-stroke
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.geom.shapes :as geom]
|
||||
[app.util.object :as obj]))
|
||||
|
||||
|
@ -21,7 +22,8 @@
|
|||
(let [shape (unchecked-get props "shape")
|
||||
base-props (unchecked-get props "base-props")
|
||||
elem-name (unchecked-get props "elem-name")
|
||||
{:keys [id x y width height]} (geom/shape->rect-shape shape)
|
||||
{:keys [x y width height]} (geom/shape->rect-shape shape)
|
||||
id (uuid/next)
|
||||
stroke-style (:stroke-style shape :none)
|
||||
stroke-position (:stroke-alignment shape :center)]
|
||||
(cond
|
||||
|
|
77
frontend/src/app/main/ui/shapes/filters.cljs
Normal file
77
frontend/src/app/main/ui/shapes/filters.cljs
Normal file
|
@ -0,0 +1,77 @@
|
|||
;; 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.shapes.filters
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.util.color :as color]
|
||||
[app.common.math :as mth]
|
||||
[app.common.uuid :as uuid]))
|
||||
|
||||
(defn get-filter-id []
|
||||
(str "filter_" (uuid/next)))
|
||||
|
||||
(defn filter-str
|
||||
[filter-id shape]
|
||||
|
||||
(when (seq (:shadow shape))
|
||||
(str/fmt "url(#$0)" [filter-id])))
|
||||
|
||||
(mf/defc drop-shadow-filter
|
||||
[{:keys [filter-id filter shape]}]
|
||||
|
||||
(let [{:keys [x y width height]} (:selrect shape)
|
||||
{:keys [fid color opacity offset-x offset-y blur spread]} filter
|
||||
|
||||
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)
|
||||
filter-height (+ height (mth/abs offset-x) (* spread 2) (* blur 2) 10)
|
||||
|
||||
[r g b a] (color/hex->rgba color opacity)
|
||||
[r g b] [(/ r 255) (/ g 255) (/ b 255)]
|
||||
color-matrix (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])]
|
||||
[:filter {:id filter-id
|
||||
:x filter-x :y filter-y
|
||||
:width filter-width :height filter-height
|
||||
:filterUnits "userSpaceOnUse"
|
||||
:color-interpolation-filters "sRGB"}
|
||||
[:feFlood {:flood-opacity 0 :result "BackgroundImageFix"}]
|
||||
[: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"}]
|
||||
(when (> spread 0)
|
||||
[:feMorphology {:radius spread
|
||||
:operator "dilate"
|
||||
:in "SourceAlpha"
|
||||
:result "effect1_dropShadow"}])
|
||||
|
||||
[:feOffset {:dx offset-x :dy offset-y}]
|
||||
[:feGaussianBlur {:stdDeviation (/ blur 2)}]
|
||||
|
||||
[:feColorMatrix {:type "matrix" :values color-matrix}]
|
||||
|
||||
[:feBlend {:mode "normal"
|
||||
:in2 "BackgroundImageFix"
|
||||
:result "effect1_dropShadow"}]
|
||||
|
||||
[:feBlend {:mode "normal"
|
||||
:in "SourceGraphic"
|
||||
:in2 "effect1_dropShadow"
|
||||
:result "shape"}]]))
|
||||
|
||||
(mf/defc filters
|
||||
[{:keys [filter-id shape]}]
|
||||
[:defs
|
||||
(for [{:keys [id type hidden] :as filter} (:shadow shape)]
|
||||
(when (not hidden)
|
||||
[:& drop-shadow-filter {:key id
|
||||
:filter-id filter-id
|
||||
:filter filter
|
||||
:shape shape}]))])
|
|
@ -11,12 +11,15 @@
|
|||
"The main container for a frame in viewer mode"
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.data :as d]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages-helpers :as cph]
|
||||
[app.main.data.viewer :as dv]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.shapes.filters :as filters]
|
||||
[app.main.ui.shapes.circle :as circle]
|
||||
[app.main.ui.shapes.frame :as frame]
|
||||
[app.main.ui.shapes.group :as group]
|
||||
|
@ -53,10 +56,14 @@
|
|||
|
||||
on-mouse-down (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(on-mouse-down % shape))]
|
||||
#(on-mouse-down % shape))
|
||||
|
||||
filter-id (filters/get-filter-id)]
|
||||
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:cursor (when (:interactions shape) "pointer")}
|
||||
:cursor (when (:interactions shape) "pointer")
|
||||
:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
[:& component {:shape shape
|
||||
:frame frame
|
||||
:childs childs
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.keyboard :as kbd]
|
||||
[app.main.ui.shapes.filters :as filters]
|
||||
[app.util.dom :as dom]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
|
@ -69,9 +70,12 @@
|
|||
#(on-mouse-down % shape))
|
||||
on-context-menu (mf/use-callback
|
||||
(mf/deps shape)
|
||||
#(on-context-menu % shape))]
|
||||
#(on-context-menu % shape))
|
||||
filter-id (filters/get-filter-id)]
|
||||
[:g.shape {:on-mouse-down on-mouse-down
|
||||
:on-context-menu on-context-menu}
|
||||
:on-context-menu on-context-menu
|
||||
:filter (filters/filter-str filter-id shape)}
|
||||
[:& filters/filters {:filter-id filter-id :shape shape}]
|
||||
[:& component {:shape shape}]])))
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
;; 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.common
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[app.util.dom :as dom]))
|
||||
|
||||
(mf/defc advanced-options [{:keys [visible? on-close children]}]
|
||||
(let [handle-click (fn [event] (when on-close
|
||||
(do (dom/stop-propagation event)
|
||||
(on-close))))]
|
||||
(when visible?
|
||||
[:*
|
||||
[:div.focus-overlay {:on-click handle-click}]
|
||||
[:div.advanced-options {}
|
||||
children]])))
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
[app.main.data.workspace.grid :as dw]
|
||||
[app.util.geom.grid :as gg]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
[app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
|
@ -30,16 +31,6 @@
|
|||
(def workspace-saved-grids
|
||||
(l/derived :saved-grids refs/workspace-page-options))
|
||||
|
||||
(mf/defc advanced-options [{:keys [visible? on-close children]}]
|
||||
(when visible?
|
||||
[:*
|
||||
[:div.focus-overlay {:on-click #(when on-close
|
||||
(do
|
||||
(dom/stop-propagation %)
|
||||
(on-close)))}]
|
||||
[:div.advanced-options {}
|
||||
children]]))
|
||||
|
||||
(defn- get-size-options [locale]
|
||||
[{:value :auto :label (t locale "workspace.options.grid.auto")}
|
||||
:separator
|
||||
|
@ -254,3 +245,4 @@
|
|||
:on-remove (handle-remove-grid index)
|
||||
:on-save-grid handle-save-grid}])])]))
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
[rumext.alpha :as mf]
|
||||
[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.stroke :refer [stroke-attrs stroke-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]]))
|
||||
|
||||
(mf/defc options
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
@ -31,5 +32,8 @@
|
|||
:values fill-values}]
|
||||
[:& stroke-menu {:ids ids
|
||||
:type type
|
||||
:values stroke-values}]]))
|
||||
:values stroke-values}]
|
||||
[:& shadow-menu {:ids ids
|
||||
:type type
|
||||
:values (select-keys shape [:shadow])}]]))
|
||||
|
||||
|
|
195
frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs
Normal file
195
frontend/src/app/main/ui/workspace/sidebar/options/shadow.cljs
Normal file
|
@ -0,0 +1,195 @@
|
|||
;; 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.shadow
|
||||
(: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]))
|
||||
|
||||
(defn create-shadow []
|
||||
(let [id (uuid/next)]
|
||||
{:id id
|
||||
:style :drop-shadow
|
||||
:color "#000000"
|
||||
:opacity 0.2
|
||||
:offset-x 4
|
||||
:offset-y 4
|
||||
:blur 4
|
||||
:spread 0
|
||||
:hidden false}))
|
||||
|
||||
(defn valid-number? [value]
|
||||
(or (number? value) (not (js/isNaN (js/parseInt value)))))
|
||||
|
||||
(mf/defc shadow-entry
|
||||
[{:keys [ids index value]}]
|
||||
(let [open-shadow (mf/use-state false)
|
||||
|
||||
basic-offset-x-ref (mf/use-ref nil)
|
||||
basic-offset-y-ref (mf/use-ref nil)
|
||||
basic-blur-ref (mf/use-ref nil)
|
||||
|
||||
adv-offset-x-ref (mf/use-ref nil)
|
||||
adv-offset-y-ref (mf/use-ref nil)
|
||||
adv-blur-ref (mf/use-ref nil)
|
||||
adv-spread-ref (mf/use-ref nil)
|
||||
|
||||
remove-shadow-by-id
|
||||
(fn [values id] (->> values (filterv (fn [s] (not= (:id s) id)))))
|
||||
|
||||
|
||||
|
||||
on-remove-shadow
|
||||
(fn [id]
|
||||
(fn []
|
||||
(st/emit! (dwc/update-shapes ids #(update % :shadow remove-shadow-by-id id) ))))
|
||||
|
||||
select-text
|
||||
(fn [ref] (fn [event] (dom/select-text! (mf/ref-val ref))))
|
||||
|
||||
update-attr
|
||||
(fn update-attr
|
||||
([index attr valid?]
|
||||
(update-attr index attr valid? nil))
|
||||
|
||||
([index attr valid? update-ref]
|
||||
(fn [event]
|
||||
(let [value (dom/get-value (dom/get-target event))]
|
||||
(when (or (not valid?) (valid? value))
|
||||
(do
|
||||
(when update-ref
|
||||
(dom/set-value! (mf/ref-val update-ref) value))
|
||||
(st/emit! (dwc/update-shapes ids #(assoc-in % [:shadow index attr] (js/parseInt value 10))))))))))
|
||||
|
||||
update-color
|
||||
(fn [index]
|
||||
(fn [color opacity]
|
||||
(st/emit! (dwc/update-shapes
|
||||
ids
|
||||
#(-> %
|
||||
(assoc-in [:shadow index :color] color)
|
||||
(assoc-in [:shadow index :opacity] opacity))))))
|
||||
|
||||
toggle-visibility
|
||||
(fn [index]
|
||||
(fn []
|
||||
(st/emit! (dwc/update-shapes ids #(update-in % [:shadow index :hidden] not)))))]
|
||||
[:*
|
||||
[:div.element-set-options-group
|
||||
|
||||
[:div.element-set-actions-button
|
||||
{:on-click #(reset! open-shadow true)}
|
||||
i/actions]
|
||||
|
||||
[:input.input-text {:type "number"
|
||||
:ref basic-offset-x-ref
|
||||
:on-change (update-attr index :offset-x valid-number?)
|
||||
:on-click (select-text basic-offset-x-ref)
|
||||
:default-value (:offset-x value)}]
|
||||
[:input.input-text {:type "number"
|
||||
:ref basic-offset-y-ref
|
||||
:on-change (update-attr index :offset-y valid-number?)
|
||||
:on-click (select-text basic-offset-y-ref)
|
||||
:default-value (:offset-y value)}]
|
||||
[:input.input-text {:type "number"
|
||||
:ref basic-blur-ref
|
||||
:on-click (select-text basic-blur-ref)
|
||||
:on-change (update-attr index :blur valid-number?)
|
||||
:min 0
|
||||
:default-value (:blur value)}]
|
||||
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click (toggle-visibility index)}
|
||||
(if (:hidden value) i/eye-closed i/eye)]
|
||||
[:div.element-set-actions-button {:on-click (on-remove-shadow (:id value))}
|
||||
i/minus]]]
|
||||
|
||||
[:& advanced-options {:visible? @open-shadow
|
||||
:on-close #(reset! open-shadow false)}
|
||||
[:div.row-grid-2
|
||||
[:select.input-select
|
||||
[:option {:value ":drop-shadow"} "Drop shadow"]
|
||||
#_[:option {:value ":inner-shadow"} "Inner shadow"]]]
|
||||
|
||||
[:div.row-grid-2
|
||||
[:div.input-element
|
||||
[:input.input-text {:type "number"
|
||||
:ref adv-offset-x-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-click (select-text adv-offset-x-ref)
|
||||
:on-change (update-attr index :offset-x valid-number? basic-offset-x-ref)
|
||||
:default-value (:offset-x value)}]
|
||||
[:span.after "X"]]
|
||||
|
||||
[:div.input-element
|
||||
[:input.input-text {:type "number"
|
||||
:ref adv-offset-y-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-click (select-text adv-offset-y-ref)
|
||||
:on-change (update-attr index :offset-y valid-number? basic-offset-y-ref)
|
||||
:default-value (:offset-y value)}]
|
||||
[:span.after "Y"]]]
|
||||
|
||||
[:div.row-grid-2
|
||||
[:div.input-element
|
||||
[:input.input-text {:type "number"
|
||||
:ref adv-blur-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-click (select-text adv-blur-ref)
|
||||
:on-change (update-attr index :blur valid-number? basic-blur-ref)
|
||||
:min 0
|
||||
:default-value (:blur value)}]
|
||||
[:span.after "Blur"]]
|
||||
|
||||
[:div.input-element
|
||||
[:input.input-text {:type "number"
|
||||
:ref adv-spread-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-click (select-text adv-spread-ref)
|
||||
:on-change (update-attr index :spread valid-number?)
|
||||
:min 0
|
||||
:default-value (:spread value)}]
|
||||
[:span.after "Spread"]]]
|
||||
|
||||
[:div.color-row-wrap
|
||||
[:& color-row {:color {:value (:color value) :opacity (:opacity value)}
|
||||
:on-change (update-color index)
|
||||
: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}]
|
||||
|
||||
(.log js/console "values" (clj->js values))
|
||||
(let [on-add-shadow
|
||||
(fn []
|
||||
(st/emit! (dwc/update-shapes ids #(update % :shadow (fnil conj []) (create-shadow)) )))]
|
||||
[:div.element-set.shadow-options
|
||||
[:div.element-set-title
|
||||
[:span "Shadow"]
|
||||
[:div.add-page {:on-click on-add-shadow} i/close]]
|
||||
|
||||
(when (seq (:shadow values))
|
||||
[:div.element-set-content
|
||||
(for [[index {:keys [id] :as value}] (d/enumerate (:shadow values []))]
|
||||
[:& shadow-entry {:key (str "shadow-" id)
|
||||
:ids ids
|
||||
:value value
|
||||
:index index}])])]))
|
|
@ -70,7 +70,7 @@
|
|||
:group (t locale "workspace.options.group-stroke")
|
||||
(t locale "workspace.options.stroke"))
|
||||
|
||||
show-options (not= (or (:stroke-style values) :none) :none)
|
||||
show-options (not= (:stroke-style values :none) :none)
|
||||
|
||||
current-stroke-color {:value (:stroke-color values)
|
||||
:opacity (:stroke-opacity values)
|
||||
|
|
|
@ -103,6 +103,10 @@
|
|||
[node]
|
||||
(set! (.-value node) ""))
|
||||
|
||||
(defn set-value!
|
||||
[node value]
|
||||
(set! (.-value node) value))
|
||||
|
||||
(defn select-text!
|
||||
[node]
|
||||
(.select node))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue