mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
🎉 Add tokens to color selection (#7447)
* 🎉 Add tokens to color row * 🎉 Add color-token to stroke input * 🐛 Fix change token on multiselection with groups * 🎉 Create token colors on selected-colors section * ♻️ Fix comments
This commit is contained in:
@@ -1137,16 +1137,20 @@
|
||||
ref-id (:stroke-color-ref-id stroke)
|
||||
|
||||
colors (-> libraries
|
||||
(get ref-file)
|
||||
(get ref-id)
|
||||
(get :data)
|
||||
(ctl/get-colors))
|
||||
shared? (contains? colors ref-id)
|
||||
has-color? (:stroke-color stroke)
|
||||
|
||||
is-shared? (contains? colors ref-id)
|
||||
has-color? (or (:stroke-color stroke)
|
||||
(:stroke-color-gradient stroke))
|
||||
attrs (cond-> (clr/stroke->color stroke)
|
||||
(not (or is-shared? (= ref-file file-id)))
|
||||
(dissoc :ref-id :ref-file))]
|
||||
base-attrs (cond-> (clr/stroke->color stroke)
|
||||
(not (or shared? (= ref-file file-id)))
|
||||
(dissoc :ref-file :ref-id))
|
||||
|
||||
attrs (cond-> base-attrs
|
||||
(:has-token-applied stroke)
|
||||
(assoc :has-token-applied true
|
||||
:token-name (:token-name stroke)))]
|
||||
|
||||
(when has-color?
|
||||
{:attrs attrs
|
||||
@@ -1154,7 +1158,25 @@
|
||||
:shape-id (:shape-id stroke)
|
||||
:index (:index stroke)})))
|
||||
|
||||
(defn- shadow->color-att
|
||||
(defn- shadow->color-attr
|
||||
"Given a stroke map enriched with :shape-id, :index, and optionally
|
||||
:has-token-applied / :token-name, returns a color attribute map.
|
||||
|
||||
If :has-token-applied is true, adds token metadata to :attrs:
|
||||
{:has-token-applied true
|
||||
:token-name <token-name>}
|
||||
|
||||
Args:
|
||||
- stroke: map with stroke info, including :shape-id and :index
|
||||
- file-id: current file UUID
|
||||
- libraries: map of shared color libraries
|
||||
|
||||
Returns:
|
||||
A map like:
|
||||
{:attrs {...color data...}
|
||||
:prop :stroke
|
||||
:shape-id <uuid>
|
||||
:index <int>}"
|
||||
[shadow file-id libraries]
|
||||
(let [color (get shadow :color)
|
||||
ref-file (get color :ref-file)
|
||||
@@ -1202,6 +1224,24 @@
|
||||
(map #(text->color-att % file-id libraries)))))
|
||||
|
||||
(defn- fill->color-att
|
||||
"Given a fill map enriched with :shape-id, :index, and optionally
|
||||
:has-token-applied / :token-name, returns a color attribute map.
|
||||
|
||||
If :has-token-applied is true, adds token metadata to :attrs:
|
||||
{:has-token-applied true
|
||||
:token-name <token-name>}
|
||||
|
||||
Args:
|
||||
- fill: map with fill info, including :shape-id and :index
|
||||
- file-id: current file UUID
|
||||
- libraries: map of shared color libraries
|
||||
|
||||
Returns:
|
||||
A map like:
|
||||
{:attrs {...color data...}
|
||||
:prop :fill
|
||||
:shape-id <uuid>
|
||||
:index <int>}"
|
||||
[fill file-id libraries]
|
||||
(let [ref-file (:fill-color-ref-file fill)
|
||||
ref-id (:fill-color-ref-id fill)
|
||||
@@ -1213,9 +1253,15 @@
|
||||
shared? (contains? colors ref-id)
|
||||
has-color? (or (:fill-color fill)
|
||||
(:fill-color-gradient fill))
|
||||
attrs (cond-> (types.fills/fill->color fill)
|
||||
|
||||
base-attrs (cond-> (types.fills/fill->color fill)
|
||||
(not (or shared? (= ref-file file-id)))
|
||||
(dissoc :ref-file :ref-id))]
|
||||
(dissoc :ref-file :ref-id))
|
||||
|
||||
attrs (cond-> base-attrs
|
||||
(:has-token-applied fill)
|
||||
(assoc :has-token-applied true
|
||||
:token-name (:token-name fill)))]
|
||||
|
||||
(when has-color?
|
||||
{:attrs attrs
|
||||
@@ -1224,21 +1270,55 @@
|
||||
:index (:index fill)})))
|
||||
|
||||
(defn extract-all-colors
|
||||
"Extracts color information from a list of shapes, including fills, strokes, and shadows.
|
||||
If a shape has applied tokens of type :fill or :stroke-color, the first fill or stroke
|
||||
will include extra attributes in its :attrs map:
|
||||
{:has-token-applied true
|
||||
:token-name <token-name>}
|
||||
|
||||
Args:
|
||||
- shapes: vector of shape maps
|
||||
- file-id: current file UUID
|
||||
- libraries: map of shared color libraries
|
||||
|
||||
Returns:
|
||||
A vector of color attribute maps with metadata for each shape."
|
||||
[shapes file-id libraries]
|
||||
(reduce
|
||||
(fn [result shape]
|
||||
(let [fill-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:fills shape))
|
||||
stroke-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:strokes shape))
|
||||
shadow-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:shadow shape))]
|
||||
(let [applied-tokens (:applied-tokens shape)
|
||||
applied-fill (get applied-tokens :fill)
|
||||
applied-stroke (get applied-tokens :stroke-color)
|
||||
fills (:fills shape)
|
||||
strokes (:strokes shape)
|
||||
shadows (:shadow shape)
|
||||
shape-id (:id shape)
|
||||
|
||||
fills* (map-indexed
|
||||
(fn [index fill]
|
||||
(cond-> (assoc fill :shape-id shape-id :index index)
|
||||
(and (zero? index) applied-fill)
|
||||
(assoc :has-token-applied true
|
||||
:token-name applied-fill)))
|
||||
fills)
|
||||
|
||||
strokes* (map-indexed
|
||||
(fn [index stroke]
|
||||
(cond-> (assoc stroke :shape-id shape-id :index index)
|
||||
(and (zero? index) applied-stroke)
|
||||
(assoc :has-token-applied true
|
||||
:token-name applied-stroke)))
|
||||
strokes)
|
||||
|
||||
shadows* (map-indexed #(assoc %2 :shape-id shape-id :index %1) shadows)]
|
||||
(if (= :text (:type shape))
|
||||
(-> result
|
||||
(into (keep #(stroke->color-att % file-id libraries)) stroke-obj)
|
||||
(into (map #(shadow->color-att % file-id libraries)) shadow-obj)
|
||||
(into (keep #(stroke->color-att % file-id libraries)) strokes*)
|
||||
(into (map #(shadow->color-attr % file-id libraries)) shadows*)
|
||||
(into (extract-text-colors shape file-id libraries)))
|
||||
|
||||
(-> result
|
||||
(into (keep #(fill->color-att % file-id libraries)) fill-obj)
|
||||
(into (keep #(stroke->color-att % file-id libraries)) stroke-obj)
|
||||
(into (map #(shadow->color-att % file-id libraries)) shadow-obj)))))
|
||||
(into (keep #(fill->color-att % file-id libraries)) fills*)
|
||||
(into (keep #(stroke->color-att % file-id libraries)) strokes*)
|
||||
(into (map #(shadow->color-attr % file-id libraries)) shadows*)))))
|
||||
[]
|
||||
shapes))
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
:style {:background-image (str/ffmt "url(%)" uri)}}])
|
||||
has-errors
|
||||
[:span {:class (stl/css :swatch-error)}]
|
||||
|
||||
:else
|
||||
[:span {:class (stl/css :swatch-opacity)}
|
||||
[:span {:class (stl/css :swatch-solid-side)
|
||||
|
||||
@@ -13,44 +13,93 @@
|
||||
[app.main.data.workspace.tokens.application :as dwta]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row*]]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- prepare-colors
|
||||
[shapes file-id libraries]
|
||||
(let [data (into [] (remove nil? (dwc/extract-all-colors shapes file-id libraries)))
|
||||
groups (d/group-by :attrs #(dissoc % :attrs) data)
|
||||
all-colors (distinct (mapv :attrs data))
|
||||
"Prepares and groups extracted color information from shapes.
|
||||
Input:
|
||||
- shapes: vector of shape maps
|
||||
- file-id: current file UUID
|
||||
- libraries: shared color libraries
|
||||
|
||||
tmp (group-by #(some? (:id %)) all-colors)
|
||||
library-colors (get tmp true)
|
||||
colors (get tmp false)]
|
||||
Output:
|
||||
{:groups explained below
|
||||
:all-colors vector of all color maps (unique attrs)
|
||||
:colors vector of normal colors (without ref-id or token)
|
||||
:library-colors vector of colors linked to libraries (with ref-id)
|
||||
:token-colors vector of colors linked to applied tokens
|
||||
:tokens placeholder for future token data}
|
||||
|
||||
:groups structure
|
||||
|
||||
A map where:
|
||||
- Each **key** is a color descriptor map representing a unique color instance.
|
||||
Depending on the color type, it can contain:
|
||||
• :color → hex string (e.g. \"#9f2929\")
|
||||
• :opacity → numeric value between 0-1
|
||||
• :ref-id and :ref-file → if the color comes from a library
|
||||
• :token-name \"some-token\" → if the color
|
||||
originates from an applied token
|
||||
|
||||
- Each **value** is a vector of one or more maps describing *where* that
|
||||
color is used. Each entry corresponds to a specific shape and color
|
||||
property in the document:
|
||||
• :prop → the property type (:fill, :stroke, :shadow, etc.)
|
||||
• :shape-id → the UUID of the shape using this color
|
||||
• :index → index of the color in the shape's fill/stroke list
|
||||
|
||||
Example of groups:
|
||||
{
|
||||
{:color \"#9f2929\", :opacity 0.3, :token-name \"asd2\" :has-token-applied true}
|
||||
[{:prop :fill, :shape-id #uuid \"d0231035-25c9-80d5-8006-eae4c3dff32e\", :index 0}]
|
||||
|
||||
{:color \"#1b54b6\", :opacity 1}
|
||||
[{:prop :fill, :shape-id #uuid \"aab34f9a-98c1-801a-8006-eae5e8236f1b\", :index 0}]
|
||||
}
|
||||
|
||||
This structure allows fast lookups of all shapes using the same visual color,
|
||||
regardless of whether it comes from local fills, strokes or shadow-colors."
|
||||
|
||||
[shapes file-id libraries]
|
||||
(let [data (into [] (remove nil?) (dwc/extract-all-colors shapes file-id libraries))
|
||||
groups (d/group-by :attrs #(dissoc % :attrs) data)
|
||||
|
||||
;; Unique color attribute maps
|
||||
all-colors (distinct (mapv :attrs data))
|
||||
|
||||
;; Split into: library colors, token colors, and plain colors
|
||||
library-colors (filterv :ref-id all-colors)
|
||||
token-colors (filterv :token-name all-colors)
|
||||
colors (filterv #(and (nil? (:ref-id %))
|
||||
(not (:token-name %)))
|
||||
all-colors)]
|
||||
{:groups groups
|
||||
:all-colors all-colors
|
||||
:colors colors
|
||||
:token-colors token-colors
|
||||
:library-colors library-colors}))
|
||||
|
||||
(def xf:map-shape-id
|
||||
(map :shape-id))
|
||||
|
||||
(defn- generate-color-operations
|
||||
(defn- retrieve-color-operations
|
||||
[groups old-color prev-colors]
|
||||
(let [old-color (-> old-color
|
||||
(dissoc :name :path)
|
||||
(d/without-nils))
|
||||
prev-color (d/seek (partial get groups) prev-colors)
|
||||
(let [old-color (-> old-color
|
||||
(dissoc :name :path)
|
||||
(d/without-nils))
|
||||
prev-color (d/seek (partial get groups) prev-colors)
|
||||
color-operations-old (get groups old-color)
|
||||
color-operations-prev (get groups prev-colors)
|
||||
color-operations (or color-operations-prev color-operations-old)
|
||||
old-color (or prev-color old-color)]
|
||||
old-color (or prev-color old-color)]
|
||||
[color-operations old-color]))
|
||||
|
||||
(mf/defc color-selection-menu*
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]}
|
||||
[{:keys [shapes file-id libraries]}]
|
||||
(let [{:keys [groups library-colors colors]}
|
||||
(let [{:keys [groups library-colors colors token-colors]}
|
||||
(mf/with-memo [file-id shapes libraries]
|
||||
(prepare-colors shapes file-id libraries))
|
||||
|
||||
@@ -63,21 +112,19 @@
|
||||
|
||||
expand-lib-color (mf/use-state false)
|
||||
expand-color (mf/use-state false)
|
||||
expand-token-color (mf/use-state false)
|
||||
|
||||
groups-ref (h/use-ref-value groups)
|
||||
;; TODO: Review if this is still necessary.
|
||||
prev-colors-ref (mf/use-ref nil)
|
||||
|
||||
on-change
|
||||
(mf/use-fn
|
||||
(fn [new-color old-color from-picker?]
|
||||
(let [;; When dragging on the color picker sometimes all
|
||||
;; the shapes hasn't updated the color to the prev
|
||||
;; value so we need this extra calculation
|
||||
groups (mf/ref-val groups-ref)
|
||||
prev-colors (mf/ref-val prev-colors-ref)
|
||||
|
||||
[color-operations old-color] (generate-color-operations groups old-color prev-colors)]
|
||||
(mf/deps groups)
|
||||
(fn [old-color new-color from-picker?]
|
||||
(let [prev-colors (mf/ref-val prev-colors-ref)
|
||||
[color-operations old-color] (retrieve-color-operations groups old-color prev-colors)]
|
||||
|
||||
;; TODO: Review if this is still necessary.
|
||||
(when from-picker?
|
||||
(let [color (-> new-color
|
||||
(dissoc :name :path)
|
||||
@@ -85,7 +132,7 @@
|
||||
(mf/set-ref-val! prev-colors-ref
|
||||
(conj prev-colors color))))
|
||||
|
||||
(st/emit! (dwc/change-color-in-selected color-operations new-color old-color)))))
|
||||
(st/emit! (dwc/change-color-in-selected color-operations new-color (dissoc old-color :token-name :has-token-applied))))))
|
||||
|
||||
on-open
|
||||
(mf/use-fn #(mf/set-ref-val! prev-colors-ref []))
|
||||
@@ -95,31 +142,52 @@
|
||||
|
||||
on-detach
|
||||
(mf/use-fn
|
||||
(mf/deps groups)
|
||||
(fn [color]
|
||||
(let [groups (mf/ref-val groups-ref)
|
||||
color-operations (get groups color)
|
||||
color' (dissoc color :id :file-id)]
|
||||
(let [color-operations (get groups color)
|
||||
color' (dissoc color :ref-id :ref-file)]
|
||||
(st/emit! (dwc/change-color-in-selected color-operations color' color)))))
|
||||
|
||||
on-detach-token
|
||||
(mf/use-fn
|
||||
(mf/deps token-colors groups)
|
||||
(fn [token]
|
||||
(let [prev-colors (mf/ref-val prev-colors-ref)
|
||||
token-color (some #(when (= (:token-name %) (:name token)) %) token-colors)
|
||||
|
||||
[color-operations _] (retrieve-color-operations groups token-color prev-colors)]
|
||||
(doseq [op color-operations]
|
||||
(let [attr (if (= (:prop op) :stroke)
|
||||
#{:stroke-color}
|
||||
#{:fill})
|
||||
color (-> token-color
|
||||
(dissoc :token-name :has-token-applied)
|
||||
(d/without-nils))]
|
||||
(mf/set-ref-val! prev-colors-ref
|
||||
(conj prev-colors color))
|
||||
(st/emit! (dwta/unapply-token {:attributes attr
|
||||
:token token
|
||||
:shape-ids [(:shape-id op)]})))))))
|
||||
|
||||
select-only
|
||||
(mf/use-fn
|
||||
(mf/deps groups)
|
||||
(fn [color]
|
||||
(let [groups (mf/ref-val groups-ref)
|
||||
color-operations (get groups color)
|
||||
(let [color-operations (get groups color)
|
||||
ids (into (d/ordered-set) xf:map-shape-id color-operations)]
|
||||
(st/emit! (dws/select-shapes ids)))))
|
||||
|
||||
on-token-change
|
||||
(mf/use-fn
|
||||
(mf/deps groups)
|
||||
(fn [_ token old-color]
|
||||
(let [groups (mf/ref-val groups-ref)
|
||||
prev-colors (mf/ref-val prev-colors-ref)
|
||||
(let [prev-colors (mf/ref-val prev-colors-ref)
|
||||
resolved-value (:resolved-value token)
|
||||
new-color (dwta/value->color resolved-value)
|
||||
color (-> new-color
|
||||
(dissoc :name :path)
|
||||
(d/without-nils))
|
||||
[color-operations _] (generate-color-operations groups old-color prev-colors)]
|
||||
[color-operations _] (retrieve-color-operations groups old-color prev-colors)]
|
||||
(mf/set-ref-val! prev-colors-ref
|
||||
(conj prev-colors color))
|
||||
(st/emit! (dwta/apply-token-on-selected color-operations token)))))]
|
||||
@@ -135,22 +203,15 @@
|
||||
(when open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
[:div {:class (stl/css :selected-color-group)}
|
||||
;; The hidden color is to solve a problem with the color picker. When a color is changed
|
||||
;; and is no longer a library color it disapears from the list of library colors. Because
|
||||
;; we need to keep the color picker open we need to maintain that color. The easier way
|
||||
;; is to render the color elements so even if the library color is no longer we have still
|
||||
;; the component to change it from the color picker.
|
||||
(let [lib-colors (cond->> library-colors (not @expand-lib-color) (take 3))
|
||||
lib-colors (concat lib-colors colors)]
|
||||
(for [[index color] (d/enumerate lib-colors)]
|
||||
(let [library-colors-extract (cond->> library-colors (not @expand-lib-color) (take 3))]
|
||||
(for [[index color] (d/enumerate library-colors-extract)]
|
||||
[:> color-row*
|
||||
{:key index
|
||||
:color color
|
||||
:index index
|
||||
:hidden (not (:id color))
|
||||
:on-detach on-detach
|
||||
:on-detach #(on-detach color %)
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-change #(on-change color %1 %2)
|
||||
:on-token-change #(on-token-change %1 %2 color)
|
||||
:on-open on-open
|
||||
:origin :color-selection
|
||||
@@ -167,7 +228,7 @@
|
||||
:color color
|
||||
:index index
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-change #(on-change color %1 %2)
|
||||
:origin :color-selection
|
||||
:on-token-change #(on-token-change %1 %2 color)
|
||||
:on-open on-open
|
||||
@@ -176,4 +237,28 @@
|
||||
(when (and (false? @expand-color) (< 3 (count colors)))
|
||||
[:button {:class (stl/css :more-colors-btn)
|
||||
:on-click #(reset! expand-color true)}
|
||||
(tr "workspace.options.more-colors")])]])]))
|
||||
(tr "workspace.options.more-colors")])]
|
||||
|
||||
[:div {:class (stl/css :selected-color-group)}
|
||||
(let [token-color-extract (cond->> token-colors (not @expand-token-color) (take 3))]
|
||||
(for [[index token-color] (d/enumerate token-color-extract)]
|
||||
(let [color {:color (:color token-color)
|
||||
:opacity (:opacity token-color)}]
|
||||
[:> color-row*
|
||||
{:key index
|
||||
:color color
|
||||
:index index
|
||||
:select-only select-only
|
||||
:on-change #(on-change token-color %1 %2)
|
||||
:origin :color-selection
|
||||
:applied-token (:token-name token-color)
|
||||
:on-detach-token on-detach-token
|
||||
:on-token-change #(on-token-change %1 %2 token-color)
|
||||
:on-open on-open
|
||||
:on-close on-close}])))
|
||||
|
||||
(when (and (false? @expand-token-color)
|
||||
(< 3 (count token-colors)))
|
||||
[:button {:class (stl/css :more-colors-btn)
|
||||
:on-click #(reset! expand-token-color true)}
|
||||
(tr "workspace.options.more-token-colors")])]])]))
|
||||
|
||||
@@ -256,7 +256,9 @@
|
||||
:on-remove on-remove
|
||||
:disable-drag disable-drag?
|
||||
:on-focus on-focus
|
||||
:applied-token fill-token-applied
|
||||
:applied-token (if (= index 0)
|
||||
fill-token-applied
|
||||
nil)
|
||||
:on-token-change on-token-change
|
||||
:origin :fill
|
||||
:select-on-focus (not disable-drag?)
|
||||
|
||||
@@ -69,9 +69,9 @@
|
||||
(mf/defc color-token-row*
|
||||
{::mf/private true}
|
||||
[{:keys [active-tokens color-token color on-swatch-click-token detach-token open-modal-from-token]}]
|
||||
(let [;; `active-tokens` may be provided as a `delay` (lazy computation).
|
||||
;; In that case we must deref it (`@active-tokens`) to force evaluation
|
||||
;; and obtain the actual value. If it’s already realized (not a delay),
|
||||
(let [;; `active-tokens` may be provided as a `delay` (lazy computation).
|
||||
;; In that case we must deref it (`@active-tokens`) to force evaluation
|
||||
;; and obtain the actual value. If it’s already realized (not a delay),
|
||||
;; we just use it directly.
|
||||
active-tokens (if (delay? active-tokens)
|
||||
@active-tokens
|
||||
@@ -143,10 +143,10 @@
|
||||
[{:keys [index color class disable-gradient disable-opacity disable-image disable-picker hidden
|
||||
on-change on-reorder on-detach on-open on-close on-remove origin on-detach-token
|
||||
disable-drag on-focus on-blur select-only select-on-focus on-token-change applied-token]}]
|
||||
|
||||
(let [token-color (contains? cfg/flags :token-color)
|
||||
libraries (mf/deref refs/files)
|
||||
on-change (h/use-ref-callback on-change)
|
||||
on-token-change (h/use-ref-callback on-token-change)
|
||||
|
||||
color-without-hash (mf/use-memo
|
||||
(mf/deps color)
|
||||
#(-> color :color clr/remove-hash))
|
||||
@@ -169,11 +169,12 @@
|
||||
|
||||
active-tokens* (mf/use-ctx ctx/active-tokens-by-type)
|
||||
|
||||
tokens (mf/with-memo [active-tokens* origin]
|
||||
(delay
|
||||
(-> (deref active-tokens*)
|
||||
(select-keys (get tk/tokens-by-input origin))
|
||||
(not-empty))))
|
||||
tokens (mf/with-memo [active-tokens* origin]
|
||||
(let [origin (if (= :color-selection origin) :fill origin)]
|
||||
(delay
|
||||
(-> (deref active-tokens*)
|
||||
(select-keys (get tk/tokens-by-input origin))
|
||||
(not-empty)))))
|
||||
|
||||
on-focus'
|
||||
(mf/use-fn
|
||||
@@ -205,9 +206,12 @@
|
||||
|
||||
handle-select
|
||||
(mf/use-fn
|
||||
(mf/deps select-only color)
|
||||
(mf/deps select-only color applied-token)
|
||||
(fn []
|
||||
(select-only color)))
|
||||
(let [color (if applied-token
|
||||
(assoc color :has-token-applied true :token-name applied-token)
|
||||
color)]
|
||||
(select-only color))))
|
||||
|
||||
on-color-change
|
||||
(mf/use-fn
|
||||
@@ -233,7 +237,7 @@
|
||||
|
||||
open-modal
|
||||
(mf/use-fn
|
||||
(mf/deps disable-gradient disable-opacity disable-image disable-picker on-change on-close on-open tokens)
|
||||
(mf/deps disable-gradient disable-opacity disable-image disable-picker on-change on-close on-open tokens index)
|
||||
(fn [color pos tab]
|
||||
(let [color (cond
|
||||
has-multiple-colors
|
||||
@@ -427,4 +431,4 @@
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "settings.select-this-color")
|
||||
:on-click handle-select
|
||||
:icon i/move}])]))
|
||||
:icon i/move}])]))
|
||||
|
||||
@@ -127,7 +127,6 @@
|
||||
|
||||
stroke-style (or (:stroke-style stroke) :solid)
|
||||
|
||||
|
||||
stroke-style-options
|
||||
(mf/with-memo [stroke-style]
|
||||
(d/concat-vec
|
||||
|
||||
@@ -6514,7 +6514,11 @@ msgstr "Top"
|
||||
msgid "workspace.options.more-colors"
|
||||
msgstr "More colors"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
|
||||
msgid "workspace.options.more-token-colors"
|
||||
msgstr "More color tokens"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
|
||||
msgid "workspace.options.more-lib-colors"
|
||||
msgstr "More library colors"
|
||||
|
||||
|
||||
@@ -6457,7 +6457,11 @@ msgstr "Arriba"
|
||||
msgid "workspace.options.more-colors"
|
||||
msgstr "Más colores"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:161
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs
|
||||
msgid "workspace.options.more-token-colors"
|
||||
msgstr "Más tokens de color"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:140
|
||||
msgid "workspace.options.more-lib-colors"
|
||||
msgstr "Más colores de la biblioteca"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user