Merge pull request #6674 from penpot/niwinz-develop-enhacements-3

 Refactor fills-menu and related components
This commit is contained in:
Andrey Antukh 2025-06-26 11:09:30 +02:00 committed by GitHub
commit f2c4a1eb1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 402 additions and 341 deletions

View file

@ -109,19 +109,27 @@
[fill] [fill]
(assoc fills position fill))))) (assoc fills position fill)))))
(defn transform-fill*
"A lower-level companion function for `transform-fill`"
[state ids transform options]
(let [page-id (or (get options :page-id)
(get state :current-page-id))
objects (dsh/lookup-page-objects state page-id)
[text-ids shape-ids]
(split-text-shapes objects ids)]
(rx/concat
(->> (rx/from text-ids)
(rx/map #(dwt/update-text-with-function % transform options)))
(rx/of (dwsh/update-shapes shape-ids transform options)))))
(defn transform-fill (defn transform-fill
"A low level function that creates a shape fill transformations stream" "A low level function that creates a shape fill transformations stream"
([state ids color transform] ([state ids color transform]
(transform-fill state ids color transform nil)) (transform-fill state ids color transform nil))
([state ids color transform options] ([state ids color transform options]
(let [page-id (or (get options :page-id) (let [fill
(get state :current-page-id))
objects (dsh/lookup-page-objects state page-id)
[text-ids shape-ids]
(split-text-shapes objects ids)
fill
(cond-> {} (cond-> {}
(contains? color :color) (contains? color :color)
(assoc :fill-color (:color color)) (assoc :fill-color (:color color))
@ -147,12 +155,10 @@
:always :always
(types.fill/check-fill)) (types.fill/check-fill))
transform-attrs #(transform % fill)] transform-attrs
#(transform % fill)]
(rx/concat (transform-fill* state ids transform-attrs options))))
(->> (rx/from text-ids)
(rx/map #(dwt/update-text-with-function % transform-attrs options)))
(rx/of (dwsh/update-shapes shape-ids transform-attrs options))))))
(defn swap-attrs [shape attr index new-index] (defn swap-attrs [shape attr index new-index]
(let [first (get-in shape [attr index]) (let [first (get-in shape [attr index])
@ -228,12 +234,40 @@
(transform-fill state ids color change-fn options) (transform-fill state ids color change-fn options)
(rx/of (dwu/commit-undo-transaction undo-id))))))))) (rx/of (dwu/commit-undo-transaction undo-id)))))))))
(defn remove-fill (defn detach-fill
([ids color position] (remove-fill ids color position nil)) ([ids position] (detach-fill ids position nil))
([ids color position options] ([ids position options]
(assert (types.color/check-color color) (assert (number? position)
"expected a valid color struct") "expected a valid number for position")
(assert (every? uuid? ids)
"expected a valid coll of uuid's")
(ptk/reify ::detach-fill
ptk/WatchEvent
(watch [_ state _]
(let [detach-fn
(fn [values index]
(update values index dissoc :fill-color-ref-id :fill-color-ref-file))
change-fn
;; The `node` can be a shape or a text content node
(fn [node]
(update node :fills detach-fn position))
undo-id
(js/Symbol)]
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id))
(transform-fill* state ids change-fn options)
(rx/of (dwu/commit-undo-transaction undo-id))))))))
(defn remove-fill
([ids position] (remove-fill ids position nil))
([ids position options]
(assert (number? position)
"expected a valid number for position")
(assert (every? uuid? ids) (assert (every? uuid? ids)
"expected a valid coll of uuid's") "expected a valid coll of uuid's")
@ -242,37 +276,38 @@
(watch [_ state _] (watch [_ state _]
(let [remove-fill-by-index (let [remove-fill-by-index
(fn [values index] (fn [values index]
(->> (d/enumerate values) (into []
(filterv (fn [[idx _]] (not= idx index))) (comp
(mapv second))) (map-indexed (fn [i o] (when (not= i index) o)))
(filter some?))
values))
change-fn change-fn
(fn [shape _] (update shape :fills remove-fill-by-index position)) ;; The `node` can be a shape or a text content node
(fn [node]
(update node :fills remove-fill-by-index position))
undo-id undo-id
(js/Symbol)] (js/Symbol)]
(rx/concat (rx/concat
(rx/of (dwu/start-undo-transaction undo-id)) (rx/of (dwu/start-undo-transaction undo-id))
(transform-fill state ids color change-fn options) (transform-fill* state ids change-fn options)
(rx/of (dwu/commit-undo-transaction undo-id)))))))) (rx/of (dwu/commit-undo-transaction undo-id))))))))
(defn remove-all-fills (defn remove-all-fills
([ids color] (remove-all-fills ids color nil)) ([ids] (remove-all-fills ids nil))
([ids color options] ([ids options]
(assert (types.color/check-color color) "expected a valid color struct")
(assert (every? uuid? ids) "expected a valid coll of uuid's") (assert (every? uuid? ids) "expected a valid coll of uuid's")
(ptk/reify ::remove-all-fills (ptk/reify ::remove-all-fills
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [change-fn (fn [shape _] (assoc shape :fills [])) (let [change-fn (fn [node] (assoc node :fills []))
undo-id (js/Symbol)] undo-id (js/Symbol)]
(rx/concat (rx/concat
(rx/of (dwu/start-undo-transaction undo-id)) (rx/of (dwu/start-undo-transaction undo-id))
(transform-fill state ids color change-fn options) (transform-fill* state ids change-fn options)
(rx/of (dwu/commit-undo-transaction undo-id)))))))) (rx/of (dwu/commit-undo-transaction undo-id))))))))
(defn change-hide-fill-on-export (defn change-hide-fill-on-export
@ -743,7 +778,8 @@
[{:keys [type current-color stops gradient opacity] :as state}] [{:keys [type current-color stops gradient opacity] :as state}]
(cond (cond
(= type :color) (= type :color)
(clear-color-components current-color) (-> (clear-color-components current-color)
(dissoc :offset))
(= type :image) (= type :image)
(clear-image-components current-color) (clear-image-components current-color)

View file

@ -8,32 +8,27 @@
(:require (:require
[app.common.colors :as cc] [app.common.colors :as cc]
[app.common.data :as d] [app.common.data :as d]
[app.main.ui.hooks :as hooks]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.globals :as globals] [app.util.globals :as globals]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd] [app.util.keyboard :as kbd]
[app.util.object :as obj]
[goog.events :as events] [goog.events :as events]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(defn clean-color (defn- get-clean-color
[value] [node]
(-> value (-> (dom/get-value node)
(cc/expand-hex) (cc/expand-hex)
(cc/parse) (cc/parse)
(cc/prepend-hash))) (cc/prepend-hash)))
(mf/defc color-input* (mf/defc color-input*
{::mf/wrap-props false {::mf/forward-ref true}
::mf/forward-ref true} [{:keys [value on-change on-blur on-focus select-on-focus class aria-label] :rest props} external-ref]
[props external-ref] (let [select-on-focus? (d/nilv select-on-focus true)
(let [value (obj/get props "value") class (d/nilv class "color-input")
on-change (obj/get props "onChange") aria-label (or aria-label (tr "inspect.attributes.color"))
on-blur (obj/get props "onBlur")
on-focus (obj/get props "onFocus")
select-on-focus? (d/nilv (unchecked-get props "selectOnFocus") true)
class (d/nilv (unchecked-get props "className") "color-input")
aria-label (d/nilv (unchecked-get props "aria-label") (tr "inspect.attributes.color"))
;; We need a ref pointing to the input dom element, but the user ;; We need a ref pointing to the input dom element, but the user
;; of this component may provide one (that is forwarded here). ;; of this component may provide one (that is forwarded here).
@ -42,25 +37,22 @@
ref (or external-ref local-ref) ref (or external-ref local-ref)
;; We need to store the handle-blur ref so we can call it on unmount ;; We need to store the handle-blur ref so we can call it on unmount
handle-blur-ref (mf/use-ref nil)
dirty-ref (mf/use-ref false) dirty-ref (mf/use-ref false)
parse-value parse-value
(mf/use-fn (mf/use-fn
(mf/deps ref)
(fn [] (fn []
(let [input-node (mf/ref-val ref)] (let [input-node (mf/ref-val ref)]
(try (try
(let [new-value (clean-color (dom/get-value input-node))] (let [value (get-clean-color input-node)]
(dom/set-validity! input-node "") (dom/set-validity! input-node "")
new-value) value)
(catch :default _e (catch :default _e
(dom/set-validity! input-node (tr "errors.invalid-color")) (dom/set-validity! input-node (tr "errors.invalid-color"))
nil))))) nil)))))
update-input update-input
(mf/use-fn (mf/use-fn
(mf/deps ref)
(fn [new-value] (fn [new-value]
(let [input-node (mf/ref-val ref)] (let [input-node (mf/ref-val ref)]
(dom/set-value! input-node (cc/remove-hash new-value))))) (dom/set-value! input-node (cc/remove-hash new-value)))))
@ -71,8 +63,7 @@
(fn [new-value] (fn [new-value]
(mf/set-ref-val! dirty-ref false) (mf/set-ref-val! dirty-ref false)
(when (and new-value (not= (cc/remove-hash new-value) value)) (when (and new-value (not= (cc/remove-hash new-value) value))
(when on-change (when on-change (on-change new-value))
(on-change new-value))
(update-input new-value)))) (update-input new-value))))
handle-key-down handle-key-down
@ -80,38 +71,27 @@
(mf/deps apply-value update-input) (mf/deps apply-value update-input)
(fn [event] (fn [event]
(mf/set-ref-val! dirty-ref true) (mf/set-ref-val! dirty-ref true)
(let [enter? (kbd/enter? event) (let [input-node (mf/ref-val ref)]
esc? (kbd/esc? event) (cond
input-node (mf/ref-val ref)] (kbd/enter? event)
(when enter? (let [value (parse-value)]
(dom/prevent-default event) (update-input value)
(let [new-value (parse-value)] (dom/prevent-default event)
(apply-value new-value) (dom/blur! input-node))
(dom/blur! input-node)))
(when esc?
(dom/prevent-default event)
(update-input value)
(dom/blur! input-node)))))
handle-blur (kbd/esc? event)
(mf/use-fn (do
(mf/deps parse-value apply-value update-input) (update-input value)
(fn [_] (dom/prevent-default event)
(let [new-value (parse-value)] (dom/blur! input-node))))))
(when on-blur
(on-blur))
(if new-value
(apply-value new-value)
(update-input value)))))
on-click on-click
(mf/use-fn (mf/use-fn
(fn [event] (fn [event]
(let [target (dom/get-target event)] (let [target (dom/get-target event)
(when (some? ref) current (mf/ref-val ref)]
(let [current (mf/ref-val ref)] (when (and (some? current) (not (.contains current target)))
(when (and (some? current) (not (.contains current target))) (dom/blur! current)))))
(dom/blur! current)))))))
on-mouse-up on-mouse-up
(mf/use-fn (mf/use-fn
@ -122,57 +102,53 @@
(mf/use-fn (mf/use-fn
(fn [event] (fn [event]
(let [target (dom/get-target event)] (let [target (dom/get-target event)]
(when on-focus (when on-focus (on-focus))
(on-focus event))
(when select-on-focus? (when select-on-focus?
(-> event (dom/get-target) (.select)) (-> event (dom/get-target) (.select))
;; In webkit browsers the mouseup event will be called after the on-focus causing and unselect ;; In webkit browsers the mouseup event will be called after the on-focus causing and unselect
(.addEventListener target "mouseup" on-mouse-up #js {"once" true}))))) (.addEventListener target "mouseup" on-mouse-up #js {:once true})))))
props (-> (obj/clone props) handle-blur
(obj/unset! "selectOnFocus") (mf/use-fn
(obj/set! "value" mf/undefined) (mf/deps parse-value apply-value update-input)
(obj/set! "onChange" mf/undefined) (fn [_]
(obj/set! "className" class) (let [new-value (parse-value)]
(obj/set! "type" "text") (if new-value
(obj/set! "ref" ref) (apply-value new-value)
(obj/set! "aria-label" aria-label) (update-input value))
;; (obj/set! "list" list-id) (when on-blur
(obj/set! "defaultValue" value) (on-blur)))))
(obj/set! "onKeyDown" handle-key-down)
(obj/set! "onBlur" handle-blur)
(obj/set! "onFocus" handle-focus))]
(mf/use-effect handle-blur
(mf/deps value) (hooks/use-ref-callback handle-blur)
(fn []
(when-let [node (mf/ref-val ref)]
(dom/set-value! node value))))
(mf/use-effect props
(mf/deps handle-blur) (mf/spread-props props
(fn [] {:class class
(mf/set-ref-val! handle-blur-ref {:fn handle-blur}))) :type "text"
:ref ref
:aria-label aria-label
:default-value value
:on-key-down handle-key-down
:on-blur handle-blur
:on-focus handle-focus})]
(mf/use-layout-effect (mf/with-effect [value]
(fn [] (when-let [node (mf/ref-val ref)]
#(when (mf/ref-val dirty-ref) (dom/set-value! node value)))
(let [handle-blur (:fn (mf/ref-val handle-blur-ref))]
(handle-blur)))))
(mf/use-layout-effect (mf/with-layout-effect []
(fn [] ;; UNMOUNT: we use layout-effect because we still need the dom
(let [keys [(events/listen globals/window "pointerdown" on-click) ;; node to be present on the refs, for properly execute the
(events/listen globals/window "click" on-click)]] ;; on-blur event handler
#(doseq [key keys] #(when (mf/ref-val dirty-ref) (handle-blur)))
(events/unlistenByKey key)))))
[:* (mf/with-layout-effect []
[:> :input props] (let [key1 (events/listen globals/window "pointerdown" on-click)
;; FIXME: this causes some weird interactions because of using apply-value key2 (events/listen globals/window "click" on-click)]
;; [:datalist {:id list-id} #(do
;; (for [color-name cc/color-names] (events/unlistenByKey key1)
;; [:option color-name])] (events/unlistenByKey key2))))
]))
[:> :input props]))

View file

@ -7,15 +7,14 @@
(ns app.main.ui.components.reorder-handler (ns app.main.ui.components.reorder-handler
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as ic] [app.main.ui.ds.foundations.assets.icon :as ic]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(mf/defc reorder-handler (mf/defc reorder-handler*
{::mf/forward-ref true} [{:keys [ref]}]
[_ ref]
[:* [:*
[:div {:ref ref :class (stl/css :reorder)} [:div {:ref ref :class (stl/css :reorder)}
[:> icon* [:> ic/icon*
{:icon-id ic/reorder {:icon-id ic/reorder
:class (stl/css :reorder-icon) :class (stl/css :reorder-icon)
:aria-hidden true}]] :aria-hidden true}]]

View file

@ -15,7 +15,7 @@
[app.config :as cfg] [app.config :as cfg]
[app.main.features :as features] [app.main.features :as features]
[app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.reorder-handler :refer [reorder-handler]] [app.main.ui.components.reorder-handler :refer [reorder-handler*]]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.formats :as fmt] [app.main.ui.formats :as fmt]
@ -139,7 +139,7 @@
:dnd-over-top (= (:over dprops) :top) :dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))} :dnd-over-bot (= (:over dprops) :bot))}
[:& reorder-handler {:ref dref}] [:> reorder-handler* {:ref dref}]
[:div {:class (stl/css :offset-input-wrapper)} [:div {:class (stl/css :offset-input-wrapper)}
[:span {:class (stl/css :icon-text)} "%"] [:span {:class (stl/css :icon-text)} "%"]

View file

@ -7,8 +7,6 @@
(ns app.main.ui.workspace.sidebar.options.menus.fill (ns app.main.ui.workspace.sidebar.options.menus.fill
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.colors :as clr]
[app.common.data :as d]
[app.common.types.color :as ctc] [app.common.types.color :as ctc]
[app.common.types.fill :as types.fill] [app.common.types.fill :as types.fill]
[app.common.types.shape.attrs :refer [default-color]] [app.common.types.shape.attrs :refer [default-color]]
@ -24,127 +22,162 @@
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
;; FIXME:revisit this
(def fill-attrs (def fill-attrs
[:fills #{:fills :hide-fill-on-export})
:fill-color
:fill-opacity
:fill-color-ref-id
:fill-color-ref-file
:fill-color-gradient
:hide-fill-on-export])
(def fill-attrs-shape (def ^:private
(conj fill-attrs :hide-fill-on-export)) xf:take-max-fills
(take types.fill/MAX-FILLS))
(defn color-values (def ^:private
[color] xf:enumerate
{:color (:fill-color color) (map-indexed
:opacity (:fill-opacity color) (fn [index item]
:id (:fill-color-ref-id color) (let [color (ctc/fill->color item)]
:file-id (:fill-color-ref-file color) (with-meta item {:index index :color color})))))
:gradient (:fill-color-gradient color)})
(mf/defc fill-menu (def ^:private ^boolean binary-fills-enabled?
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]} (contains? cfg/flags :frontend-binary-fills))
[{:keys [ids type values] :as props}]
(let [label (case type
:multiple (tr "workspace.options.selection-fill")
:group (tr "workspace.options.group-fill")
(tr "workspace.options.fill"))
;; Excluding nil values (def ^:private
values (d/without-nils values) xf:process-fills
fills (if (contains? cfg/flags :frontend-binary-fills) (if binary-fills-enabled?
(take types.fill/MAX-FILLS (d/nilv (:fills values) [])) (comp xf:take-max-fills xf:enumerate)
(:fills values)) xf:enumerate))
has-fills? (or (= :multiple fills) (some? (seq fills)))
can-add-fills? (if (contains? cfg/flags :frontend-binary-fills)
(and (not (= :multiple fills))
(< (count fills) types.fill/MAX-FILLS))
(not (= :multiple fills)))
state* (mf/use-state has-fills?) (defn- prepare-fills
open? (deref state*) "Internal helper hook that prepares fills"
[fills]
(if (= :multiple fills)
fills
(->> fills
(into [] xf:process-fills)
(not-empty))))
toggle-content (mf/use-fn #(swap! state* not)) (defn- check-props
"A fills-menu specific memoize check function that only checks if
specific values are changed on provided props. This allows pass the
whole shape as values without adding additional rerenders when other
shape properties changes."
[n-props o-props]
(and (identical? (unchecked-get n-props "ids")
(unchecked-get o-props "ids"))
(let [o-vals (unchecked-get o-props "values")
n-vals (unchecked-get n-props "values")
o-fills (get o-vals :fills)
n-fills (get n-vals :fills)
o-hide (get o-vals :hide-fill-on-export)
n-hide (get n-vals :hide-fill-on-export)]
(and (identical? o-hide n-hide)
(identical? o-fills n-fills)))))
open-content (mf/use-fn #(reset! state* true)) (mf/defc fill-menu*
{::mf/wrap [#(mf/memo' % check-props)]}
[{:keys [ids type values]}]
(let [fills (get values :fills)
hide-on-export (get values :hide-fill-on-export false)
close-content (mf/use-fn #(reset! state* false)) ^boolean
multiple? (= :multiple fills)
hide-fill-on-export? (:hide-fill-on-export values false) fills (mf/with-memo [fills]
(prepare-fills fills))
checkbox-ref (mf/use-ref) has-fills? (or multiple? (some? fills))
empty-fills? (and (not multiple?)
(= 0 (count fills)))
open* (mf/use-state has-fills?)
open? (deref open*)
toggle-content (mf/use-fn #(swap! open* not))
open-content (mf/use-fn #(reset! open* true))
close-content (mf/use-fn #(reset! open* false))
checkbox-ref (mf/use-ref)
can-add-fills?
(if binary-fills-enabled?
(and (not multiple?)
(< (count fills) types.fill/MAX-FILLS))
(not ^boolean multiple?))
label
(case type
:multiple (tr "workspace.options.selection-fill")
:group (tr "workspace.options.group-fill")
(tr "workspace.options.fill"))
on-add on-add
(mf/use-fn (mf/use-fn
(mf/deps ids fills) (mf/deps ids multiple? empty-fills?)
(fn [_] (fn [_]
(when can-add-fills? (when can-add-fills?
(st/emit! (dc/add-fill ids {:color default-color (st/emit! (dc/add-fill ids {:color default-color
:opacity 1})) :opacity 1}))
(when (or (= :multiple fills) (when (or multiple? empty-fills?)
(not (some? (seq fills))))
(open-content))))) (open-content)))))
on-change on-change
(fn [index] (mf/use-fn
(fn [color] (mf/deps ids)
(let [color (select-keys color ctc/color-attrs)] (fn [color index]
(st/emit! (dc/change-fill ids color index))))) (let [color (select-keys color ctc/color-attrs)]
(st/emit! (dc/change-fill ids color index)))))
on-reorder on-reorder
(fn [new-index] (mf/use-fn
(fn [index] (mf/deps ids)
(st/emit! (dc/reorder-fills ids index new-index)))) (fn [new-index index]
(st/emit! (dc/reorder-fills ids index new-index))))
on-remove on-remove
(fn [index] (mf/use-fn
(fn [] (mf/deps ids multiple? empty-fills?)
(st/emit! (dc/remove-fill ids {:color default-color (fn [index _event]
:opacity 1} index)) (st/emit! (dc/remove-fill ids index))
(when (or (= :multiple fills) (when (or multiple? empty-fills?)
(= 0 (count (seq fills)))) (close-content))))
(close-content))))
on-remove-all on-remove-all
(fn [_] (mf/use-fn
(st/emit! (dc/remove-all-fills ids {:color clr/black (mf/deps ids)
:opacity 1}))) #(st/emit! (dc/remove-all-fills ids)))
on-detach on-detach
(mf/use-fn (mf/use-fn
(mf/deps ids) (mf/deps ids)
(fn [index] (fn [index _event]
(fn [color] (st/emit! (dc/detach-fill ids index))))
(let [color (dissoc color :ref-id :ref-file)]
(st/emit! (dc/change-fill ids color index))))))
on-change-show-fill-on-export on-change-show-on-export
(mf/use-fn (mf/use-fn
(mf/deps ids) (mf/deps ids)
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/checked?)] (let [value (-> event dom/get-target dom/checked?)]
(st/emit! (dc/change-hide-fill-on-export ids (not value)))))) (st/emit! (dc/change-hide-fill-on-export ids (not value))))))
disable-drag (mf/use-state false) disable-drag*
(mf/use-state false)
on-focus (fn [_] disable-drag?
(reset! disable-drag true)) (deref disable-drag*)
on-blur (fn [_] on-focus
(reset! disable-drag false))] (mf/use-fn
#(reset! disable-drag* true))
(mf/use-layout-effect on-blur
(mf/deps hide-fill-on-export?) (mf/use-fn #(reset! disable-drag* false))]
#(let [checkbox (mf/ref-val checkbox-ref)]
(when checkbox (mf/with-layout-effect [hide-on-export]
;; Note that the "indeterminate" attribute only may be set by code, not as a static attribute. (when-let [checkbox (mf/ref-val checkbox-ref)]
;; See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#attr-indeterminate ;; Note that the "indeterminate" attribute only may be set by code, not as a static attribute.
(if (= hide-fill-on-export? :multiple) ;; See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#attr-indeterminate
(dom/set-attribute! checkbox "indeterminate" true) (if (= hide-on-export :multiple)
(dom/remove-attribute! checkbox "indeterminate"))))) (dom/set-attribute! checkbox "indeterminate" true)
(dom/remove-attribute! checkbox "indeterminate"))))
[:div {:class (stl/css :element-set)} [:div {:class (stl/css :element-set)}
[:div {:class (stl/css :element-title)} [:div {:class (stl/css :element-title)}
@ -174,34 +207,38 @@
:on-click on-remove-all :on-click on-remove-all
:icon "remove"}]] :icon "remove"}]]
(seq fills) (some? fills)
[:& h/sortable-container {} [:& h/sortable-container {}
(for [[index value] (d/enumerate fills)] (for [value fills]
[:> color-row* {:color (ctc/fill->color value) (let [mdata (meta value)
:key index index (get mdata :index)
:index index color (get mdata :color)]
:title (tr "workspace.options.fill") [:> color-row* {:color color
:on-change (on-change index) :key index
:on-reorder (on-reorder index) :index index
:on-detach (on-detach index) :title (tr "workspace.options.fill")
:on-remove (on-remove index) :on-change on-change
:disable-drag disable-drag :on-reorder on-reorder
:on-focus on-focus :on-detach on-detach
:select-on-focus (not @disable-drag) :on-remove on-remove
:on-blur on-blur}])]) :disable-drag disable-drag?
:on-focus on-focus
:select-on-focus (not disable-drag?)
:on-blur on-blur}]))])
(when (or (= type :frame) (when (or (= type :frame)
(and (= type :multiple) (some? (:hide-fill-on-export values)))) (and (= type :multiple)
(some? hide-on-export)))
[:div {:class (stl/css :checkbox)} [:div {:class (stl/css :checkbox)}
[:label {:for "show-fill-on-export" [:label {:for "show-fill-on-export"
:class (stl/css-case :global/checked (not hide-fill-on-export?))} :class (stl/css-case :global/checked (not hide-on-export))}
[:span {:class (stl/css-case :check-mark true [:span {:class (stl/css-case :check-mark true
:checked (not hide-fill-on-export?))} :checked (not hide-on-export))}
(when (not hide-fill-on-export?) (when (not hide-on-export)
i/status-tick)] i/status-tick)]
(tr "workspace.options.show-fill-on-export") (tr "workspace.options.show-fill-on-export")
[:input {:type "checkbox" [:input {:type "checkbox"
:id "show-fill-on-export" :id "show-fill-on-export"
:ref checkbox-ref :ref checkbox-ref
:checked (not hide-fill-on-export?) :checked (not hide-on-export)
:on-change on-change-show-fill-on-export}]]])])])) :on-change on-change-show-on-export}]]])])]))

View file

@ -17,7 +17,7 @@
[app.main.data.workspace.undo :as dwu] [app.main.data.workspace.undo :as dwu]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.reorder-handler :refer [reorder-handler]] [app.main.ui.components.reorder-handler :refer [reorder-handler*]]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.components.title-bar :refer [title-bar]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
@ -127,7 +127,7 @@
:dnd-over-top (= (:over dprops) :top) :dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))} :dnd-over-bot (= (:over dprops) :bot))}
(when (some? on-reorder) (when (some? on-reorder)
[:& reorder-handler {:ref dref}]) [:> reorder-handler* {:ref dref}])
[:* [:*
[:div {:class (stl/css :basic-options)} [:div {:class (stl/css :basic-options)}

View file

@ -19,7 +19,7 @@
[app.main.ui.components.color-bullet :as cb] [app.main.ui.components.color-bullet :as cb]
[app.main.ui.components.color-input :refer [color-input*]] [app.main.ui.components.color-input :refer [color-input*]]
[app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.reorder-handler :refer [reorder-handler]] [app.main.ui.components.reorder-handler :refer [reorder-handler*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.formats :as fmt] [app.main.ui.formats :as fmt]
[app.main.ui.hooks :as h] [app.main.ui.hooks :as h]
@ -50,7 +50,6 @@
on-change on-reorder on-detach on-open on-close on-remove on-change on-reorder on-detach on-open on-close on-remove
disable-drag on-focus on-blur select-only select-on-focus]}] disable-drag on-focus on-blur select-only select-on-focus]}]
(let [libraries (mf/deref refs/files) (let [libraries (mf/deref refs/files)
hover-detach (mf/use-state false)
on-change (h/use-ref-callback on-change) on-change (h/use-ref-callback on-change)
file-id (or (:ref-file color) (:file-id color)) file-id (or (:ref-file color) (:file-id color))
@ -76,21 +75,21 @@
(not library-color?) (not library-color?)
(not disable-opacity)) (not disable-opacity))
on-focus on-focus'
(mf/use-fn (mf/use-fn
(mf/deps on-focus) (mf/deps on-focus)
(fn [event] (fn [_]
(reset! editing-text* true) (reset! editing-text* true)
(when on-focus (when on-focus
(on-focus event)))) (on-focus))))
on-blur on-blur'
(mf/use-fn (mf/use-fn
(mf/deps on-blur) (mf/deps on-blur)
(fn [event] (fn [_]
(reset! editing-text* false) (reset! editing-text* false)
(when on-blur (when on-blur
(on-blur event)))) (on-blur))))
parse-color parse-color
(mf/use-fn (mf/use-fn
@ -99,10 +98,10 @@
detach-value detach-value
(mf/use-fn (mf/use-fn
(mf/deps on-detach color) (mf/deps on-detach index)
(fn [] (fn [_]
(when on-detach (when on-detach
(on-detach color)))) (on-detach index))))
handle-select handle-select
(mf/use-fn (mf/use-fn
@ -110,27 +109,27 @@
(fn [] (fn []
(select-only color))) (select-only color)))
handle-value-change on-color-change
(mf/use-fn (mf/use-fn
(mf/deps color on-change) (mf/deps color index on-change)
(fn [value] (fn [value _event]
(let [color (-> color (let [color (-> color
(assoc :color value) (assoc :color value)
(dissoc :gradient) (dissoc :gradient)
(select-keys types.color/color-attrs))] (select-keys types.color/color-attrs))]
(st/emit! (dwc/add-recent-color color) (st/emit! (dwc/add-recent-color color)
(on-change color))))) (on-change color index)))))
handle-opacity-change on-opacity-change
(mf/use-fn (mf/use-fn
(mf/deps color on-change) (mf/deps color index on-change)
(fn [value] (fn [value]
(let [color (-> color (let [color (-> color
(assoc :opacity (/ value 100)) (assoc :opacity (/ value 100))
(dissoc :ref-id :ref-file) (dissoc :ref-id :ref-file)
(select-keys types.color/color-attrs))] (select-keys types.color/color-attrs))]
(st/emit! (dwc/add-recent-color color) (st/emit! (dwc/add-recent-color color)
(on-change color))))) (on-change color index)))))
handle-click-color handle-click-color
(mf/use-fn (mf/use-fn
@ -157,7 +156,7 @@
:disable-opacity disable-opacity :disable-opacity disable-opacity
:disable-image disable-image :disable-image disable-image
;; on-change second parameter means if the source is the color-picker ;; on-change second parameter means if the source is the color-picker
:on-change #(on-change % true) :on-change #(on-change % index)
:on-close (fn [value opacity id file-id] :on-close (fn [value opacity id file-id]
(when on-close (when on-close
(on-close value opacity id file-id))) (on-close value opacity id file-id)))
@ -169,40 +168,51 @@
(when-not disable-picker (when-not disable-picker
(modal/show! :colorpicker props))))) (modal/show! :colorpicker props)))))
prev-color (h/use-previous color) on-remove'
(mf/use-fn
(mf/deps index)
(fn [_]
(when on-remove
(on-remove index))))
prev-color
(h/use-previous color)
on-drop on-drop
(mf/use-fn (mf/use-fn
(mf/deps on-reorder) (mf/deps on-reorder index)
(fn [_ data] (fn [_ data]
(on-reorder (:index data)))) (on-reorder index (:index data))))
[dprops dref]
(if (some? on-reorder)
(h/use-sortable
:data-type "penpot/color-row"
:on-drop on-drop
:disabled disable-drag
:detect-center? false
:data {:id (str "color-row-" index)
:index index
:name (str "Color row" index)})
[nil nil])
row-class
(stl/css-case :color-data true
:hidden hidden
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot))]
[dprops dref] (if (some? on-reorder)
(h/use-sortable
:data-type "penpot/color-row"
:on-drop on-drop
:disabled @disable-drag
:detect-center? false
:data {:id (str "color-row-" index)
:index index
:name (str "Color row" index)})
[nil nil])]
(mf/with-effect [color prev-color disable-picker] (mf/with-effect [color prev-color disable-picker]
(when (and (not disable-picker) (not= prev-color color)) (when (and (not disable-picker) (not= prev-color color))
(modal/update-props! :colorpicker {:data (parse-color color)}))) (modal/update-props! :colorpicker {:data (parse-color color)})))
[:div {:class (dm/str [:div {:class [class row-class]}
class
(stl/css-case
:color-data true
:hidden hidden
:dnd-over-top (= (:over dprops) :top)
:dnd-over-bot (= (:over dprops) :bot)))}
;; Drag handler ;; Drag handler
(when (some? on-reorder) (when (some? on-reorder)
[:& reorder-handler {:ref dref}]) [:> reorder-handler* {:ref dref}])
[:div {:class (stl/css :color-info)} [:div {:class (stl/css :color-info)}
[:div {:class (stl/css-case :color-name-wrapper true [:div {:class (stl/css-case :color-name-wrapper true
@ -228,22 +238,18 @@
[:button [:button
{:class (stl/css :detach-btn) {:class (stl/css :detach-btn)
:title (tr "settings.detach") :title (tr "settings.detach")
:on-pointer-enter #(reset! hover-detach true)
:on-pointer-leave #(reset! hover-detach false)
:on-click detach-value} :on-click detach-value}
detach-icon])] detach-icon])]
;; Rendering a gradient ;; Rendering a gradient
gradient-color? gradient-color?
[:* [:div {:class (stl/css :color-name)}
[:div {:class (stl/css :color-name)} (uc/gradient-type->string (dm/get-in color [:gradient :type]))]
(uc/gradient-type->string (dm/get-in color [:gradient :type]))]]
;; Rendering an image ;; Rendering an image
image-color? image-color?
[:* [:div {:class (stl/css :color-name)}
[:div {:class (stl/css :color-name)} (tr "media.image")]
(tr "media.image")]]
;; Rendering a plain color ;; Rendering a plain color
:else :else
@ -252,22 +258,22 @@
"" ""
(-> color :color cc/remove-hash)) (-> color :color cc/remove-hash))
:placeholder (tr "settings.multiple") :placeholder (tr "settings.multiple")
:data-index index
:class (stl/css :color-input) :class (stl/css :color-input)
:on-focus on-focus :on-focus on-focus'
:on-blur on-blur :on-blur on-blur'
:on-change handle-value-change}]])] :on-change on-color-change}]])]
(when opacity? (when opacity?
[:div {:class (stl/css :opacity-element-wrapper)} [:div {:class (stl/css :opacity-element-wrapper)}
[:span {:class (stl/css :icon-text)} [:span {:class (stl/css :icon-text)} "%"]
"%"]
[:> numeric-input* {:value (-> color :opacity opacity->string) [:> numeric-input* {:value (-> color :opacity opacity->string)
:className (stl/css :opacity-input) :class (stl/css :opacity-input)
:placeholder "--" :placeholder "--"
:select-on-focus select-on-focus :select-on-focus select-on-focus
:on-focus on-focus :on-focus on-focus'
:on-blur on-blur :on-blur on-blur'
:on-change handle-opacity-change :on-change on-opacity-change
:data-testid "opacity-input" :data-testid "opacity-input"
:default 100 :default 100
:min 0 :min 0
@ -276,7 +282,7 @@
(when (some? on-remove) (when (some? on-remove)
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"
:aria-label (tr "settings.remove-color") :aria-label (tr "settings.remove-color")
:on-click on-remove :on-click on-remove'
:icon "remove"}]) :icon "remove"}])
(when select-only (when select-only
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"

View file

@ -10,7 +10,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.types.color :as ctc] [app.common.types.color :as ctc]
[app.main.ui.components.numeric-input :refer [numeric-input*]] [app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.reorder-handler :refer [reorder-handler]] [app.main.ui.components.reorder-handler :refer [reorder-handler*]]
[app.main.ui.components.select :refer [select]] [app.main.ui.components.select :refer [select]]
[app.main.ui.hooks :as h] [app.main.ui.hooks :as h]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
@ -145,7 +145,7 @@
:dnd-over-bot (= (:over dprops) :bot))} :dnd-over-bot (= (:over dprops) :bot))}
(when (some? on-reorder) (when (some? on-reorder)
[:& reorder-handler {:ref dref}]) [:> reorder-handler* {:ref dref}])
;; Stroke Color ;; Stroke Color
;; FIXME: memorize stroke color ;; FIXME: memorize stroke color

View file

@ -11,7 +11,7 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
@ -82,9 +82,11 @@
[:& constraints-menu {:ids ids [:& constraints-menu {:ids ids
:values constraint-values}]) :values constraint-values}])
[:& fill-menu {:ids ids [:> fill/fill-menu*
:type type {:ids ids
:values (select-keys shape fill-attrs)}] :type type
:values shape}]
[:& stroke-menu {:ids ids [:& stroke-menu {:ids ids
:type type :type type
:show-caps true :show-caps true

View file

@ -11,7 +11,7 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
@ -83,9 +83,10 @@
[:& constraints-menu {:ids ids [:& constraints-menu {:ids ids
:values constraint-values}]) :values constraint-values}])
[:& fill-menu {:ids ids [:> fill/fill-menu*
:type type {:ids ids
:values (select-keys shape fill-attrs)}] :type type
:values shape}]
[:& stroke-menu {:ids ids [:& stroke-menu {:ids ids
:type type :type type
:values stroke-values}] :values stroke-values}]

View file

@ -15,7 +15,7 @@
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]] [app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu variant-menu*]] [app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu variant-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs-shape fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.frame-grid :refer [frame-grid]] [app.main.ui.workspace.sidebar.options.menus.frame-grid :refer [frame-grid]]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
@ -117,9 +117,11 @@
[:& constraints-menu {:ids ids [:& constraints-menu {:ids ids
:values constraint-values}]) :values constraint-values}])
[:& fill-menu {:ids ids [:> fill/fill-menu*
:type shape-type {:ids ids
:values (select-keys shape fill-attrs-shape)}] :type shape-type
:values shape}]
[:& stroke-menu {:ids ids [:& stroke-menu {:ids ids
:type shape-type :type shape-type
:values stroke-values}] :values stroke-values}]

