mirror of
https://github.com/penpot/penpot.git
synced 2025-06-10 15:31:38 +02:00
Merge pull request #5840 from penpot/niwinz-tokens-changes-3
♻️ Token changes (part 3)
This commit is contained in:
commit
2ffb77cb4d
5 changed files with 316 additions and 291 deletions
|
@ -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!
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue