♻️ Add needed changes to get tokens from sidebar

This reverts commit afe149f702148d86d1dea6cb6a537917ce7202aa.
This commit is contained in:
Andrey Antukh
2025-08-26 17:17:01 +02:00
committed by Eva Marco
parent 9686075104
commit 07904bcc5d
14 changed files with 259 additions and 30 deletions

View File

@@ -468,3 +468,25 @@
"Predicate if a typography composite token is a reference value - a string pointing to another reference token."
[token-value]
(string? token-value))
(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}
:x #{:spacing :dimensions}
:y #{:spacing :dimensions}
: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}
:font-size #{:font-size}
:letter-spacing #{:letter-spacing}})

View File

@@ -417,7 +417,6 @@
;; FIXME: this with effect with trigger all the time because
;; `config` will be always a different instance
(mf/with-effect [tokens config]
(let [cached (get @cache-atom tokens)]
(cond

View File

@@ -38,6 +38,138 @@
[potok.v2.core :as ptk]))
(declare token-properties)
(declare update-layout-item-margin)
;; Events to apply / unapply tokens to shapes ------------------------------------------------------------
(defn apply-token
"Apply `attributes` that match `token` for `shape-ids`.
Optionally remove attributes from `attributes-to-remove`,
this is useful for applying a single attribute from an attributes set
while removing other applied tokens from this set."
[{:keys [attributes attributes-to-remove token shape-ids on-update-shape]}]
(ptk/reify ::apply-token
ptk/WatchEvent
(watch [_ state _]
;; We do not allow to apply tokens while text editor is open.
(when (empty? (get state :workspace-editor-state))
(let [attributes-to-remove
;; Remove atomic typography tokens when applying composite and vice-verca
(cond
(ctt/typography-token-keys (:type token)) (set/union attributes-to-remove ctt/typography-keys)
(ctt/typography-keys (:type token)) (set/union attributes-to-remove ctt/typography-token-keys)
:else attributes-to-remove)]
(when-let [tokens (some-> (dsh/lookup-file-data state)
(get :tokens-lib)
(ctob/get-tokens-in-active-sets))]
(->> (sd/resolve-tokens tokens)
(rx/mapcat
(fn [resolved-tokens]
(let [undo-id (js/Symbol)
objects (dsh/lookup-page-objects state)
selected-shapes (select-keys objects shape-ids)
shape-ids (or (->> selected-shapes
(filter (fn [[_ shape]]
(or
(and (ctsl/any-layout-immediate-child? objects shape)
(some ctt/spacing-margin-keys attributes))
(ctt/any-appliable-attr? attributes (:type shape)))))
(keys))
[])
resolved-value (get-in resolved-tokens [(cft/token-identifier token) :resolved-value])
tokenized-attributes (cft/attributes-map attributes token)
type (:type token)]
(rx/concat
(rx/of
(st/emit! (ev/event {::ev/name "apply-tokens"
:type type
:applyed-to attributes}))
(dwu/start-undo-transaction undo-id)
(dwsh/update-shapes shape-ids (fn [shape]
(cond-> shape
attributes-to-remove
(update :applied-tokens #(apply (partial dissoc %) attributes-to-remove))
:always
(update :applied-tokens merge tokenized-attributes)))))
(when on-update-shape
(let [res (on-update-shape resolved-value shape-ids attributes)]
;; Composed updates return observables and need to be executed differently
(if (rx/observable? res)
res
(rx/of res))))
(rx/of (dwu/commit-undo-transaction undo-id)))))))))))))
(defn apply-spacing-token
"Handles edge-case for spacing token when applying token via toggle button.
Splits out `shape-ids` into seperate default actions:
- Layouts take the `default` update function
- Shapes inside layout will only take margin"
[{:keys [token shapes]}]
(ptk/reify ::apply-spacing-token
ptk/WatchEvent
(watch [_ state _]
(let [objects (dsh/lookup-page-objects state)
{:keys [attributes on-update-shape]}
(get token-properties (:type token))
{:keys [other frame-children]}
(group-by #(if (ctsl/any-layout-immediate-child? objects %) :frame-children :other) shapes)]
(rx/of
(apply-token {:attributes attributes
:token token
:shape-ids (map :id other)
:on-update-shape on-update-shape})
(apply-token {:attributes ctt/spacing-margin-keys
:token token
:shape-ids (map :id frame-children)
:on-update-shape update-layout-item-margin}))))))
(defn unapply-token
"Removes `attributes` that match `token` for `shape-ids`.
Doesn't update shape attributes."
[{:keys [attributes token shape-ids] :as _props}]
(ptk/reify ::unapply-token
ptk/WatchEvent
(watch [_ _ _]
(rx/of
(let [remove-token #(when % (cft/remove-attributes-for-token attributes token %))]
(dwsh/update-shapes
shape-ids
(fn [shape]
(update shape :applied-tokens remove-token))))))))
(defn toggle-token
[{:keys [token shapes attrs]}]
(ptk/reify ::on-toggle-token
ptk/WatchEvent
(watch [_ _ _]
(let [{:keys [attributes all-attributes on-update-shape]}
(get token-properties (:type token))
unapply-tokens?
(cft/shapes-token-applied? token shapes (or all-attributes attributes))
shape-ids (map :id shapes)]
(if unapply-tokens?
(rx/of
(unapply-token {:attributes (or attrs all-attributes attributes)
:token token
:shape-ids shape-ids}))
(rx/of
(case (:type token)
:spacing
(apply-spacing-token {:token token
:shapes shapes})
(apply-token {:attributes (or attrs attributes)
:token token
:shape-ids shape-ids
:on-update-shape on-update-shape}))))))))
;; Events to update the value of attributes with applied tokens ---------------------------------------------------------

View File

@@ -14,10 +14,12 @@
[app.common.logic.shapes :as cls]
[app.common.types.shape :as cts]
[app.common.types.shape.layout :as ctl]
[app.common.types.token :as tk]
[app.main.constants :refer [size-presets]]
[app.main.data.workspace :as udw]
[app.main.data.workspace.interactions :as dwi]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.tokens.application :as dwta]
[app.main.data.workspace.transforms :as dwt]
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs]
@@ -25,7 +27,9 @@
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.context :as muc]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.controls.numeric-input :as ni]
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.workspace.sidebar.options.menus.border-radius :refer [border-radius-menu*]]
@@ -87,12 +91,31 @@
shape)]
(select-keys shape measure-attrs)))
(mf/defc numeric-input-wrapper*
{::mf/private true}
[{:keys [values name applied-tokens] :rest props}]
(let [tokens (mf/use-ctx muc/active-tokens-by-type)
tokens (mf/with-memo [tokens name]
(delay
(-> (deref tokens)
(select-keys (get tk/tokens-by-input name))
(not-empty))))
props (mf/spread-props props
{:placeholder (if (or (= :multiple (:applied-tokens values))
(= :multiple (get values name)))
(tr "settings.multiple") "--")
:class (stl/css :numeric-input-measures)
:applied-token (get applied-tokens name)
:tokens tokens
:value (get values name)})]
[:> ni/numeric-input* props]))
(def ^:private xf:map-type (map :type))
(def ^:private xf:mapcat-type-to-options (mapcat type->options))
(mf/defc measures-menu*
{::mf/memo true}
[{:keys [ids values type shapes]}]
[{:keys [ids values applied-tokens type shapes]}]
(let [all-types
(mf/with-memo [type shapes]
;; We only need this when multiple type is used
@@ -284,12 +307,20 @@
(mf/use-fn
(mf/deps ids)
(fn [value attr]
(st/emit! (udw/trigger-bounding-box-cloaking ids))
(binding [cts/*wasm-sync* true]
(run! #(do-position-change %1 value attr) shapes))))
(if (or (string? value) (int? value))
(do (st/emit! (udw/trigger-bounding-box-cloaking ids))
(binding [cts/*wasm-sync* true]
(run! #(do-position-change %1 value attr) shapes)))
(do
(let [value2 (:resolved-value value)]
(st/emit! (udw/trigger-bounding-box-cloaking ids)
(dwta/toggle-token {:token value
:attrs #{attr}
:shapes shapes}))
(binding [cts/*wasm-sync* true]
(run! #(do-position-change %1 value2 attr) shapes)))))))
;; ROTATION
on-rotation-change
(mf/use-fn
(mf/deps ids)
@@ -310,6 +341,15 @@
on-pos-y-change
(mf/use-fn (mf/deps on-position-change) #(on-position-change % :y))
on-detach-token
(mf/use-fn
(mf/deps ids)
(fn [token attr]
;; Review this, detach is having problems
(let [shape-ids (map :id shapes)]
(st/emit! (dwta/unapply-token {:token token
:attributes #{attr}
:shape-ids shape-ids})))))
;; CLIP CONTENT AND SHOW IN VIEWER
on-change-clip-content
(mf/use-fn
@@ -421,31 +461,30 @@
:disabled (= proportion-lock :multiple)
:aria-label (if proportion-lock (tr "workspace.options.size.unlock") (tr "workspace.options.size.lock"))
:on-click on-proportion-lock-change}]])
(when (options :position)
[:div {:class (stl/css :position)}
[:div {:class (stl/css-case :x-position true
:disabled disabled-position?)
:title (tr "workspace.options.x")}
[:span {:class (stl/css :icon-text)} "X"]
[:> numeric-input* {:no-validate true
:placeholder (if (= :multiple (:x values)) (tr "settings.multiple") "--")
:on-change on-pos-x-change
:disabled disabled-position?
:class (stl/css :numeric-input)
:value (:x values)}]]
[:> numeric-input-wrapper*
{:disabled disabled-position?
:on-change on-position-change
:on-detach on-detach-token
:icon "character-x"
:name :x
:property (tr "workspace.options.x")
:applied-tokens applied-tokens
:values values}]
[:div {:class (stl/css-case :y-position true
:disabled disabled-position?)
:title (tr "workspace.options.y")}
[:span {:class (stl/css :icon-text)} "Y"]
[:> numeric-input* {:no-validate true
:placeholder (if (= :multiple (:y values)) (tr "settings.multiple") "--")
:disabled disabled-position?
:on-change on-pos-y-change
:class (stl/css :numeric-input)
:value (:y values)}]]])
(when (or (options :rotation)
(options :radius))
[:> numeric-input-wrapper*
{:disabled disabled-position?
:on-change on-position-change
:on-detach on-detach-token
:icon "character-y"
:name :y
:property (tr "workspace.options.y")
:applied-tokens applied-tokens
:values values}]])
(when (or (options :rotation) (options :radius))
[:div {:class (stl/css :rotation-radius)}
(when (options :rotation)
[:div {:class (stl/css :rotation)

View File

@@ -187,3 +187,7 @@
.checkbox-button {
@extend .button-icon;
}
.numeric-input-measures {
--dropdown-width: 247px;
}

View File

@@ -29,6 +29,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
measure-values
(select-keys shape measure-attrs)
@@ -84,6 +87,7 @@
:values layer-values}]
[:> measures-menu* {:ids ids
:applied-tokens applied-tokens
:type type
:values measure-values
:shapes shapes}]

View File

@@ -30,6 +30,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
measure-values
(select-keys shape measure-attrs)
@@ -84,6 +87,7 @@
:values layer-values}]
[:> measures-menu* {:ids ids
:applied-tokens applied-tokens
:type type
:values measure-values
:shapes shapes}]

View File

@@ -33,6 +33,9 @@
ids (mf/with-memo [shape-id] [shape-id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
stroke-values
(select-keys shape stroke-attrs)
@@ -99,6 +102,7 @@
:type shape-type
:values layer-values}]
[:> measures-menu* {:ids ids
:applied-tokens applied-tokens
:values measure-values
:type shape-type
:shapes shapes}]

View File

@@ -37,6 +37,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
objects
(mf/with-memo [shapes-with-children]
(d/index-by :id shapes-with-children))
@@ -111,6 +114,7 @@
:values layer-values}]
[:> measures-menu* {:type type
:ids measure-ids
:applied-tokens applied-tokens
:values measure-values
:shapes shapes}]

View File

@@ -420,7 +420,7 @@
;; also don't use the memoized version of get-attrs because it
;; makes no sense because the shapes object are changed on
;; each rerender.
[measure-ids measure-values]
[measure-ids measure-values measure-tokens]
(get-attrs* shapes objects :measure)]
[:div {:class (stl/css :options)}
@@ -434,6 +434,7 @@
{:type type
:ids measure-ids
:values measure-values
:applied-tokens measure-tokens
:shapes shapes}])
(when (some? components)

View File

@@ -30,6 +30,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
measure-values
(select-keys shape measure-attrs)
@@ -85,6 +88,7 @@
:values layer-values}]
[:> measures-menu* {:ids ids
:type type
:applied-tokens applied-tokens
:values measure-values
:shapes shapes}]

View File

@@ -30,6 +30,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
measure-values
(select-keys shape measure-attrs)
@@ -86,6 +89,7 @@
[:> measures-menu* {:ids ids
:type type
:values measure-values
:applied-tokens applied-tokens
:shapes shapes}]
[:& layout-container-menu

View File

@@ -95,6 +95,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
{:keys [tag] :as content}
(get shape :content)
@@ -153,6 +156,7 @@
[:*
[:> measures-menu* {:ids ids
:type type
:applied-tokens applied-tokens
:values measure-values
:shapes shapes}]

View File

@@ -35,6 +35,9 @@
ids (mf/with-memo [id] [id])
shapes (mf/with-memo [shape] [shape])
applied-tokens
(get shape :applied-tokens)
measure-values
(select-keys shape measure-attrs)
@@ -132,6 +135,7 @@
[:> measures-menu*
{:ids ids
:type type
:applied-tokens applied-tokens
:values measure-values
:shapes shapes}]