Merge pull request #5840 from penpot/niwinz-tokens-changes-3

♻️ Token changes (part 3)
This commit is contained in:
Eva Marco 2025-02-14 12:55:12 +01:00 committed by GitHub
commit 2ffb77cb4d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 316 additions and 291 deletions

View file

@ -44,17 +44,13 @@
(defn group-item
"Add a group to the item name, in the form group.name."
[item group-name separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(update item :name #(str group-name separator %)))
(assert (valid-groupable-item? item) "expected groupable item")
(update item :name #(dm/str group-name separator %)))
(defn ungroup-item
"Remove the first group from the item name."
[item separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(assert (valid-groupable-item? item) "expected groupable item")
(update item :name #(-> %
(split-path separator)
(rest)
@ -63,9 +59,7 @@
(defn get-path
"Get the groups part of the name as a vector. E.g. group.subgroup.name -> ['group' 'subgroup']"
[item separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(assert (valid-groupable-item? item) "expected groupable item")
(split-path (:name item) separator))
(defn get-groups-str
@ -78,9 +72,7 @@
(defn get-final-name
"Get the final part of the name. E.g. group.subgroup.name -> name"
[item separator]
(dm/assert!
"expected groupable item"
(valid-groupable-item? item))
(assert (valid-groupable-item? item) "expected groupable item")
(-> (:name item)
(split-path separator)
(last)))
@ -94,9 +86,7 @@
"Get all children of a group of a grouping tree. Each child is
a tuple [name item], where item "
[group]
(dm/assert!
"expected group node"
(group? group))
(assert (group? group) "expected group node")
(seq group))
;; === Token
@ -114,36 +104,37 @@
(defrecord Token [name type value description modified-at])
(def schema:token
[:and
(defn token?
[o]
(instance? Token o))
(def schema:token-attrs
[:map {:title "Token"}
[:name cto/token-name-ref]
[:type [::sm/one-of cto/token-types]]
[:value :any]
[:description [:maybe :string]]
[:modified-at ::sm/inst]]
[:fn (partial instance? Token)]])
[:modified-at ::sm/inst]])
(sm/register! ::token schema:token)
(def schema:token
[:and
schema:token-attrs
[:fn token?]])
(def valid-token?
(sm/validator schema:token))
(def check-token
(sm/check-fn schema:token :hint "expected valid token"))
(def check-token!
(sm/check-fn ::token))
(def ^:private check-token-attrs
(sm/check-fn schema:token-attrs :hint "expected valid params for token"))
(defn make-token
[& {:keys [] :as params}]
(let [params (-> params
[& {:as attrs}]
(-> attrs
(dissoc :id) ;; we will remove this when old data structures are removed
(update :modified-at #(or % (dt/now))))
token (map->Token params)]
(dm/assert!
"expected valid token"
(check-token! token))
token))
(update :modified-at #(or % (dt/now)))
(update :description d/nilv "")
(check-token-attrs)
(map->Token)))
(defn find-token-value-references
"Returns set of token references found in `token-value`.
@ -336,17 +327,16 @@
tokens))
(add-token [_ token]
(dm/assert! "expected valid token" (check-token! token))
(let [token (check-token token)]
(TokenSet. name
description
(dt/now)
(assoc tokens (:name token) token)))
(assoc tokens (:name token) token))))
(update-token [this token-name f]
(if-let [token (get tokens token-name)]
(let [token' (-> (make-token (f token))
(assoc :modified-at (dt/now)))]
(check-token! token')
(TokenSet. name
description
(dt/now)
@ -382,36 +372,44 @@
"$type" (cto/token-type->dtcg-token-type (:type token))}
(:description token) (assoc "$description" (:description token)))))))
(def schema:token-set
[:and [:map {:title "TokenSet"}
(defn token-set?
[o]
(instance? TokenSet o))
(def schema:token-set-attrs
[:map {:title "TokenSet"}
[:name :string]
[:description [:maybe :string]]
[:modified-at ::sm/inst]
[:tokens [:and [:map-of {:gen/max 5} :string ::token]
[:fn d/ordered-map?]]]]
[:fn (partial instance? TokenSet)]])
[:tokens [:and
[:map-of {:gen/max 5} :string schema:token]
[:fn d/ordered-map?]]]])
(def schema:token-set
[:and
schema:token-set-attrs
[:fn token-set?]])
(sm/register! ::token-set schema:token-set)
(def valid-token-set?
(sm/validator schema:token-set))
(def check-token-set!
(sm/check-fn ::token-set))
(def check-token-set
(sm/check-fn schema:token-set :hint "expected valid token set"))
(def ^:private check-token-set-attrs
(sm/check-fn schema:token-set-attrs :hint "expected valid params for token-set"))
(defn make-token-set
[& {:keys [] :as params}]
(let [params (-> params
[& {:as attrs}]
(-> attrs
(dissoc :id)
(update :modified-at #(or % (dt/now)))
(update :tokens #(into (d/ordered-map) %)))
token-set (map->TokenSet params)]
(dm/assert!
"expected valid token set"
(check-token-set! token-set))
token-set))
(update :tokens #(into (d/ordered-map) %))
(update :description d/nilv "")
(check-token-set-attrs)
(map->TokenSet)))
;; === TokenSets (collection)
@ -455,22 +453,16 @@
[:fn d/ordered-map?]]]}}
[:ref ::node]])
(sm/register! ::token-set-node schema:token-set-node)
(def schema:token-sets
[:and
[:map-of {:title "TokenSets"}
:string ::token-set-node]
:string
schema:token-set-node]
[:fn d/ordered-map?]])
(sm/register! ::token-sets schema:token-sets)
(def valid-token-sets?
(sm/validator schema:token-sets))
(def check-token-sets!
(sm/check-fn ::token-sets))
;; === TokenTheme
(def theme-separator "/")
@ -549,23 +541,34 @@
(hidden-temporary-theme? [this]
(theme-matches-group-name this hidden-token-theme-group hidden-token-theme-name)))
(def schema:token-theme
[:and [:map {:title "TokenTheme"}
(defn token-theme?
[o]
(instance? TokenTheme o))
(def schema:token-theme-attrs
[:map {:title "TokenTheme"}
[:name :string]
[:group :string]
[:description [:maybe :string]]
[:is-source [:maybe :boolean]]
[:modified-at ::sm/inst]
[:sets [:set {:gen/max 5} :string]]]
[:fn (partial instance? TokenTheme)]])
[:sets [:set {:gen/max 5} :string]]])
(def schema:token-theme
[:and
schema:token-theme-attrs
[:fn token-theme?]])
(sm/register! ::token-theme schema:token-theme)
(def valid-token-theme?
(sm/validator schema:token-theme))
(def check-token-theme!
(sm/check-fn ::token-theme))
(def check-token-theme
(sm/check-fn schema:token-theme :hint "expected a valid token-theme"))
(def ^:private check-token-theme-attrs
(sm/check-fn schema:token-theme-attrs :hint "expected valid params for token-theme"))
(def top-level-theme-group-name
"Top level theme groups have an empty string as the theme group."
@ -575,26 +578,23 @@
(= group top-level-theme-group-name))
(defn make-token-theme
[& {:keys [] :as params}]
(let [params (-> params
[& {:as attrs}]
(-> attrs
(dissoc :id)
(update :group #(or % top-level-theme-group-name))
(update :is-source #(or % false))
(update :group d/nilv top-level-theme-group-name)
(update :is-source d/nilv false)
(update :modified-at #(or % (dt/now)))
(update :sets #(into #{} %)))
token-theme (map->TokenTheme params)]
(dm/assert!
"expected valid token theme"
(check-token-theme! token-theme))
token-theme))
(update :sets set)
(update :description d/nilv "")
(check-token-theme-attrs)
(map->TokenTheme)))
(defn make-hidden-token-theme
[& {:keys [] :as params}]
(make-token-theme (assoc params
:group hidden-token-theme-group
:name hidden-token-theme-name)))
[& {:as attrs}]
(-> attrs
(assoc :group hidden-token-theme-group)
(assoc :name hidden-token-theme-name)
(make-token-theme)))
;; === TokenThemes (collection)
@ -606,8 +606,7 @@
(get-theme-tree [_] "get a nested tree of all themes in the library")
(get-themes [_] "get an ordered sequence of all themes in the library")
(get-theme [_ group name] "get one theme looking for name")
(get-hidden-theme [_] "get the theme hidden from the user ,
used for managing active sets without a user created theme.")
(get-hidden-theme [_] "get the theme hidden from the user, used for managing active sets without a user created theme.")
(get-theme-groups [_] "get a sequence of group names by order")
(get-active-theme-paths [_] "get the active theme paths")
(get-active-themes [_] "get an ordered sequence of active themes in the library")
@ -620,23 +619,18 @@ used for managing active sets without a user created theme.")
(def schema:token-themes
[:and
[:map-of {:title "TokenThemes"}
:string [:and [:map-of :string ::token-theme]
:string [:and [:map-of :string schema:token-theme]
[:fn d/ordered-map?]]]
[:fn d/ordered-map?]])
(sm/register! ::token-themes schema:token-themes)
(def valid-token-themes?
(sm/validator schema:token-themes))
(def check-token-themes!
(sm/check-fn ::token-themes))
(def schema:active-token-themes
[:set string?])
(def ^:private schema:active-themes
[:set :string])
(def valid-active-token-themes?
(sm/validator schema:active-token-themes))
(sm/validator schema:active-themes))
;; === Import / Export from DTCG format
@ -869,17 +863,14 @@ Will return a value that matches this schema:
ITokenSets
(add-set [_ token-set]
(dm/assert! "expected valid token set" (check-token-set! token-set))
(let [path (get-token-set-prefixed-path token-set)]
(let [path (get-token-set-prefixed-path token-set)
token-set (check-token-set token-set)]
(TokensLib. (d/oassoc-in sets path token-set)
themes
active-themes)))
(add-sets [this token-sets]
(reduce
(fn [lib set]
(add-set lib set))
this token-sets))
(reduce add-set this token-sets))
(update-set [this set-name f]
(let [prefixed-full-path (set-name->prefixed-full-path set-name)
@ -889,7 +880,6 @@ Will return a value that matches this schema:
(assoc :modified-at (dt/now)))
prefixed-full-path' (get-token-set-prefixed-path set')
name-changed? (not= (:name set) (:name set'))]
(check-token-set! set')
(if name-changed?
(TokensLib. (-> sets
(d/oassoc-in-before prefixed-full-path prefixed-full-path' set')
@ -1061,10 +1051,10 @@ Will return a value that matches this schema:
ITokenThemes
(add-theme [_ token-theme]
(dm/assert! "expected valid token theme" (check-token-theme! token-theme))
(let [token-theme (check-token-theme token-theme)]
(TokensLib. sets
(update themes (:group token-theme) d/oassoc (:name token-theme) token-theme)
active-themes))
active-themes)))
(update-theme [this group name f]
(let [theme (dm/get-in themes [group name])]
@ -1076,7 +1066,6 @@ Will return a value that matches this schema:
same-group? (= group group')
same-name? (= name name')
same-path? (and same-group? same-name?)]
(check-token-theme! theme')
(TokensLib. sets
(if same-path?
(update themes group' assoc name' theme')
@ -1164,7 +1153,6 @@ Will return a value that matches this schema:
(some? (get-in sets (set-group-path->set-group-prefixed-path set-path))))
(add-token-in-set [this set-name token]
(dm/assert! "expected valid token instance" (check-token! token))
(update-set this set-name #(add-token % token)))
(get-token-in-set [this set-name token-name]
@ -1304,6 +1292,7 @@ Will return a value that matches this schema:
(into tokens' (map (fn [x] [(:name x) x]) (get-tokens set))))
{} (get-sets this)))
;; FIXME: revisit if this still necessary
(validate [_]
(and (valid-token-sets? sets)
(valid-token-themes? themes)
@ -1314,11 +1303,14 @@ Will return a value that matches this schema:
(and (instance? TokensLib o)
(validate o)))
(defn check-tokens-lib!
[lib]
(dm/assert!
"expected valid tokens lib"
(valid-tokens-lib? lib)))
(def ^:private check-token-sets
(sm/check-fn schema:token-sets :hint "expected valid token sets"))
(def ^:private check-token-themes
(sm/check-fn schema:token-themes :hint "expected valid token themes"))
(def ^:private check-active-themes
(sm/check-fn schema:active-themes :hint "expected valid active themes"))
(defn make-tokens-lib
"Create an empty or prepopulated tokens library."
@ -1333,13 +1325,11 @@ Will return a value that matches this schema:
:active-themes #{}))
([& {:keys [sets themes active-themes]}]
(let [tokens-lib (TokensLib. sets themes (or active-themes #{}))]
(dm/assert!
"expected valid tokens lib"
(valid-tokens-lib? tokens-lib))
tokens-lib)))
(let [active-themes (d/nilv active-themes #{})]
(TokensLib.
(check-token-sets sets)
(check-token-themes themes)
(check-active-themes active-themes)))))
(defn ensure-tokens-lib
[tokens-lib]
@ -1353,10 +1343,11 @@ Will return a value that matches this schema:
(def type:tokens-lib
{:type ::tokens-lib
:pred valid-tokens-lib?
:type-properties {:encode/json encode-dtcg
:type-properties
{:encode/json encode-dtcg
:decode/json decode-dtcg}})
(sm/register! ::tokens-lib type:tokens-lib)
(sm/register! type:tokens-lib)
;; === Serialization handlers for RPC API (transit) and database (fressian)
@ -1369,17 +1360,17 @@ Will return a value that matches this schema:
{:id "penpot/token-set"
:class TokenSet
:wfn #(into {} %)
:rfn #(make-token-set %)}
:rfn #(map->TokenSet %)}
{:id "penpot/token-theme"
:class TokenTheme
:wfn #(into {} %)
:rfn #(make-token-theme %)}
:rfn #(map->TokenTheme %)}
{:id "penpot/token"
:class Token
:wfn #(into {} %)
:rfn #(make-token %)})
:rfn #(map->Token %)})
#?(:clj
(fres/add-handlers!

View file

@ -37,23 +37,21 @@
(t/is (= (:name token1) "test-token-1"))
(t/is (= (:type token1) :boolean))
(t/is (= (:value token1) true))
(t/is (nil? (:description token1)))
(t/is (= (:description token1) ""))
(t/is (some? (:modified-at token1)))
(t/is (ctob/valid-token? token1))
(t/is (ctob/check-token token1))
(t/is (= (:name token2) "test-token-2"))
(t/is (= (:type token2) :numeric))
(t/is (= (:value token2) 66))
(t/is (= (:description token2) "test description"))
(t/is (= (:modified-at token2) now))
(t/is (ctob/valid-token? token2))))
(t/is (ctob/check-token token2))))
(t/testing "invalid-tokens"
(let [args {:name 777
:type :invalid}]
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid token"
(apply ctob/make-token args)))
(t/is (false? (ctob/valid-token? {})))))
(let [params {:name 777 :type :invalid}]
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid params for token"
(ctob/make-token params)))))
(t/testing "find-token-value-references"
(t/testing "finds references inside curly braces in a string"
@ -75,7 +73,7 @@
:tokens [])]
(t/is (= (:name token-set1) "test-token-set-1"))
(t/is (nil? (:description token-set1)))
(t/is (= (:description token-set1) ""))
(t/is (some? (:modified-at token-set1)))
(t/is (empty? (:tokens token-set1)))
@ -85,10 +83,9 @@
(t/is (empty? (:tokens token-set2)))))
(t/testing "invalid-token-set"
(let [args {:name 777
:description 999}]
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid token set"
(apply ctob/make-token-set args)))))
(let [params {:name 777 :description 999}]
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid params for token-set"
(ctob/make-token-set params)))))
(t/testing "move-token-set"
(t/testing "flat"
@ -192,7 +189,7 @@
(t/is (= (:name token-theme1) "test-token-theme-1"))
(t/is (= (:group token-theme1) ""))
(t/is (nil? (:description token-theme1)))
(t/is (= (:description token-theme1) ""))
(t/is (false? (:is-source token-theme1)))
(t/is (some? (:modified-at token-theme1)))
(t/is (empty? (:sets token-theme1)))
@ -205,12 +202,12 @@
(t/is (empty? (:sets token-theme2)))))
(t/testing "invalid-token-theme"
(let [args {:name 777
(let [params {:name 777
:group nil
:description 999
:is-source 42}]
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid token theme"
(apply ctob/make-token-theme args))))))
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid params for token-theme"
(ctob/make-token-theme params))))))
(t/deftest tokens-lib
@ -219,10 +216,9 @@
(t/is (= (ctob/set-count tokens-lib) 0))))
(t/testing "invalid-tokens-lib"
(let [args {:sets nil
:themes nil}]
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid tokens lib"
(apply ctob/make-tokens-lib args))))))
(let [params {:sets nil :themes nil}]
(t/is (thrown-with-msg? #?(:cljs js/Error :clj Exception) #"expected valid token sets"
(ctob/make-tokens-lib params))))))
(t/testing "token-set in a lib"
@ -413,7 +409,7 @@
(t/is (= (count (:tokens token-set')) 2))
(t/is (= (d/index-of (keys (:tokens token-set')) "updated-name") 0))
(t/is (= (:name token') "updated-name"))
(t/is (= (:description token') nil))
(t/is (= (:description token') ""))
(t/is (= (:value token') true))
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
@ -757,7 +753,7 @@
(t/is (= (ctob/set-count tokens-lib') 1))
(t/is (= (:name token') "group1.updated-name"))
(t/is (= (:description token') nil))
(t/is (= (:description token') ""))
(t/is (= (:value token') true))
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
@ -792,7 +788,7 @@
(t/is (= (ctob/set-count tokens-lib') 1))
(t/is (= (d/index-of (keys (:tokens token-set')) "group2.updated-name") 1))
(t/is (= (:name token') "group2.updated-name"))
(t/is (= (:description token') nil))
(t/is (= (:description token') ""))
(t/is (= (:value token') true))
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
@ -930,7 +926,7 @@
(t/is (= (count group1') 3))
(t/is (= (d/index-of (keys group1') "S-updated-name") 0))
(t/is (= (:name token-set') "group1/updated-name"))
(t/is (= (:description token-set') nil))
(t/is (= (:description token-set') ""))
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))
sets-tree'))
@ -961,7 +957,7 @@
(t/is (= (count group2') 1))
(t/is (nil? (get group1' "S-updated-name")))
(t/is (= (:name token-set') "group2/updated-name"))
(t/is (= (:description token-set') nil))
(t/is (= (:description token-set') ""))
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))))
(t/testing "delete-set-in-group"
@ -1097,7 +1093,7 @@
(t/is (= (d/index-of (keys group1') "updated-name") 0))
(t/is (= (:name token-theme') "updated-name"))
(t/is (= (:group token-theme') "group1"))
(t/is (= (:description token-theme') nil))
(t/is (= (:description token-theme') ""))
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
(t/testing "move-theme-of-group"
@ -1127,7 +1123,7 @@
(t/is (= (d/index-of (keys group2') "updated-name") 0))
(t/is (= (:name token-theme') "updated-name"))
(t/is (= (:group token-theme') "group2"))
(t/is (= (:description token-theme') nil))
(t/is (= (:description token-theme') ""))
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
(t/testing "delete-theme-in-group"
@ -1166,7 +1162,7 @@
{:name "colors.red.600"
:type :color
:value "#e53e3e"
:description nil}))
:description ""}))
(t/is (= (get-set-token "core" "spacing.multi-value")
{:name "spacing.multi-value"
:type :spacing
@ -1176,7 +1172,7 @@
{:name "button.primary.background"
:type :color
:value "{accent.default}"
:description nil})))
:description ""})))
(t/testing "invalid tokens got discarded"
(t/is (nil? (get-set-token "typography" "H1.Bold"))))))))
@ -1200,7 +1196,7 @@
{:name "colors.red.600"
:type :color
:value "#e53e3e"
:description nil}))
:description ""}))
(t/is (tht/token-data-eq? (get-set-token "core" "spacing.multi-value")
{:name "spacing.multi-value"
:type :spacing
@ -1210,7 +1206,7 @@
{:name "button.primary.background"
:type :color
:value "{accent.default}"
:description nil})))
:description ""})))
(t/testing "invalid tokens got discarded"
(t/is (nil? (get-set-token "typography" "H1.Bold"))))))
@ -1238,8 +1234,8 @@
:group "group-1"
:modified-at now
:sets #{"core"})))
expected (ctob/encode-dtcg tokens-lib)]
(t/is (= {"$themes" [{"description" nil
result (ctob/encode-dtcg tokens-lib)
expected {"$themes" [{"description" ""
"group" "group-1"
"is-source" false
"modified-at" now
@ -1248,7 +1244,8 @@
"$metadata" {"tokenSetOrder" ["core"]}
"core"
{"colors" {"red" {"600" {"$value" "#e53e3e"
"$type" "color"}}}
"$type" "color"
"$description" ""}}}
"spacing"
{"multi-value"
{"$value" "{dimension.sm} {dimension.xl}"
@ -1256,8 +1253,10 @@
"$description" "You can have multiple values in a single spacing token"}}
"button"
{"primary" {"background" {"$value" "{accent.default}"
"$type" "color"}}}}}
expected))))
"$type" "color"
"$description" ""}}}}}]
(t/is (= expected result))))
(t/testing "encode-decode-dtcg-json"
(with-redefs [dt/now (constantly #inst "2024-10-16T12:01:20.257840055-00:00")]

View file

@ -18,7 +18,6 @@
[app.main.data.helpers :as dsh]
[app.main.data.notifications :as ntf]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.tokens.selected-set :as dwts]
[app.main.ui.workspace.tokens.update :as wtu]
[app.util.i18n :refer [tr]]
[beicon.v2.core :as rx]
@ -38,6 +37,14 @@
(-> (dsh/lookup-file-data state)
(get :tokens-lib)))
(defn lookup-token-set
([state]
(when-let [selected (dm/get-in state [:workspace-tokens :selected-token-set-name])]
(lookup-token-set state selected)))
([state name]
(some-> (get-tokens-lib state)
(ctob/get-set name))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Helpers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -233,49 +240,72 @@
(rx/of
(drop-error (ex-data e))))))))
;; FIXME: the the name is very confusing
(defn update-create-token
[{:keys [token prev-token-name]}]
(ptk/reify ::update-create-token
(defn- create-token-with-set
"A special case when a first token is created and no set exists"
[token]
(ptk/reify ::create-token-and-set
ptk/WatchEvent
(watch [_ _ _]
(let [set-name "Global"
token-set
(-> (ctob/make-token-set :name set-name)
(ctob/add-token token))
hidden-theme
(ctob/make-hidden-token-theme :sets [set-name])
changes
(pcb/add-token-set (pcb/empty-changes) token-set)
changes
(-> changes
(pcb/add-token-theme hidden-theme)
(pcb/update-active-token-themes #{ctob/hidden-token-theme-path} #{}))]
(rx/of (set-selected-token-set-name set-name)
(dch/commit-changes changes))))))
(defn create-token
[params]
(let [token (ctob/make-token params)]
(ptk/reify ::create-token
ptk/WatchEvent
(watch [it state _]
(if-let [token-set (lookup-token-set state)]
(let [data (dsh/lookup-file-data state)
selected (dm/get-in state [:workspace-tokens :selected-token-set-name])
tokens-lib (get-tokens-lib state)
token-set (if selected
(some-> tokens-lib (ctob/get-set selected))
(some-> tokens-lib (ctob/get-sets) (first)))
set-name (or (:name token-set) "Global")
changes (if (not token-set)
;; No set created add a global set
(let [token-set (ctob/make-token-set :name set-name :tokens {(:name token) token})
hidden-theme (ctob/make-hidden-token-theme :sets [set-name])
active-theme-paths (some-> tokens-lib ctob/get-active-theme-paths)
add-to-hidden-theme? (= active-theme-paths #{ctob/hidden-token-theme-path})
base-changes (pcb/add-token-set (pcb/empty-changes) token-set)]
(cond
(not tokens-lib)
(-> base-changes
(pcb/add-token-theme hidden-theme)
(pcb/update-active-token-themes #{ctob/hidden-token-theme-path} #{}))
add-to-hidden-theme?
(let [prev-hidden-theme (ctob/get-theme tokens-lib ctob/hidden-token-theme-group ctob/hidden-token-theme-name)]
(-> base-changes
(pcb/update-token-theme (ctob/toggle-set prev-hidden-theme ctob/hidden-token-theme-path) prev-hidden-theme)))
:else base-changes))
(-> (pcb/empty-changes it)
changes (-> (pcb/empty-changes it)
(pcb/with-library-data data)
(pcb/set-token set-name (or prev-token-name (:name token)) token)))]
(pcb/set-token (:name token-set)
(:name token)
token))]
(rx/of
(set-selected-token-set-name set-name)
(when-not prev-token-name
(ptk/event ::ev/event {::ev/name "create-tokens"}))
(dch/commit-changes changes))))))
(rx/of (dch/commit-changes changes)
(ptk/data-event ::ev/event {::ev/name "create-token"})))
(rx/of (create-token-with-set token)))))))
(defn update-token
[name params]
(assert (string? name) "expected string for `name`")
(ptk/reify ::update-token
ptk/WatchEvent
(watch [it state _]
(let [token-set (lookup-token-set state)
data (dsh/lookup-file-data state)
token (ctob/get-token token-set name)
token' (->> (merge token params)
(into {})
(ctob/make-token))
changes (-> (pcb/empty-changes it)
(pcb/with-library-data data)
(pcb/set-token (:name token-set)
(:name token)
token'))]
(rx/of (dch/commit-changes changes))))))
(defn delete-token
[set-name token-name]
@ -296,21 +326,23 @@
(ptk/reify ::duplicate-token
ptk/WatchEvent
(watch [_ state _]
(let [token-set (dwts/get-selected-token-set state)
token (some-> token-set (ctob/get-token token-name))
tokens (some-> token-set (ctob/get-tokens))
suffix-fn (fn [copy-count]
(when-let [token-set (lookup-token-set state)]
(when-let [token (ctob/get-token token-set token-name)]
(let [tokens (ctob/get-tokens token-set)
unames (map :name tokens)
suffix-fn
(fn [copy-count]
(let [suffix (tr "workspace.token.duplicate-suffix")]
(str/concat "-"
suffix
(when (> copy-count 1)
(str "-" copy-count)))))
unames (map :name tokens)
copy-name (cfh/generate-unique-name token-name unames :suffix-fn suffix-fn)]
(when token
(rx/of
(update-create-token
{:token (assoc token :name copy-name)})))))))
copy-name
(cfh/generate-unique-name token-name unames :suffix-fn suffix-fn)]
(rx/of (create-token (assoc token :name copy-name)))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TOKEN UI OPS

View file

@ -397,13 +397,20 @@
;; The result should be a vector of all resolved validations
;; We do not handle the error case as it will be handled by the components validations
(when (and (seq result) (not err))
(st/emit! (dt/update-create-token {:token (ctob/make-token :name final-name
:type (or (:type token) token-type)
(st/emit!
(if (ctob/token? token)
(dt/update-token (:name token)
{:name final-name
:value final-value
:description final-description)
:prev-token-name (:name token)}))
(st/emit! (wtu/update-workspace-tokens))
(modal/hide!))))))))
:description final-description})
(dt/create-token {:name final-name
:type token-type
:value final-value
:description final-description}))
(wtu/update-workspace-tokens)
(modal/hide)))))))))
on-delete-token
(mf/use-fn
(mf/deps selected-token-set-name)

View file

@ -203,10 +203,11 @@
store (ths/setup-store file)
;; ==== Action
events [(dt/update-create-token {:token (ctob/make-token :name "test-token-1"
events [(dt/set-selected-token-set-name "test-token-set")
(dt/update-token "test-token-1"
{:name "test-token-1"
:type :border-radius
:value 66)
:prev-token-name "test-token-1"})]
:value 66})]
step2 (fn [_]
(let [events2 [(wtu/update-workspace-tokens)
@ -358,30 +359,25 @@
store (ths/setup-store file)
;; ==== Action
events [(dt/update-create-token {:token (ctob/make-token :name "token-radius"
:type :border-radius
:value 30)
:prev-token-name "token-radius"})
(dt/update-create-token {:token (ctob/make-token :name "token-rotation"
:type :rotation
:value 45)
:prev-token-name "token-rotation"})
(dt/update-create-token {:token (ctob/make-token :name "token-opacity"
:type :opacity
:value 0.9)
:prev-token-name "token-opacity"})
(dt/update-create-token {:token (ctob/make-token :name "token-stroke-width"
:type :stroke-width
:value 8)
:prev-token-name "token-stroke-width"})
(dt/update-create-token {:token (ctob/make-token :name "token-color"
:type :color
:value "#ff0000")
:prev-token-name "token-color"})
(dt/update-create-token {:token (ctob/make-token :name "token-dimensions"
:type :dimensions
:value 200)
:prev-token-name "token-dimensions"})]
events [(dt/set-selected-token-set-name "test-token-set")
(dt/update-token "token-radius"
{:name "token-radius"
:value 30})
(dt/update-token "token-rotation"
{:name "token-rotation"
:value 45})
(dt/update-token "token-opacity"
{:name "token-opacity"
:value 0.9})
(dt/update-token "token-stroke-width"
{:name "token-stroke-width"
:value 8})
(dt/update-token "token-color"
{:name "token-color"
:value "#ff0000"})
(dt/update-token "token-dimensions"
{:name "token-dimensions"
:value 200})]
step2 (fn [_]
(let [events2 [(wtu/update-workspace-tokens)