mirror of
https://github.com/penpot/penpot.git
synced 2026-03-22 10:23:43 +00:00
♻️ Design review for numeric inputs (#8630)
* ♻️ Update tooltip position on icon buttons * ♻️ Sort token groups by priority not alphabetically * ♻️ Add proper padding on text-icon-inputs * ♻️ Hide detach button when dropdown is open * 🐛 Fix detach stroke width * 🐛 Fix strokes applied on all rows * 🐛 Fix nillable inputs * 🐛 Fix comments on PR
This commit is contained in:
@@ -522,31 +522,31 @@
|
||||
|
||||
(def tokens-by-input
|
||||
"A map from input name to applicable token for that input."
|
||||
{:width #{:sizing :dimensions}
|
||||
:height #{:sizing :dimensions}
|
||||
:max-width #{:sizing :dimensions}
|
||||
:max-height #{:sizing :dimensions}
|
||||
:min-width #{:sizing :dimensions}
|
||||
:min-height #{:sizing :dimensions}
|
||||
:x #{:dimensions}
|
||||
:y #{:dimensions}
|
||||
:rotation #{:number :rotation}
|
||||
:border-radius #{:border-radius :dimensions}
|
||||
:row-gap #{:spacing :dimensions}
|
||||
:column-gap #{:spacing :dimensions}
|
||||
:horizontal-padding #{:spacing :dimensions}
|
||||
:vertical-padding #{:spacing :dimensions}
|
||||
:sided-paddings #{:spacing :dimensions}
|
||||
:horizontal-margin #{:spacing :dimensions}
|
||||
:vertical-margin #{:spacing :dimensions}
|
||||
:sided-margins #{:spacing :dimensions}
|
||||
:line-height #{:line-height :number}
|
||||
:opacity #{:opacity}
|
||||
:stroke-width #{:stroke-width :dimensions}
|
||||
:font-size #{:font-size}
|
||||
:letter-spacing #{:letter-spacing}
|
||||
:fill #{:color}
|
||||
:stroke-color #{:color}})
|
||||
{:width [:sizing :dimensions]
|
||||
:height [:sizing :dimensions]
|
||||
:max-width [:sizing :dimensions]
|
||||
:max-height [:sizing :dimensions]
|
||||
:min-width [:sizing :dimensions]
|
||||
:min-height [:sizing :dimensions]
|
||||
:x [:dimensions]
|
||||
:y [:dimensions]
|
||||
:rotation [:rotation :number]
|
||||
:border-radius [:border-radius :dimensions]
|
||||
:row-gap [:spacing :dimensions]
|
||||
:column-gap [:spacing :dimensions]
|
||||
:horizontal-padding [:spacing :dimensions]
|
||||
:vertical-padding [:spacing :dimensions]
|
||||
:sided-paddings [:spacing :dimensions]
|
||||
:horizontal-margin [:spacing :dimensions]
|
||||
:vertical-margin [:spacing :dimensions]
|
||||
:sided-margins [:spacing :dimensions]
|
||||
:line-height [:line-height :number]
|
||||
:opacity [:opacity]
|
||||
:stroke-width [:stroke-width :dimensions]
|
||||
:font-size [:font-size]
|
||||
:letter-spacing [:letter-spacing]
|
||||
:fill [:color]
|
||||
:stroke-color [:color]})
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; HELPERS for tokens application
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
[app.main.ui.ds.controls.utilities.token-field :refer [token-field*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon* icon-list] :as i]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.workspace.tokens.management.forms.controls.utils :as csu]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
@@ -83,48 +84,6 @@
|
||||
(str/replace #"^\{" "")
|
||||
(str/replace #"\}$" "")))
|
||||
|
||||
(defn- token->dropdown-option
|
||||
[token]
|
||||
{:id (str (get token :id))
|
||||
:type :token
|
||||
:resolved-value (get token :resolved-value)
|
||||
:name (get token :name)})
|
||||
|
||||
(defn- generate-dropdown-options
|
||||
[tokens no-sets]
|
||||
(if (empty? tokens)
|
||||
[{:type :empty
|
||||
:label (if no-sets
|
||||
(tr "ds.inputs.numeric-input.no-applicable-tokens")
|
||||
(tr "ds.inputs.numeric-input.no-matches"))}]
|
||||
(->> tokens
|
||||
(map (fn [[type items]]
|
||||
(cons {:group true
|
||||
:type :group
|
||||
:id (dm/str "group-" (name type))
|
||||
:name (name type)}
|
||||
(map token->dropdown-option items))))
|
||||
(interpose [{:separator true
|
||||
:id "separator"
|
||||
:type :separator}])
|
||||
(apply concat)
|
||||
(vec)
|
||||
(not-empty))))
|
||||
|
||||
(defn- extract-partial-brace-text
|
||||
[s]
|
||||
(when-let [start (str/last-index-of s "{")]
|
||||
(subs s (inc start))))
|
||||
|
||||
(defn- filter-token-groups-by-name
|
||||
[tokens filter-text]
|
||||
(let [lc-filter (str/lower filter-text)]
|
||||
(into {}
|
||||
(keep (fn [[group tokens]]
|
||||
(let [filtered (filter #(str/includes? (str/lower (:name %)) lc-filter) tokens)]
|
||||
(when (seq filtered)
|
||||
[group filtered]))))
|
||||
tokens)))
|
||||
|
||||
(defn- focusable-option?
|
||||
[option]
|
||||
@@ -149,31 +108,6 @@
|
||||
j)))
|
||||
indices)))
|
||||
|
||||
(defn- sort-groups-and-tokens
|
||||
"Sorts both the groups and the tokens inside them alphabetically.
|
||||
|
||||
Input:
|
||||
A map where:
|
||||
- keys are groups (keywords or strings, e.g. :dimensions, :colors)
|
||||
- values are vectors of token maps, each containing at least a :name key
|
||||
|
||||
Example input:
|
||||
{:dimensions [{:name \"tres\"} {:name \"quini\"}]
|
||||
:colors [{:name \"azul\"} {:name \"rojo\"}]}
|
||||
|
||||
Output:
|
||||
A sorted map where:
|
||||
- groups are ordered alphabetically by key
|
||||
- tokens inside each group are sorted alphabetically by :name
|
||||
|
||||
Example output:
|
||||
{:colors [{:name \"azul\"} {:name \"rojo\"}]
|
||||
:dimensions [{:name \"quini\"} {:name \"tres\"}]}"
|
||||
|
||||
[groups->tokens]
|
||||
(into (sorted-map) ;; ensure groups are ordered alphabetically by their key
|
||||
(for [[group tokens] groups->tokens]
|
||||
[group (sort-by :name tokens)])))
|
||||
|
||||
(def ^:private schema:icon
|
||||
[:and :string [:fn #(contains? icon-list %)]])
|
||||
@@ -288,16 +222,7 @@
|
||||
|
||||
dropdown-options
|
||||
(mf/with-memo [tokens filter-id]
|
||||
(delay
|
||||
(let [tokens (if (delay? tokens) @tokens tokens)
|
||||
|
||||
sorted-tokens (sort-groups-and-tokens tokens)
|
||||
partial (extract-partial-brace-text filter-id)
|
||||
options (if (seq partial)
|
||||
(filter-token-groups-by-name sorted-tokens partial)
|
||||
sorted-tokens)
|
||||
no-sets? (nil? sorted-tokens)]
|
||||
(generate-dropdown-options options no-sets?))))
|
||||
(csu/get-token-dropdown-options tokens filter-id))
|
||||
|
||||
selected-id*
|
||||
(mf/use-state (fn []
|
||||
@@ -649,6 +574,7 @@
|
||||
:icon i/tokens
|
||||
:tooltip-class (stl/css :button-tooltip)
|
||||
:class (stl/css :invisible-button)
|
||||
:tooltip-placement "top-left"
|
||||
:aria-label (tr "ds.inputs.numeric-input.open-token-list-dropdown")
|
||||
:ref open-dropdown-ref
|
||||
:on-click open-dropdown}])))
|
||||
@@ -676,6 +602,7 @@
|
||||
:on-blur on-blur
|
||||
:class inner-class
|
||||
:property property
|
||||
:is-open is-open
|
||||
:slot-start (when (or icon text-icon)
|
||||
(mf/html
|
||||
(cond
|
||||
@@ -714,6 +641,11 @@
|
||||
(when-let [node (mf/ref-val ref)]
|
||||
(dom/set-value! node value'))))
|
||||
|
||||
(mf/with-effect [applied-token]
|
||||
(when (nil? applied-token)
|
||||
(reset! token-applied* nil)
|
||||
(reset! selected-id* nil)))
|
||||
|
||||
(mf/with-layout-effect [on-mouse-wheel]
|
||||
(when-let [node (mf/ref-val ref)]
|
||||
(let [key (events/listen node "wheel" on-mouse-wheel #js {:passive false})]
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
|
||||
.text-icon {
|
||||
color: var(--color-foreground-secondary);
|
||||
@include t.use-typography("code-font");
|
||||
@include t.use-typography("body-small");
|
||||
inline-size: fit-content;
|
||||
min-inline-size: px2rem(40);
|
||||
min-inline-size: px2rem(46);
|
||||
padding-inline-start: var(--sp-xs);
|
||||
}
|
||||
|
||||
.invisible-button {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
[:property {:optional true} [:maybe :string]]
|
||||
[:value :any]
|
||||
[:disabled {:optional true} :boolean]
|
||||
[:is-open {:optional true} :boolean]
|
||||
[:slot-start {:optional true} [:maybe some?]]
|
||||
[:on-click {:optional true} fn?]
|
||||
[:on-token-key-down fn?]
|
||||
@@ -36,7 +37,7 @@
|
||||
{::mf/schema schema:token-field}
|
||||
[{:keys [id label value slot-start disabled class
|
||||
on-click on-token-key-down on-blur detach-token
|
||||
token-wrapper-ref token-detach-btn-ref on-focus property]}]
|
||||
token-wrapper-ref token-detach-btn-ref on-focus property is-open]}]
|
||||
(let [set-active? (some? id)
|
||||
content (if set-active?
|
||||
label
|
||||
@@ -88,9 +89,11 @@
|
||||
|
||||
(when-not ^boolean disabled
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:class (stl/css :invisible-button)
|
||||
:class (stl/css-case :invisible-button true
|
||||
:invisible-btn-dropdown-open is-open)
|
||||
:tooltip-class (stl/css :button-tooltip)
|
||||
:icon i/broken-link
|
||||
:ref token-detach-btn-ref
|
||||
:tooltip-placement "top-left"
|
||||
:aria-label (tr "ds.inputs.token-field.detach-token")
|
||||
:on-click detach-token}])]]))
|
||||
|
||||
@@ -136,6 +136,9 @@
|
||||
--opacity-button: 1;
|
||||
}
|
||||
}
|
||||
.invisible-btn-dropdown-open {
|
||||
--opacity-button: 0;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
inline-size: 100%;
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
(deref placement*)
|
||||
|
||||
delay
|
||||
(d/nilv delay 300)
|
||||
(d/nilv delay 700)
|
||||
|
||||
schedule-ref
|
||||
(mf/use-ref nil)
|
||||
@@ -188,7 +188,7 @@
|
||||
(when-not (.-hidden js/document)
|
||||
(let [trigger-el (mf/ref-val trigger-ref)]
|
||||
(clear-schedule schedule-ref)
|
||||
(add-schedule schedule-ref (d/nilv delay 300)
|
||||
(add-schedule schedule-ref delay
|
||||
(fn []
|
||||
(when-let [active @active-tooltip]
|
||||
(when (not= (:id active) tooltip-id)
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
(ns app.main.ui.workspace.sidebar.options.common
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.data.workspace.tokens.application :as dwta]
|
||||
[app.main.store :as st]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
@@ -24,3 +26,17 @@
|
||||
:ref ref}
|
||||
children])))
|
||||
|
||||
(defn emit-value-or-token [value emit-value-fn ids attrs]
|
||||
(cond
|
||||
(nil? value)
|
||||
(emit-value-fn nil)
|
||||
|
||||
(or (string? value) (number? value))
|
||||
(emit-value-fn value)
|
||||
|
||||
:else
|
||||
(st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs attrs
|
||||
:shape-ids ids}))))
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.workspace.sidebar.options.common :as soc]
|
||||
[app.main.ui.workspace.sidebar.options.menus.input-wrapper-tokens :refer [numeric-input-wrapper*]]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[beicon.v2.core :as rx]
|
||||
@@ -130,26 +131,21 @@
|
||||
(mf/use-fn
|
||||
(mf/deps change-radius ids)
|
||||
(fn [value]
|
||||
(if (or (string? value) (number? value))
|
||||
(st/emit!
|
||||
(change-radius (fn [shape]
|
||||
(ctsr/set-radius-to-all-corners shape value))))
|
||||
(st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs #{:r1 :r2 :r3 :r4}
|
||||
:shape-ids ids})))))
|
||||
|
||||
(soc/emit-value-or-token
|
||||
value
|
||||
#(st/emit! (change-radius (fn [shape] (ctsr/set-radius-to-all-corners shape %))))
|
||||
ids
|
||||
#{:r1 :r2 :r3 :r4})))
|
||||
|
||||
on-single-radius-change
|
||||
(mf/use-fn
|
||||
(mf/deps change-one-radius ids)
|
||||
(fn [value attr]
|
||||
(if (or (string? value) (number? value))
|
||||
(st/emit! (change-one-radius #(ctsr/set-radius-to-single-corner % attr value) attr))
|
||||
(st/emit! (st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs #{attr}
|
||||
:shape-ids ids}))))))
|
||||
(soc/emit-value-or-token
|
||||
value
|
||||
#(st/emit! (change-one-radius (fn [shape] (ctsr/set-radius-to-single-corner shape attr %)) attr))
|
||||
ids
|
||||
#{attr})))
|
||||
|
||||
on-radius-r1-change #(on-single-radius-change % :r1)
|
||||
on-radius-r2-change #(on-single-radius-change % :r2)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.input-wrapper-tokens
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.types.token :as tk]
|
||||
[app.main.ui.context :as muc]
|
||||
[app.main.ui.ds.controls.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.workspace.tokens.management.forms.controls.utils :as csu]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
@@ -11,11 +11,8 @@
|
||||
[{:keys [value attr applied-token align on-detach placeholder input-type class] :rest props}]
|
||||
(let [tokens (mf/use-ctx muc/active-tokens-by-type)
|
||||
|
||||
tokens (mf/with-memo [tokens input-type]
|
||||
(delay
|
||||
(-> (deref tokens)
|
||||
(select-keys (get tk/tokens-by-input (or input-type attr)))
|
||||
(not-empty))))
|
||||
tokens (mf/with-memo [tokens input-type attr]
|
||||
(csu/filter-tokens-for-input tokens (or input-type attr)))
|
||||
|
||||
on-detach-attr
|
||||
(mf/use-fn
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as deprecated-icon]
|
||||
[app.main.ui.workspace.sidebar.options.common :as soc]
|
||||
[app.main.ui.workspace.sidebar.options.menus.input-wrapper-tokens :refer [numeric-input-wrapper*]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
@@ -335,15 +336,8 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-change ids)
|
||||
(fn [value attr event]
|
||||
(if (or (string? value) (number? value))
|
||||
(on-change :simple attr value event)
|
||||
(do
|
||||
(st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs (if (= :p1 attr)
|
||||
#{:p1 :p3}
|
||||
#{:p2 :p4})
|
||||
:shape-ids ids}))))))
|
||||
(let [on-change-fn #(on-change :simple attr % event)]
|
||||
(soc/emit-value-or-token value on-change-fn ids #{attr}))))
|
||||
|
||||
on-detach-token
|
||||
(mf/use-fn
|
||||
@@ -719,15 +713,8 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-change wrap-type ids)
|
||||
(fn [value event attr]
|
||||
(if (or (string? value) (number? value))
|
||||
(on-change (= "nowrap" wrap-type) attr value event)
|
||||
(do
|
||||
(st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs (if (= "nowrap" wrap-type)
|
||||
#{:row-gap :colum-gap}
|
||||
#{attr})
|
||||
:shape-ids ids}))))))
|
||||
(let [on-change-fn #((on-change (= "nowrap" wrap-type) attr % event))]
|
||||
(soc/emit-value-or-token value on-change-fn ids #{attr}))))
|
||||
|
||||
on-detach-token
|
||||
(mf/use-fn
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
[app.main.ui.components.title-bar :refer [title-bar*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
||||
[app.main.ui.icons :as deprecated-icon]
|
||||
[app.main.ui.workspace.sidebar.options.common :as soc]
|
||||
[app.main.ui.workspace.sidebar.options.menus.input-wrapper-tokens :refer [numeric-input-wrapper*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.layout-container :refer [get-layout-flex-icon]]
|
||||
[app.util.dom :as dom]
|
||||
@@ -117,15 +118,11 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-change ids)
|
||||
(fn [value attr]
|
||||
(if (or (string? value) (number? value))
|
||||
(on-change :simple attr value)
|
||||
(do
|
||||
(st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs (if (= :m1 attr)
|
||||
#{:m1 :m3}
|
||||
#{:m2 :m4})
|
||||
:shape-ids ids}))))))
|
||||
(soc/emit-value-or-token
|
||||
value
|
||||
#(on-change :simple attr %)
|
||||
ids
|
||||
(if (= :m1 attr) #{:m1 :m3} #{:m2 :m4}))))
|
||||
|
||||
on-focus-m1
|
||||
(mf/use-fn (mf/deps on-focus) #(on-focus :m1))
|
||||
@@ -247,14 +244,11 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-change ids)
|
||||
(fn [value attr]
|
||||
(if (or (string? value) (number? value))
|
||||
(on-change :multiple attr value)
|
||||
(do
|
||||
(st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs #{attr}
|
||||
:shape-ids ids}))))))
|
||||
|
||||
(soc/emit-value-or-token
|
||||
value
|
||||
#(on-change :multiple attr %)
|
||||
ids
|
||||
#{attr})))
|
||||
|
||||
on-m1-change
|
||||
(mf/use-fn (mf/deps on-change') #(on-change' % :m1))
|
||||
@@ -577,13 +571,11 @@
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [value attr]
|
||||
(if (or (string? value) (number? value))
|
||||
(st/emit! (dwsl/update-layout-child ids {attr value}))
|
||||
(do
|
||||
(st/emit!
|
||||
(dwta/toggle-token {:token (first value)
|
||||
:attrs #{attr}
|
||||
:shape-ids ids}))))))
|
||||
(soc/emit-value-or-token
|
||||
value
|
||||
#(st/emit! (dwsl/update-layout-child ids {attr %}))
|
||||
ids
|
||||
#{attr})))
|
||||
|
||||
on-layout-item-min-w-change
|
||||
(mf/use-fn (mf/deps on-size-change) #(on-size-change % :layout-item-min-w))
|
||||
|
||||
@@ -168,6 +168,7 @@
|
||||
|
||||
on-blur (fn [_]
|
||||
(reset! disable-drag false))
|
||||
|
||||
on-detach-token
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
@@ -205,7 +206,7 @@
|
||||
(seq strokes)
|
||||
[:> h/sortable-container* {}
|
||||
(for [[index value] (d/enumerate (:strokes values []))]
|
||||
[:> stroke-row* {:key (dm/str "stroke-" index)
|
||||
[:> stroke-row* {:key (dm/str "stroke-" index "-" (hash applied-tokens))
|
||||
:stroke value
|
||||
:title (tr "workspace.options.stroke-color")
|
||||
:index index
|
||||
@@ -222,7 +223,7 @@
|
||||
:on-stroke-cap-start-change on-stroke-cap-start-change
|
||||
:on-stroke-cap-end-change on-stroke-cap-end-change
|
||||
:on-stroke-cap-switch on-stroke-cap-switch
|
||||
:applied-tokens applied-tokens
|
||||
:applied-tokens (when (= 0 index) applied-tokens)
|
||||
:on-detach-token on-detach-token
|
||||
:on-remove on-remove
|
||||
:on-reorder handle-reorder
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.color :as clr]
|
||||
[app.common.types.shape.attrs :refer [default-color]]
|
||||
[app.common.types.token :as tk]
|
||||
[app.config :as cfg]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.colors :as dwc]
|
||||
@@ -27,6 +26,7 @@
|
||||
[app.main.ui.ds.utilities.swatch :refer [swatch*]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.workspace.tokens.management.forms.controls.utils :as csu]
|
||||
[app.util.color :as uc]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
@@ -176,12 +176,9 @@
|
||||
|
||||
active-tokens* (mf/use-ctx ctx/active-tokens-by-type)
|
||||
|
||||
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)))))
|
||||
tokens (mf/with-memo [active-tokens* origin]
|
||||
(csu/filter-tokens-for-input active-tokens* origin))
|
||||
|
||||
on-focus'
|
||||
(mf/use-fn
|
||||
(mf/deps on-focus)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.workspace.sidebar.options.common :as soc]
|
||||
[app.main.ui.workspace.sidebar.options.menus.input-wrapper-tokens :refer [numeric-input-wrapper*]]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row*]]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
@@ -92,14 +93,13 @@
|
||||
|
||||
on-width-change
|
||||
(mf/use-fn
|
||||
(mf/deps index on-stroke-width-change)
|
||||
(mf/deps index on-stroke-width-change ids)
|
||||
(fn [value]
|
||||
(if (or (string? value) (number? value))
|
||||
(on-stroke-width-change index value)
|
||||
|
||||
(st/emit! (dwta/toggle-token {:token (first value)
|
||||
:attrs #{:stroke-width}
|
||||
:shape-ids ids})))))
|
||||
(soc/emit-value-or-token
|
||||
value
|
||||
#(on-stroke-width-change index %)
|
||||
ids
|
||||
#{:stroke-width})))
|
||||
|
||||
stroke-alignment (or (:stroke-alignment stroke) :center)
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
(mf/use-fn
|
||||
(mf/deps on-detach-token)
|
||||
(fn [token]
|
||||
(on-detach-token (first token) #{:stroke-width})))
|
||||
(on-detach-token token #{:stroke-width})))
|
||||
|
||||
stroke-caps-options
|
||||
[{:value nil :label (tr "workspace.options.stroke-cap.none")}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
[token]
|
||||
{:id (str (get token :id))
|
||||
:type :token
|
||||
:resolved-value (get token :value)
|
||||
:resolved-value (get token :resolved-value)
|
||||
:name (get token :name)})
|
||||
|
||||
(defn- generate-dropdown-options
|
||||
@@ -53,7 +53,7 @@
|
||||
tokens)))
|
||||
|
||||
(defn- sort-groups-and-tokens
|
||||
"Sorts both the groups and the tokens inside them alphabetically.
|
||||
"Sorts the tokens inside the groups alphabetically.
|
||||
|
||||
Input:
|
||||
A map where:
|
||||
@@ -65,18 +65,18 @@
|
||||
:colors [{:name \"azul\"} {:name \"rojo\"}]}
|
||||
|
||||
Output:
|
||||
A sorted map where:
|
||||
- groups are ordered alphabetically by key
|
||||
A map which:
|
||||
- tokens inside each group are sorted alphabetically by :name
|
||||
|
||||
Example output:
|
||||
{:colors [{:name \"azul\"} {:name \"rojo\"}]
|
||||
:dimensions [{:name \"quini\"} {:name \"tres\"}]}"
|
||||
{:dimensions [{:name \"quini\"} {:name \"tres\"}]
|
||||
:colors [{:name \"azul\"} {:name \"rojo\"}]}"
|
||||
|
||||
[groups->tokens]
|
||||
(into (sorted-map) ;; ensure groups are ordered alphabetically by their key
|
||||
(for [[group tokens] groups->tokens]
|
||||
[group (sort-by :name tokens)])))
|
||||
(reduce (fn [acc [group tokens]]
|
||||
(assoc acc group (sort-by :name tokens)))
|
||||
{}
|
||||
groups->tokens))
|
||||
|
||||
(defn get-token-dropdown-options
|
||||
[tokens filter-term]
|
||||
@@ -94,9 +94,15 @@
|
||||
(defn filter-tokens-for-input
|
||||
[raw-tokens input-type]
|
||||
(delay
|
||||
(-> (deref raw-tokens)
|
||||
(select-keys (get cto/tokens-by-input input-type))
|
||||
(not-empty))))
|
||||
(let [raw-tokens (deref raw-tokens)
|
||||
key-order (get cto/tokens-by-input input-type)]
|
||||
(-> (reduce (fn [acc k]
|
||||
(if (contains? raw-tokens k)
|
||||
(assoc acc k (get raw-tokens k))
|
||||
acc))
|
||||
(array-map)
|
||||
key-order)
|
||||
(not-empty)))))
|
||||
|
||||
(defn focusable-options [options]
|
||||
(filter #(= (:type %) :token) options))
|
||||
Reference in New Issue
Block a user