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