0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-11 07:11:32 -05:00

Move token change events to changes ns

This commit is contained in:
Florian Schroedl 2024-07-24 15:46:14 +02:00
parent 56e72b5247
commit b392c3ba65
5 changed files with 142 additions and 173 deletions

View file

@ -6,13 +6,14 @@
(ns app.main.ui.workspace.tokens.changes
(:require
[app.common.types.token :as ctt]
[app.common.types.shape.radius :as ctsr]
[app.common.types.token :as ctt]
[app.main.data.tokens :as dt]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace :as udw]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.transforms :as dwt]
[app.main.data.workspace.undo :as dwu]
[app.main.store :as st]
[app.main.ui.workspace.tokens.core :as wtc]
[app.main.ui.workspace.tokens.style-dictionary :as sd]
@ -24,6 +25,67 @@
;; Token Updates ---------------------------------------------------------------
(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] :as _props}]
(ptk/reify ::apply-token
ptk/WatchEvent
(watch [_ state _]
(->> (rx/from (sd/resolve-tokens+ (get-in state [:workspace-data :tokens])))
(rx/mapcat
(fn [sd-tokens]
(let [undo-id (js/Symbol)
resolved-value (-> (get sd-tokens (:id token))
(wtt/resolve-token-value))
tokenized-attributes (wtt/attributes-map attributes (:id token))]
(rx/of
(dwu/start-undo-transaction undo-id)
(dch/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
(on-update-shape resolved-value shape-ids attributes))
(dwu/commit-undo-transaction undo-id)))))))))
(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 % (wtt/remove-attributes-for-token-id attributes (:id token) %))]
(dch/update-shapes
shape-ids
(fn [shape]
(update shape :applied-tokens remove-token))))))))
(defn toggle-token
[{:keys [token-type-props token shapes] :as _props}]
(ptk/reify ::on-toggle-token
ptk/WatchEvent
(watch [_ _ _]
(let [{:keys [attributes on-update-shape]} token-type-props
unapply-tokens? (wtt/shapes-token-applied? token shapes (:attributes token-type-props))
shape-ids (map :id shapes)]
(if unapply-tokens?
(rx/of
(unapply-token {:attributes attributes
:token token
:shape-ids shape-ids}))
(rx/of
(apply-token {:attributes attributes
:token token
:shape-ids shape-ids
:on-update-shape on-update-shape})))))))
(defn on-apply-token [{:keys [token token-type-props selected-shapes] :as _props}]
(let [{:keys [attributes on-apply on-update-shape]
:or {on-apply dt/update-token-from-attributes}} token-type-props
@ -125,9 +187,9 @@
:attributes attributes)
:else token-type-props)]
(wtc/on-apply-token {:token token
:token-type-props updated-token-type-props
:selected-shapes selected-shapes})))
(on-apply-token {:token token
:token-type-props updated-token-type-props
:selected-shapes selected-shapes})))
(defn update-layout-sizing-limits [value shape-ids attributes]
(ptk/reify ::update-layout-sizing-limits

View file

@ -16,7 +16,6 @@
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.icons :as i]
[app.main.ui.workspace.tokens.changes :as wtch]
[app.main.ui.workspace.tokens.core :as wtc]
[app.main.ui.workspace.tokens.token :as wtt]
[app.main.ui.workspace.tokens.token-types :as wtty]
[app.util.dom :as dom]
@ -45,8 +44,8 @@
{:title title
:selected? selected?
:action #(if selected?
(st/emit! (wtc/unapply-token props))
(st/emit! (wtc/apply-token (assoc props :on-update-shape on-update-shape))))}))
(st/emit! (wtch/unapply-token props))
(st/emit! (wtch/apply-token (assoc props :on-update-shape on-update-shape))))}))
attributes)))
(defn all-or-sepearate-actions [{:keys [attribute-labels on-update-shape-all on-update-shape]}
@ -59,8 +58,8 @@
{:title "All"
:selected? all-selected?
:action #(if all-selected?
(st/emit! (wtc/unapply-token props))
(st/emit! (wtc/apply-token (assoc props :on-update-shape (or on-update-shape-all on-update-shape)))))})
(st/emit! (wtch/unapply-token props))
(st/emit! (wtch/apply-token (assoc props :on-update-shape (or on-update-shape-all on-update-shape)))))})
single-actions (map (fn [[attr title]]
(let [selected? (selected-pred attr)]
{:title title
@ -70,10 +69,10 @@
:shape-ids shape-ids}
event (cond
all-selected? (-> (assoc props :attributes-to-remove attributes)
(wtc/apply-token))
selected? (wtc/unapply-token props)
(wtch/apply-token))
selected? (wtch/unapply-token props)
:else (-> (assoc props :on-update-shape on-update-shape)
(wtc/apply-token)))]
(wtch/apply-token)))]
(st/emit! event))}))
attribute-labels)]
(concat [all-action] single-actions)))
@ -102,19 +101,19 @@
:token token
:shape-ids shape-ids}]
(if all-selected?
(st/emit! (wtc/unapply-token props))
(st/emit! (wtc/apply-token (assoc props :on-update-shape on-update-shape))))))}
(st/emit! (wtch/unapply-token props))
(st/emit! (wtch/apply-token (assoc props :on-update-shape on-update-shape))))))}
{:title "Horizontal"
:selected? horizontal-padding-selected?
:action (fn []
(let [props {:token token
:shape-ids shape-ids}
event (cond
all-selected? (wtc/apply-token (assoc props :attributes-to-remove vertical-attributes))
horizontal-padding-selected? (wtc/apply-token (assoc props :attributes-to-remove horizontal-attributes))
:else (wtc/apply-token (assoc props
:attributes horizontal-attributes
:on-update-shape on-update-shape)))]
all-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attributes))
horizontal-padding-selected? (wtch/apply-token (assoc props :attributes-to-remove horizontal-attributes))
:else (wtch/apply-token (assoc props
:attributes horizontal-attributes
:on-update-shape on-update-shape)))]
(st/emit! event)))}
{:title "Vertical"
:selected? vertical-padding-selected?
@ -122,11 +121,11 @@
(let [props {:token token
:shape-ids shape-ids}
event (cond
all-selected? (wtc/apply-token (assoc props :attributes-to-remove vertical-attributes))
vertical-padding-selected? (wtc/apply-token (assoc props :attributes-to-remove vertical-attributes))
:else (wtc/apply-token (assoc props
:attributes vertical-attributes
:on-update-shape on-update-shape)))]
all-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attributes))
vertical-padding-selected? (wtch/apply-token (assoc props :attributes-to-remove vertical-attributes))
:else (wtch/apply-token (assoc props
:attributes vertical-attributes
:on-update-shape on-update-shape)))]
(st/emit! event)))}]
single-padding-items (->> padding-attrs
(map (fn [[attr title]]
@ -145,10 +144,10 @@
:shape-ids shape-ids}
event (cond
all-selected? (-> (assoc props :attributes-to-remove all-padding-attrs)
(wtc/apply-token))
selected? (wtc/unapply-token props)
(wtch/apply-token))
selected? (wtch/unapply-token props)
:else (-> (assoc props :on-update-shape on-update-shape)
(wtc/apply-token)))]
(wtch/apply-token)))]
(st/emit! event))}))))
gap-items (all-or-sepearate-actions {:attribute-labels {:column-gap "Column Gap"
:row-gap "Row Gap"}

View file

@ -6,25 +6,12 @@
(ns app.main.ui.workspace.tokens.core
(:require
[app.common.data :as d :refer [ordered-map]]
[app.common.types.shape.radius :as ctsr]
[app.common.types.token :as ctt]
[app.main.data.tokens :as dt]
[app.main.data.workspace :as udw]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.data.workspace.transforms :as dwt]
[app.main.data.workspace.undo :as dwu]
[app.common.data :as d]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.workspace.tokens.style-dictionary :as sd]
[app.main.ui.workspace.tokens.token :as wtt]
[app.util.dom :as dom]
[app.util.webapi :as wapi]
[beicon.v2.core :as rx]
[cuerdas.core :as str]
[potok.v2.core :as ptk]
[promesa.core :as p]))
[cuerdas.core :as str]))
;; Helpers ---------------------------------------------------------------------
@ -48,86 +35,6 @@
(cond-> (assoc item :label name)
(wtt/token-applied? item shape (or selected-attributes attributes)) (assoc :selected? true))))))
;; Events ----------------------------------------------------------------------
(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] :as _props}]
(ptk/reify ::apply-token
ptk/WatchEvent
(watch [_ state _]
(->> (rx/from (sd/resolve-tokens+ (get-in state [:workspace-data :tokens])))
(rx/mapcat
(fn [sd-tokens]
(let [undo-id (js/Symbol)
resolved-value (-> (get sd-tokens (:id token))
(resolve-token-value))
tokenized-attributes (wtt/attributes-map attributes (:id token))]
(rx/of
(dwu/start-undo-transaction undo-id)
(dch/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
(on-update-shape resolved-value shape-ids attributes))
(dwu/commit-undo-transaction undo-id)))))))))
(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 % (wtt/remove-attributes-for-token-id attributes (:id token) %))]
(dch/update-shapes
shape-ids
(fn [shape]
(update shape :applied-tokens remove-token))))))))
(defn toggle-token
[{:keys [token-type-props token shapes] :as _props}]
(ptk/reify ::on-toggle-token
ptk/WatchEvent
(watch [_ _ _]
(let [{:keys [attributes on-update-shape]} token-type-props
unapply-tokens? (wtt/shapes-token-applied? token shapes (:attributes token-type-props))
shape-ids (map :id shapes)]
(if unapply-tokens?
(rx/of
(unapply-token {:attributes attributes
:token token
:shape-ids shape-ids}))
(rx/of
(apply-token {:attributes attributes
:token token
:shape-ids shape-ids
:on-update-shape on-update-shape})))))))
(defn on-apply-token [{:keys [token token-type-props selected-shapes] :as _props}]
(let [{:keys [attributes on-apply on-update-shape]
:or {on-apply dt/update-token-from-attributes}} token-type-props
shape-ids (->> selected-shapes
(eduction
(remove #(wtt/shapes-token-applied? token % attributes))
(map :id)))]
(p/let [sd-tokens (sd/resolve-workspace-tokens+ {:debug? true})]
(let [resolved-token (get sd-tokens (:id token))
resolved-token-value (resolve-token-value resolved-token)]
(doseq [shape selected-shapes]
(st/emit! (on-apply {:token-id (:id token)
:shape-id (:id shape)
:attributes attributes}))
(on-update-shape resolved-token-value shape-ids attributes))))))
;; JSON export functions -------------------------------------------------------
(defn encode-tokens

View file

@ -14,6 +14,7 @@
[app.main.store :as st]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.main.ui.workspace.tokens.changes :as wtch]
[app.main.ui.workspace.tokens.core :as wtc]
[app.main.ui.workspace.tokens.style-dictionary :as sd]
[app.main.ui.workspace.tokens.token :as wtt]
@ -100,9 +101,9 @@
(dom/stop-propagation event)
(when (seq selected-shapes)
(st/emit!
(wtc/toggle-token {:token token
:shapes selected-shapes
:token-type-props token-type-props})))))
(wtch/toggle-token {:token token
:shapes selected-shapes
:token-type-props token-type-props})))))
tokens-count (count tokens)]
[:div {:on-click on-toggle-open-click}
[:& cmm/asset-section {:icon (mf/fnc icon-wrapper [_]

View file

@ -34,14 +34,14 @@
(let [file (setup-file)
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtc/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file :token-1)
:on-update-shape wtch/update-shape-radius-all})
(wtc/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file :token-2)
:on-update-shape wtch/update-shape-radius-all})]]
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file :token-1)
:on-update-shape wtch/update-shape-radius-all})
(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file :token-2)
:on-update-shape wtch/update-shape-radius-all})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -62,18 +62,18 @@
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [;; Apply `:token-1` to all border radius attributes
(wtc/apply-token {:attributes #{:rx :ry :r1 :r2 :r3 :r4}
:token (toht/get-token file :token-1)
:shape-ids [(:id rect-1)]
:on-update-shape wtch/update-shape-radius-all})
(wtch/apply-token {:attributes #{:rx :ry :r1 :r2 :r3 :r4}
:token (toht/get-token file :token-1)
:shape-ids [(:id rect-1)]
:on-update-shape wtch/update-shape-radius-all})
;; Apply single `:r1` attribute to same shape
;; while removing other attributes from the border-radius set
;; but keep `:r4` for testing purposes
(wtc/apply-token {:attributes #{:r1}
:attributes-to-remove #{:rx :ry :r1 :r2 :r3}
:token (toht/get-token file :token-2)
:shape-ids [(:id rect-1)]
:on-update-shape wtch/update-shape-radius-all})]]
(wtch/apply-token {:attributes #{:r1}
:attributes-to-remove #{:rx :ry :r1 :r2 :r3}
:token (toht/get-token file :token-2)
:shape-ids [(:id rect-1)]
:on-update-shape wtch/update-shape-radius-all})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -95,10 +95,10 @@
(let [file (setup-file)
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtc/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file :token-2)
:on-update-shape wtch/update-shape-radius-all})]]
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rx :ry}
:token (toht/get-token file :token-2)
:on-update-shape wtch/update-shape-radius-all})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -121,10 +121,10 @@
:type :dimensions}))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtc/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:width :height}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-shape-dimensions})]]
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:width :height}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-shape-dimensions})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -147,10 +147,10 @@
:type :sizing}))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtc/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:width :height}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-shape-dimensions})]]
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:width :height}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-shape-dimensions})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -173,10 +173,10 @@
:type :opacity}))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtc/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:opacity}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-opacity})]]
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:opacity}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-opacity})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -198,10 +198,10 @@
:type :rotation}))
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
events [(wtc/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rotation}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-rotation})]]
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
:attributes #{:rotation}
:token (toht/get-token file :token-target)
:on-update-shape wtch/update-rotation})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -220,10 +220,10 @@
store (ths/setup-store file)
rect-1 (cths/get-shape file :rect-1)
rect-2 (cths/get-shape file :rect-2)
events [(wtc/toggle-token {:shapes [rect-1 rect-2]
:token-type-props {:attributes #{:rx :ry}
:on-update-shape wtch/update-shape-radius-all}
:token (toht/get-token file :token-2)})]]
events [(wtch/toggle-token {:shapes [rect-1 rect-2]
:token-type-props {:attributes #{:rx :ry}
:on-update-shape wtch/update-shape-radius-all}
:token (toht/get-token file :token-2)})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -253,9 +253,9 @@
rect-without-token (cths/get-shape file :rect-2)
rect-with-other-token (cths/get-shape file :rect-3)
events [(wtc/toggle-token {:shapes [rect-with-token rect-without-token rect-with-other-token]
:token (toht/get-token file :token-1)
:token-type-props {:attributes #{:rx :ry}}})]]
events [(wtch/toggle-token {:shapes [rect-with-token rect-without-token rect-with-other-token]
:token (toht/get-token file :token-1)
:token-type-props {:attributes #{:rx :ry}}})]]
(tohs/run-store-async
store done events
(fn [new-state]
@ -287,9 +287,9 @@
rect-without-token (cths/get-shape file :rect-2)
rect-with-other-token-2 (cths/get-shape file :rect-3)
events [(wtc/toggle-token {:shapes [rect-with-other-token-1 rect-without-token rect-with-other-token-2]
:token (toht/get-token file :token-1)
:token-type-props {:attributes #{:rx :ry}}})]]
events [(wtch/toggle-token {:shapes [rect-with-other-token-1 rect-without-token rect-with-other-token-2]
:token (toht/get-token file :token-1)
:token-type-props {:attributes #{:rx :ry}}})]]
(tohs/run-store-async
store done events
(fn [new-state]