View file

@ -14,7 +14,7 @@
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]] [app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
@ -95,7 +95,7 @@
[:& constraints-menu {:ids constraint-ids :values constraint-values}]) [:& constraints-menu {:ids constraint-ids :values constraint-values}])
(when-not (empty? fill-ids) (when-not (empty? fill-ids)
[:& fill-menu {:type type :ids fill-ids :values fill-values}]) [:> fill/fill-menu* {:type type :ids fill-ids :values fill-values}])
(when-not (empty? stroke-ids) (when-not (empty? stroke-ids)
[:& stroke-menu {:type type :ids stroke-ids :values stroke-values}]) [:& stroke-menu {:type type :ids stroke-ids :values stroke-values}])

View file

@ -11,7 +11,7 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
@ -29,7 +29,6 @@
measure-values (select-keys shape measure-attrs) measure-values (select-keys shape measure-attrs)
layer-values (select-keys shape layer-attrs) layer-values (select-keys shape layer-attrs)
constraint-values (select-keys shape constraint-attrs) constraint-values (select-keys shape constraint-attrs)
fill-values (select-keys shape fill-attrs)
stroke-values (select-keys shape stroke-attrs) stroke-values (select-keys shape stroke-attrs)
layout-item-values (select-keys shape layout-item-attrs) layout-item-values (select-keys shape layout-item-attrs)
layout-container-values (select-keys shape layout-container-flex-attrs) layout-container-values (select-keys shape layout-container-flex-attrs)
@ -83,9 +82,10 @@
[:& constraints-menu {:ids ids [:& constraints-menu {:ids ids
:values constraint-values}]) :values constraint-values}])
[:& fill-menu {:ids ids [:> fill/fill-menu*
:type type {:ids ids
:values fill-values}] :type type
:values shape}]
[:& stroke-menu {:ids ids [:& stroke-menu {:ids ids
:type type :type type

View file

@ -22,7 +22,7 @@
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]] [app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-attrs exports-menu]] [app.main.ui.workspace.sidebar.options.menus.exports :refer [exports-attrs exports-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
@ -159,7 +159,7 @@
{:measure measure-attrs {:measure measure-attrs
:layer layer-attrs :layer layer-attrs
:constraint constraint-attrs :constraint constraint-attrs
:fill fill-attrs :fill fill/fill-attrs
:shadow shadow-attrs :shadow shadow-attrs
:blur blur-attrs :blur blur-attrs
:stroke stroke-attrs :stroke stroke-attrs
@ -388,7 +388,7 @@
[:& ot/text-menu {:type type :ids text-ids :values text-values}]) [:& ot/text-menu {:type type :ids text-ids :values text-values}])
(when-not (empty? fill-ids) (when-not (empty? fill-ids)
[:& fill-menu {:type type :ids fill-ids :values fill-values}]) [:> fill/fill-menu* {:type type :ids fill-ids :values fill-values}])
(when-not (empty? stroke-ids) (when-not (empty? stroke-ids)
[:& stroke-menu {:type type :ids stroke-ids :show-caps show-caps :values stroke-values [:& stroke-menu {:type type :ids stroke-ids :show-caps show-caps :values stroke-values

View file

@ -11,7 +11,7 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
@ -82,9 +82,11 @@
[:& constraints-menu {:ids ids [:& constraints-menu {:ids ids
:values constraint-values}]) :values constraint-values}])
[:& fill-menu {:ids ids [:> fill/fill-menu*
:type type {:ids ids
:values (select-keys shape fill-attrs)}] :type type
:values shape}]
[:& stroke-menu {:ids ids [:& stroke-menu {:ids ids
:type type :type type
:show-caps true :show-caps true

View file

@ -11,7 +11,7 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
@ -32,7 +32,6 @@
measure-values (select-measure-keys shape) measure-values (select-measure-keys shape)
layer-values (select-keys shape layer-attrs) layer-values (select-keys shape layer-attrs)
constraint-values (select-keys shape constraint-attrs) constraint-values (select-keys shape constraint-attrs)
fill-values (select-keys shape fill-attrs)
stroke-values (select-keys shape stroke-attrs) stroke-values (select-keys shape stroke-attrs)
layout-item-values (select-keys shape layout-item-attrs) layout-item-values (select-keys shape layout-item-attrs)
layout-container-values (select-keys shape layout-container-flex-attrs) layout-container-values (select-keys shape layout-container-flex-attrs)
@ -85,9 +84,10 @@
[:& constraints-menu {:ids ids [:& constraints-menu {:ids ids
:values constraint-values}]) :values constraint-values}])
[:& fill-menu {:ids ids [:> fill/fill-menu*
:type type {:ids ids
:values fill-values}] :type type
:values shape}]
[:& stroke-menu {:ids ids [:& stroke-menu {:ids ids
:type type :type type

View file

@ -13,7 +13,7 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-item :refer [layout-item-attrs layout-item-menu]]
@ -53,7 +53,7 @@
(defn get-fill-values [shape] (defn get-fill-values [shape]
(let [fill-values (select-keys shape fill-attrs) (let [fill-values (select-keys shape fill/fill-attrs)
color (-> (or (get-in shape [:content :attrs :fill]) color (-> (or (get-in shape [:content :attrs :fill])
(get-in shape [:content :attrs :style :fill])) (get-in shape [:content :attrs :style :fill]))
(parse-color)) (parse-color))
@ -154,9 +154,10 @@
[:& constraints-menu {:ids ids [:& constraints-menu {:ids ids
:values constraint-values}]) :values constraint-values}])
[:& fill-menu {:ids ids [:> fill/fill-menu*
:type type {:ids ids
:values fill-values}] :type type
:values fill-values}]
[:& stroke-menu {:ids ids [:& stroke-menu {:ids ids
:type type :type type

View file

@ -17,7 +17,7 @@
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]] [app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu fill-attrs]] [app.main.ui.workspace.sidebar.options.menus.fill :as fill]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]] [app.main.ui.workspace.sidebar.options.menus.layout-container :refer [layout-container-flex-attrs layout-container-menu]]
@ -60,12 +60,11 @@
editor-instance (when (features/active-feature? @st/state "text-editor/v2") editor-instance (when (features/active-feature? @st/state "text-editor/v2")
(mf/deref refs/workspace-editor)) (mf/deref refs/workspace-editor))
fill-values (-> (dwt/current-text-values fill-values (dwt/current-text-values
{:editor-state editor-state {:editor-state editor-state
:editor-instance editor-instance :editor-instance editor-instance
:shape shape :shape shape
:attrs (conj txt/text-fill-attrs :fills)}) :attrs (conj txt/text-fill-attrs :fills)})
(d/update-in-when [:fill-color-gradient :type] keyword))
fill-values (if (not (contains? fill-values :fills)) fill-values (if (not (contains? fill-values :fills))
;; Old fill format ;; Old fill format
@ -76,7 +75,7 @@
text-values (d/merge text-values (d/merge
(select-keys shape [:grow-type]) (select-keys shape [:grow-type])
(select-keys shape fill-attrs) (select-keys shape fill/fill-attrs)
(dwt/current-root-values (dwt/current-root-values
{:shape shape {:shape shape
:attrs txt/root-attrs}) :attrs txt/root-attrs})
@ -133,7 +132,7 @@
:type type :type type
:values text-values}] :values text-values}]
[:& fill-menu [:> fill/fill-menu*
{:ids ids {:ids ids
:type type :type type
:values fill-values}] :values fill-values}]