mirror of
https://github.com/penpot/penpot.git
synced 2025-04-05 11:31:35 -05:00
Merge pull request #290 from tokens-studio/refactor-themes-sets
Refactor themes sets
This commit is contained in:
commit
d58932c2e5
34 changed files with 1028 additions and 1074 deletions
|
@ -258,7 +258,7 @@
|
|||
[:update-active-token-themes
|
||||
[:map {:title "UpdateActiveTokenThemes"}
|
||||
[:type [:= :update-active-token-themes]]
|
||||
[:theme-ids [:set ::sm/uuid]]]]
|
||||
[:theme-ids [:set :string]]]]
|
||||
|
||||
[:delete-temporary-token-theme
|
||||
[:map {:title "DeleteTemporaryTokenThemeChange"}
|
||||
|
@ -274,14 +274,14 @@
|
|||
[:mod-token-theme
|
||||
[:map {:title "ModTokenThemeChange"}
|
||||
[:type [:= :mod-token-theme]]
|
||||
[:id ::sm/uuid]
|
||||
[:group :string]
|
||||
[:name :string]
|
||||
[:token-theme ::ctot/token-theme]]]
|
||||
|
||||
[:del-token-theme
|
||||
[:map {:title "DelTokenThemeChange"}
|
||||
[:type [:= :del-token-theme]]
|
||||
[:id ::sm/uuid]
|
||||
[:group :string]
|
||||
[:name :string]]]
|
||||
|
||||
[:add-token-set
|
||||
|
@ -292,29 +292,24 @@
|
|||
[:mod-token-set
|
||||
[:map {:title "ModTokenSetChange"}
|
||||
[:type [:= :mod-token-set]]
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:token-set ::ctot/token-set]]]
|
||||
|
||||
[:del-token-set
|
||||
[:map {:title "DelTokenSetChange"}
|
||||
[:type [:= :del-token-set]]
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]]]
|
||||
|
||||
[:add-token
|
||||
[:map {:title "AddTokenChange"}
|
||||
[:type [:= :add-token]]
|
||||
[:set-id ::sm/uuid]
|
||||
[:set-name :string]
|
||||
[:token ::cto/token]]]
|
||||
|
||||
[:mod-token
|
||||
[:map {:title "ModTokenChange"}
|
||||
[:type [:= :mod-token]]
|
||||
[:set-id ::sm/uuid]
|
||||
[:set-name :string]
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:token ::cto/token]]]
|
||||
|
||||
|
@ -322,7 +317,6 @@
|
|||
[:map {:title "DelTokenChange"}
|
||||
[:type [:= :del-token]]
|
||||
[:set-name :string]
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]]]]])
|
||||
|
||||
(sm/register! ::changes
|
||||
|
@ -793,131 +787,89 @@
|
|||
;; -- Tokens
|
||||
|
||||
(defmethod process-change :add-token
|
||||
[data {:keys [set-id set-name token]}]
|
||||
(-> data
|
||||
(ctol/add-token set-id token)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-token-in-set set-name (ctob/make-token token))))))
|
||||
[data {:keys [set-name token]}]
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-token-in-set set-name (ctob/make-token token)))))
|
||||
|
||||
(defmethod process-change :mod-token
|
||||
[data {:keys [set-name id name token]}]
|
||||
(-> data
|
||||
(ctol/update-token id merge token)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/update-token-in-set
|
||||
set-name
|
||||
name
|
||||
(fn [old-token]
|
||||
(ctob/make-token (merge old-token token))))))))
|
||||
[data {:keys [set-name name token]}]
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/update-token-in-set
|
||||
set-name
|
||||
name
|
||||
(fn [old-token]
|
||||
(ctob/make-token (merge old-token token)))))))
|
||||
|
||||
(defmethod process-change :del-token
|
||||
[data {:keys [set-name id name]}]
|
||||
(-> data
|
||||
(ctol/delete-token id)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-token-from-set
|
||||
set-name
|
||||
name)))))
|
||||
|
||||
(defn- set-ids->names
|
||||
[data sets]
|
||||
(let [lib-sets (:token-sets-index data)
|
||||
set-id->name
|
||||
(fn [set-id]
|
||||
(dm/get-in lib-sets [set-id :name]))]
|
||||
(map set-id->name sets)))
|
||||
[data {:keys [set-name name]}]
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-token-from-set
|
||||
set-name
|
||||
name))))
|
||||
|
||||
(defmethod process-change :add-temporary-token-theme
|
||||
[data {:keys [token-theme]}]
|
||||
(-> data
|
||||
(ctotl/add-temporary-token-theme token-theme)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-theme (-> token-theme
|
||||
(update :sets (partial set-ids->names data))
|
||||
(ctob/make-token-theme)))))))
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-theme (ctob/make-token-theme token-theme)))))
|
||||
|
||||
(defmethod process-change :update-active-token-themes
|
||||
[data {:keys [theme-ids]}]
|
||||
(ctotl/assoc-active-token-themes data theme-ids))
|
||||
(update data :tokens-lib #(-> % (ctob/ensure-tokens-lib)
|
||||
(ctob/set-active-themes theme-ids))))
|
||||
|
||||
(defmethod process-change :delete-temporary-token-theme
|
||||
[data {:keys [id group name]}]
|
||||
(-> data
|
||||
(ctotl/delete-temporary-token-theme id)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-theme group name)))))
|
||||
[data {:keys [group name]}]
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-theme group name))))
|
||||
|
||||
(defmethod process-change :add-token-theme
|
||||
[data {:keys [token-theme]}]
|
||||
(-> data
|
||||
(ctotl/add-token-theme token-theme)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-theme (-> token-theme
|
||||
(update :sets (partial set-ids->names data))
|
||||
(ctob/make-token-theme)))))))
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-theme (-> token-theme
|
||||
(ctob/make-token-theme))))))
|
||||
|
||||
(defmethod process-change :mod-token-theme
|
||||
[data {:keys [id name group token-theme]}]
|
||||
(-> data
|
||||
(ctotl/update-token-theme id merge token-theme)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/update-theme name group
|
||||
(fn [prev-theme]
|
||||
(merge prev-theme
|
||||
(-> token-theme
|
||||
(update :sets (partial set-ids->names data))))))))))
|
||||
[data {:keys [name group token-theme]}]
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/update-theme group name
|
||||
(fn [prev-theme]
|
||||
(merge prev-theme token-theme))))))
|
||||
|
||||
(defmethod process-change :del-token-theme
|
||||
[data {:keys [id group name]}]
|
||||
(-> data
|
||||
(ctotl/delete-token-theme id)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-theme group name)))))
|
||||
[data {:keys [group name]}]
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-theme group name))))
|
||||
|
||||
(defmethod process-change :add-token-set
|
||||
[data {:keys [token-set]}]
|
||||
(-> data
|
||||
(ctotl/add-token-set token-set)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set token-set))))))
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set token-set)))))
|
||||
|
||||
(defmethod process-change :mod-token-set
|
||||
[data {:keys [id name token-set]}]
|
||||
(-> data
|
||||
(ctotl/update-token-set id merge token-set)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/update-set name (fn [prev-set]
|
||||
(merge prev-set
|
||||
(dissoc token-set :tokens))))))))
|
||||
[data {:keys [name token-set]}]
|
||||
(update data :tokens-lib (fn [lib]
|
||||
(let [path-changed? (not= name (:name token-set))
|
||||
lib' (-> lib
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/update-set name (fn [prev-set]
|
||||
(merge prev-set (dissoc token-set :tokens)))))]
|
||||
(cond-> lib'
|
||||
path-changed? (ctob/update-set-name name (:name token-set)))))))
|
||||
|
||||
(defmethod process-change :del-token-set
|
||||
[data {:keys [id name]}]
|
||||
(-> data
|
||||
(ctotl/delete-token-set id)
|
||||
(update :tokens-lib
|
||||
#(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-set name)))))
|
||||
[data {:keys [name]}]
|
||||
(update data :tokens-lib #(-> %
|
||||
(ctob/ensure-tokens-lib)
|
||||
(ctob/delete-set name))))
|
||||
|
||||
;; === Operations
|
||||
(defmethod process-operation :set
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
[app.common.types.component :as ctk]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]))
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.types.tokens-lib :as ctob]))
|
||||
|
||||
;; Auxiliary functions to help create a set of changes (undo + redo)
|
||||
|
||||
|
@ -713,23 +714,28 @@
|
|||
[changes token-theme]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :add-token-theme :token-theme token-theme})
|
||||
(update :undo-changes conj {:type :del-token-theme :id (:id token-theme) :name (:name token-theme)})
|
||||
(update :undo-changes conj {:type :del-token-theme :group (:group token-theme) :name (:name token-theme)})
|
||||
(apply-changes-local)))
|
||||
|
||||
(defn update-token-theme
|
||||
[changes token-theme prev-token-theme]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :mod-token-theme :id (:id token-theme) :name (:name prev-token-theme) :token-theme token-theme})
|
||||
(update :undo-changes conj {:type :mod-token-theme :id (:id token-theme) :name (:name token-theme) :token-theme (or prev-token-theme token-theme)})
|
||||
(apply-changes-local)))
|
||||
(let [name (or (:name prev-token-theme)
|
||||
(:name token-theme))
|
||||
group (or (:group prev-token-theme)
|
||||
(:group token-theme))]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :mod-token-theme :group group :name name :token-theme token-theme})
|
||||
(update :undo-changes conj {:type :mod-token-theme :group group :name name :token-theme (or prev-token-theme token-theme)})
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn delete-token-theme
|
||||
[changes token-theme-id]
|
||||
[changes group name]
|
||||
(assert-library! changes)
|
||||
(let [library-data (::library-data (meta changes))
|
||||
prev-token-theme (get-in library-data [:token-themes-index token-theme-id])]
|
||||
prev-token-theme (some-> (get library-data :tokens-lib)
|
||||
(ctob/get-theme group name))]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :del-token-theme :id token-theme-id :name (:name prev-token-theme)})
|
||||
(update :redo-changes conj {:type :del-token-theme :group group :name name})
|
||||
(update :undo-changes conj {:type :add-token-theme :token-theme prev-token-theme})
|
||||
(apply-changes-local))))
|
||||
|
||||
|
@ -737,48 +743,51 @@
|
|||
[changes token-set]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :add-token-set :token-set token-set})
|
||||
(update :undo-changes conj {:type :del-token-set :id (:id token-set) :name (:name token-set)})
|
||||
(update :undo-changes conj {:type :del-token-set :name (:name token-set)})
|
||||
(apply-changes-local)))
|
||||
|
||||
(defn update-token-set
|
||||
[changes token-set prev-token-set]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :mod-token-set :id (:id token-set) :name (:name prev-token-set) :token-set token-set})
|
||||
(update :undo-changes conj {:type :mod-token-set :id (:id token-set) :name (:name prev-token-set) :token-set (or prev-token-set token-set)})
|
||||
(update :redo-changes conj {:type :mod-token-set :name (:name prev-token-set) :token-set token-set})
|
||||
(update :undo-changes conj {:type :mod-token-set :name (:name token-set) :token-set (or prev-token-set token-set)})
|
||||
(apply-changes-local)))
|
||||
|
||||
(defn delete-token-set
|
||||
[changes token-set-id token-set-name]
|
||||
[changes token-set-name]
|
||||
(assert-library! changes)
|
||||
(let [library-data (::library-data (meta changes))
|
||||
prev-token-set (get-in library-data [:token-sets-index token-set-id])]
|
||||
prev-token-theme (some-> (get library-data :tokens-lib)
|
||||
(ctob/get-set token-set-name))]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :del-token-set :id token-set-id :name token-set-name})
|
||||
(update :undo-changes conj {:type :add-token-set :token-set prev-token-set})
|
||||
(update :redo-changes conj {:type :del-token-set :name token-set-name})
|
||||
(update :undo-changes conj {:type :add-token-set :token-set prev-token-theme})
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn add-token
|
||||
[changes set-id set-name token]
|
||||
[changes set-name token]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :add-token :set-id set-id :set-name set-name :token token})
|
||||
(update :undo-changes conj {:type :del-token :set-name set-name :id (:id token) :name (:name token)})
|
||||
(update :redo-changes conj {:type :add-token :set-name set-name :token token})
|
||||
(update :undo-changes conj {:type :del-token :set-name set-name :name (:name token)})
|
||||
(apply-changes-local)))
|
||||
|
||||
(defn update-token
|
||||
[changes set-id set-name {:keys [id name] :as token} {prev-name :name :as prev-token}]
|
||||
[changes set-name token prev-token]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :mod-token :set-id set-id :set-name set-name :id id :name prev-name :token token})
|
||||
(update :undo-changes conj {:type :mod-token :set-id set-id :set-name set-name :id id :name name :token (or prev-token token)})
|
||||
(update :redo-changes conj {:type :mod-token :set-name set-name :name (:name prev-token) :token token})
|
||||
(update :undo-changes conj {:type :mod-token :set-name set-name :name (:name token) :token (or prev-token token)})
|
||||
(apply-changes-local)))
|
||||
|
||||
(defn delete-token
|
||||
[changes set-name token-id token-name]
|
||||
[changes set-name token-name]
|
||||
(assert-library! changes)
|
||||
(let [library-data (::library-data (meta changes))
|
||||
prev-token (get-in library-data [:tokens token-id])]
|
||||
prev-token (some-> (get library-data :tokens-lib)
|
||||
(ctob/get-set set-name)
|
||||
(ctob/get-token token-name))]
|
||||
(-> changes
|
||||
(update :redo-changes conj {:type :del-token :set-name set-name :id token-id :name token-name})
|
||||
(update :undo-changes conj {:type :add-token :set-id uuid/zero :set-name set-name :token prev-token})
|
||||
(update :redo-changes conj {:type :del-token :set-name set-name :name token-name})
|
||||
(update :undo-changes conj {:type :add-token :set-name set-name :token prev-token})
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn add-component
|
||||
|
|
|
@ -64,22 +64,6 @@
|
|||
[:map-of {:gen/max 5} ::sm/uuid ::media-object]]
|
||||
[:plugin-data {:optional true}
|
||||
[:map-of {:gen/max 5} :keyword ::ctpg/plugin-data]]
|
||||
[:token-theme-temporary-id {:optional true}
|
||||
::sm/uuid]
|
||||
[:token-active-themes {:optional true :default #{}}
|
||||
[:set ::sm/uuid]]
|
||||
[:token-themes {:optional true}
|
||||
[:vector ::sm/uuid]]
|
||||
[:token-themes-index {:optional true}
|
||||
[:map-of {:gen/max 5} ::sm/uuid ::ctt/token-theme]]
|
||||
[:token-set-groups {:optional true}
|
||||
[:vector ::sm/uuid]]
|
||||
[:token-set-groups-index {:optional true}
|
||||
[:map-of {:gen/max 10} ::sm/uuid ::ctt/token-set-group]]
|
||||
[:token-sets-index {:optional true}
|
||||
[:map-of {:gen/max 10} ::sm/uuid ::ctt/token-set]]
|
||||
[:tokens {:optional true}
|
||||
[:map-of {:gen/max 100} ::sm/uuid ::cto/token]]
|
||||
[:tokens-lib {:optional true} ::ctl/tokens-lib]])
|
||||
|
||||
(def check-file-data!
|
||||
|
|
|
@ -58,13 +58,13 @@
|
|||
[n]
|
||||
(string? n))
|
||||
|
||||
;; TODO Move this to tokens-lib
|
||||
(sm/register! ::token
|
||||
[:map {:title "Token"}
|
||||
[:id ::sm/uuid]
|
||||
[:name token-name-ref]
|
||||
[:type [::sm/one-of token-types]]
|
||||
[:value :any]
|
||||
[:description {:optional true} :string]
|
||||
[:description {:optional true} [:maybe :string]]
|
||||
[:modified-at {:optional true} ::sm/inst]])
|
||||
|
||||
(sm/register! ::color
|
||||
|
|
|
@ -10,35 +10,16 @@
|
|||
|
||||
(sm/register! ::token-theme
|
||||
[:map {:title "TokenTheme"}
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:group {:optional true} :string]
|
||||
[:source? {:optional true} :boolean]
|
||||
[:description {:optional true} :string]
|
||||
[:group :string]
|
||||
[:description [:maybe :string]]
|
||||
[:is-source :boolean]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:sets [:set {:gen/max 10 :gen/min 1} ::sm/uuid]]])
|
||||
|
||||
(sm/register! ::token-set-group-ref
|
||||
[:map
|
||||
[:id ::sm/uuid]
|
||||
[:type [:= :group]]])
|
||||
|
||||
(sm/register! ::token-set-ref
|
||||
[:map
|
||||
[:id ::sm/uuid]
|
||||
[:type [:= :set]]])
|
||||
|
||||
(sm/register! ::token-set-group
|
||||
[:map {:title "TokenSetGroup"}
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:items [:vector {:gen/max 10 :gen/min 1}
|
||||
[:or ::token-set-group-ref ::token-set-ref]]]])
|
||||
[:sets :any]])
|
||||
|
||||
(sm/register! ::token-set
|
||||
[:map {:title "TokenSet"}
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:description {:optional true} :string]
|
||||
[:description {:optional true} [:maybe :string]]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:tokens [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]]])
|
||||
[:tokens :any]])
|
||||
|
|
|
@ -6,14 +6,16 @@
|
|||
|
||||
(ns app.common.types.tokens-lib
|
||||
(:require
|
||||
#?(:clj [app.common.fressian :as fres])
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as dt]
|
||||
[app.common.transit :as t]
|
||||
[app.common.types.token :as cto]
|
||||
[cuerdas.core :as str]
|
||||
#?(:clj [app.common.fressian :as fres])))
|
||||
[clojure.set :as set]
|
||||
[clojure.walk :as walk]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
;; === Groups handling
|
||||
|
||||
|
@ -102,10 +104,10 @@
|
|||
(def schema:token
|
||||
[:and
|
||||
[:map {:title "Token"}
|
||||
[:name cto/token-name-ref] ;; not necessary to have uuid
|
||||
[:name cto/token-name-ref]
|
||||
[:type [::sm/one-of cto/token-types]]
|
||||
[:value :any]
|
||||
[:description [:maybe :string]] ;; defrecord always have the attributes, even with nil value
|
||||
[:description [:maybe :string]]
|
||||
[:modified-at ::sm/inst]]
|
||||
[:fn (partial instance? Token)]])
|
||||
|
||||
|
@ -130,12 +132,27 @@
|
|||
|
||||
token))
|
||||
|
||||
(defn group-by-type [tokens]
|
||||
(let [tokens' (if (or (map? tokens)
|
||||
(d/ordered-map? tokens))
|
||||
(vals tokens)
|
||||
tokens)]
|
||||
(group-by :type tokens')))
|
||||
|
||||
(defn filter-by-type [token-type tokens]
|
||||
(let [token-type? #(= token-type (:type %))]
|
||||
(cond
|
||||
(d/ordered-map? tokens) (into (d/ordered-map) (filter (comp token-type? val) tokens))
|
||||
(map? tokens) (into {} (filter (comp token-type? val) tokens))
|
||||
:else (filter token-type? tokens))))
|
||||
|
||||
;; === Token Set
|
||||
|
||||
(defprotocol ITokenSet
|
||||
(add-token [_ token] "add a token at the end of the list")
|
||||
(update-token [_ token-name f] "update a token in the list")
|
||||
(delete-token [_ token-name] "delete a token from the list")
|
||||
(get-token [_ token-name] "return token by token-name")
|
||||
(get-tokens [_] "return an ordered sequence of all tokens in the set"))
|
||||
|
||||
(defrecord TokenSet [name description modified-at tokens]
|
||||
|
@ -168,6 +185,9 @@
|
|||
(dt/now)
|
||||
(dissoc tokens token-name)))
|
||||
|
||||
(get-token [_ token-name]
|
||||
(get tokens token-name))
|
||||
|
||||
(get-tokens [_]
|
||||
(vals tokens)))
|
||||
|
||||
|
@ -221,6 +241,7 @@
|
|||
(set-count [_] "get the total number if sets in the library")
|
||||
(get-set-tree [_] "get a nested tree of all sets in the library")
|
||||
(get-sets [_] "get an ordered sequence of all sets in the library")
|
||||
(get-ordered-set-names [_] "get an ordered sequence of all sets names in the library")
|
||||
(get-set [_ set-name] "get one set looking for name")
|
||||
(get-set-group [_ set-group-path] "get the attributes of a set group"))
|
||||
|
||||
|
@ -249,20 +270,55 @@
|
|||
|
||||
;; === TokenTheme
|
||||
|
||||
(def theme-separator "/")
|
||||
|
||||
(defn token-theme-path [group name]
|
||||
(join-path [group name] theme-separator))
|
||||
|
||||
(defn split-token-theme-path [path]
|
||||
(split-path path theme-separator))
|
||||
|
||||
(def hidden-token-theme-group
|
||||
"")
|
||||
|
||||
(def hidden-token-theme-name
|
||||
"__PENPOT__HIDDEN__TOKEN__THEME__")
|
||||
|
||||
(def hidden-token-theme-path
|
||||
(token-theme-path hidden-token-theme-group hidden-token-theme-name))
|
||||
|
||||
|
||||
(defprotocol ITokenTheme
|
||||
(toggle-set [_ set-name] "togle a set used / not used in the theme"))
|
||||
(set-sets [_ set-names] "set the active token sets")
|
||||
(toggle-set [_ set-name] "togle a set used / not used in the theme")
|
||||
(theme-path [_] "get `token-theme-path` from theme")
|
||||
(theme-matches-group-name [_ group name] "if a theme matches the given group & name")
|
||||
(hidden-temporary-theme? [_] "if a theme is the (from the user ui) hidden temporary theme"))
|
||||
|
||||
(defrecord TokenTheme [name group description is-source modified-at sets]
|
||||
ITokenTheme
|
||||
(toggle-set [_ set-name]
|
||||
(set-sets [_ set-names]
|
||||
(TokenTheme. name
|
||||
group
|
||||
description
|
||||
is-source
|
||||
(dt/now)
|
||||
(if (sets set-name)
|
||||
(disj sets set-name)
|
||||
(conj sets set-name)))))
|
||||
set-names))
|
||||
|
||||
(toggle-set [this set-name]
|
||||
(set-sets this (if (sets set-name)
|
||||
(disj sets set-name)
|
||||
(conj sets set-name))))
|
||||
|
||||
(theme-path [_]
|
||||
(token-theme-path group name))
|
||||
|
||||
(theme-matches-group-name [this group name]
|
||||
(and (= (:group this) group)
|
||||
(= (:name this) name)))
|
||||
|
||||
(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"}
|
||||
|
@ -271,8 +327,7 @@
|
|||
[:description [:maybe :string]]
|
||||
[:is-source :boolean]
|
||||
[:modified-at ::sm/inst]
|
||||
[:sets [:and [:set {:gen/max 5} :string]
|
||||
[:fn d/ordered-set?]]]]
|
||||
[:sets [:set {:gen/max 5} :string]]]
|
||||
[:fn (partial instance? TokenTheme)]])
|
||||
|
||||
(sm/register! ::token-theme schema:token-theme)
|
||||
|
@ -297,7 +352,7 @@
|
|||
(update :group #(or % top-level-theme-group-name))
|
||||
(update :is-source #(or % false))
|
||||
(update :modified-at #(or % (dt/now)))
|
||||
(update :sets #(into (d/ordered-set) %)))
|
||||
(update :sets #(into #{} %)))
|
||||
token-theme (map->TokenTheme params)]
|
||||
|
||||
(dm/assert!
|
||||
|
@ -306,6 +361,12 @@
|
|||
|
||||
token-theme))
|
||||
|
||||
(defn make-hidden-token-theme
|
||||
[& {:keys [] :as params}]
|
||||
(make-token-theme (assoc params
|
||||
:group hidden-token-theme-group
|
||||
:name hidden-token-theme-name)))
|
||||
|
||||
;; === TokenThemes (collection)
|
||||
|
||||
(defprotocol ITokenThemes
|
||||
|
@ -316,7 +377,14 @@
|
|||
(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-theme-groups [_] "get a sequence of group names by order"))
|
||||
(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")
|
||||
(set-active-themes [_ active-themes] "set active themes in library")
|
||||
(theme-active? [_ group name] "predicate if token theme is active")
|
||||
(activate-theme [_ group name] "adds theme from the active-themes")
|
||||
(deactivate-theme [_ group name] "removes theme from the active-themes")
|
||||
(toggle-theme-active? [_ group name] "toggles theme in the active-themes"))
|
||||
|
||||
(def schema:token-themes
|
||||
[:and
|
||||
|
@ -333,6 +401,12 @@
|
|||
(def check-token-themes!
|
||||
(sm/check-fn ::token-themes))
|
||||
|
||||
(def schema:active-token-themes
|
||||
[:set string?])
|
||||
|
||||
(def valid-active-token-themes?
|
||||
(sm/validator schema:active-token-themes))
|
||||
|
||||
;; === Tokens Lib
|
||||
|
||||
(defprotocol ITokensLib
|
||||
|
@ -341,20 +415,30 @@
|
|||
(update-token-in-set [_ set-name token-name f] "update a token in a set")
|
||||
(delete-token-from-set [_ set-name token-name] "delete a token from a set")
|
||||
(toggle-set-in-theme [_ group-name theme-name set-name] "toggle a set used / not used in a theme")
|
||||
(get-active-themes-set-names [_] "set of set names that are active in the the active themes")
|
||||
(get-active-themes-set-tokens [_] "set of set names that are active in the the active themes")
|
||||
(update-set-name [_ old-set-name new-set-name] "updates set name in themes")
|
||||
(validate [_]))
|
||||
|
||||
(deftype TokensLib [sets set-groups themes]
|
||||
(deftype TokensLib [sets set-groups themes active-themes]
|
||||
;; NOTE: This is only for debug purposes, pending to properly
|
||||
;; implement the toString and alternative printing.
|
||||
#?@(:clj [clojure.lang.IDeref
|
||||
(deref [_] {:sets sets :set-groups set-groups :themes themes})]
|
||||
(deref [_] {:sets sets
|
||||
:set-groups set-groups
|
||||
:themes themes
|
||||
:active-themes active-themes})]
|
||||
:cljs [cljs.core/IDeref
|
||||
(-deref [_] {:sets sets :set-groups set-groups :themes themes})])
|
||||
(-deref [_] {:sets sets
|
||||
:set-groups set-groups
|
||||
:themes themes
|
||||
:active-themes active-themes})])
|
||||
|
||||
#?@(:cljs [cljs.core/IEncodeJS
|
||||
(-clj->js [_] (js-obj "sets" (clj->js sets)
|
||||
"set-groups" (clj->js set-groups)
|
||||
"themes" (clj->js themes)))])
|
||||
"themes" (clj->js themes)
|
||||
"active-themes" (clj->js active-themes)))])
|
||||
|
||||
ITokenSets
|
||||
(add-set [_ token-set]
|
||||
|
@ -365,7 +449,8 @@
|
|||
(cond-> set-groups
|
||||
(not (str/empty? groups-str))
|
||||
(assoc groups-str (make-token-set-group)))
|
||||
themes)))
|
||||
themes
|
||||
active-themes)))
|
||||
|
||||
(update-set [this set-name f]
|
||||
(let [path (split-path set-name "/")
|
||||
|
@ -381,14 +466,16 @@
|
|||
(d/oassoc-in-before path path' set')
|
||||
(d/dissoc-in path)))
|
||||
set-groups ;; TODO update set-groups as needed
|
||||
themes))
|
||||
themes
|
||||
active-themes))
|
||||
this)))
|
||||
|
||||
(delete-set [_ set-name]
|
||||
(let [path (split-path set-name "/")]
|
||||
(TokensLib. (d/dissoc-in sets path)
|
||||
set-groups ;; TODO remove set-group if needed
|
||||
themes)))
|
||||
themes
|
||||
active-themes)))
|
||||
|
||||
(get-set-tree [_]
|
||||
sets)
|
||||
|
@ -397,6 +484,9 @@
|
|||
(->> (tree-seq d/ordered-map? vals sets)
|
||||
(filter (partial instance? TokenSet))))
|
||||
|
||||
(get-ordered-set-names [this]
|
||||
(map :name (get-sets this)))
|
||||
|
||||
(set-count [this]
|
||||
(count (get-sets this)))
|
||||
|
||||
|
@ -412,7 +502,8 @@
|
|||
(dm/assert! "expected valid token theme" (check-token-theme! token-theme))
|
||||
(TokensLib. sets
|
||||
set-groups
|
||||
(update themes (:group token-theme) d/oassoc (:name token-theme) token-theme)))
|
||||
(update themes (:group token-theme) d/oassoc (:name token-theme) token-theme)
|
||||
active-themes))
|
||||
|
||||
(update-theme [this group name f]
|
||||
(let [theme (dm/get-in themes [group name])]
|
||||
|
@ -420,21 +511,28 @@
|
|||
(let [theme' (-> (make-token-theme (f theme))
|
||||
(assoc :modified-at (dt/now)))
|
||||
group' (:group theme')
|
||||
name' (:name theme')]
|
||||
name' (:name theme')
|
||||
same-group? (= group group')
|
||||
same-name? (= name name')
|
||||
same-path? (and same-group? same-name?)]
|
||||
(check-token-theme! theme')
|
||||
(TokensLib. sets
|
||||
set-groups
|
||||
(if (and (= group group') (= name name'))
|
||||
(if same-path?
|
||||
(update themes group' assoc name' theme')
|
||||
(-> themes
|
||||
(d/oassoc-in-before [group name] [group' name'] theme')
|
||||
(d/dissoc-in [group name])))))
|
||||
(d/dissoc-in [group name])))
|
||||
(if same-path?
|
||||
active-themes
|
||||
(disj active-themes (token-theme-path group name)))))
|
||||
this)))
|
||||
|
||||
(delete-theme [_ group name]
|
||||
(TokensLib. sets
|
||||
set-groups
|
||||
(d/dissoc-in themes [group name])))
|
||||
(d/dissoc-in themes [group name])
|
||||
(disj active-themes (token-theme-path group name))))
|
||||
|
||||
(get-theme-tree [_]
|
||||
themes)
|
||||
|
@ -455,13 +553,58 @@
|
|||
(get-theme [_ group name]
|
||||
(dm/get-in themes [group name]))
|
||||
|
||||
(set-active-themes [_ active-themes]
|
||||
(TokensLib. sets
|
||||
set-groups
|
||||
themes
|
||||
active-themes))
|
||||
|
||||
(activate-theme [this group name]
|
||||
(if-let [theme (get-theme this group name)]
|
||||
(let [group-themes (->> (get themes group)
|
||||
(map (comp theme-path val))
|
||||
(into #{}))
|
||||
active-themes' (-> (set/difference active-themes group-themes)
|
||||
(conj (theme-path theme)))]
|
||||
(TokensLib. sets
|
||||
set-groups
|
||||
themes
|
||||
active-themes'))
|
||||
this))
|
||||
|
||||
(deactivate-theme [_ group name]
|
||||
(TokensLib. sets
|
||||
set-groups
|
||||
themes
|
||||
(disj active-themes (token-theme-path group name))))
|
||||
|
||||
(theme-active? [_ group name]
|
||||
(contains? active-themes (token-theme-path group name)))
|
||||
|
||||
(toggle-theme-active? [this group name]
|
||||
(if (theme-active? this group name)
|
||||
(deactivate-theme this group name)
|
||||
(activate-theme this group name)))
|
||||
|
||||
(get-active-theme-paths [_]
|
||||
active-themes)
|
||||
|
||||
(get-active-themes [this]
|
||||
(into
|
||||
(list)
|
||||
(comp
|
||||
(filter (partial instance? TokenTheme))
|
||||
(filter #(theme-active? this (:group %) (:name %))))
|
||||
(tree-seq d/ordered-map? vals themes)))
|
||||
|
||||
ITokensLib
|
||||
(add-token-in-set [this set-name token]
|
||||
(dm/assert! "expected valid token instance" (check-token! token))
|
||||
(if (contains? sets set-name)
|
||||
(TokensLib. (update sets set-name add-token token)
|
||||
set-groups
|
||||
themes)
|
||||
themes
|
||||
active-themes)
|
||||
this))
|
||||
|
||||
(update-token-in-set [this set-name token-name f]
|
||||
|
@ -469,7 +612,8 @@
|
|||
(TokensLib. (update sets set-name
|
||||
#(update-token % token-name f))
|
||||
set-groups
|
||||
themes)
|
||||
themes
|
||||
active-themes)
|
||||
this))
|
||||
|
||||
(delete-token-from-set [this set-name token-name]
|
||||
|
@ -477,7 +621,8 @@
|
|||
(TokensLib. (update sets set-name
|
||||
#(delete-token % token-name))
|
||||
set-groups
|
||||
themes)
|
||||
themes
|
||||
active-themes)
|
||||
this))
|
||||
|
||||
(toggle-set-in-theme [this theme-group theme-name set-name]
|
||||
|
@ -485,12 +630,46 @@
|
|||
(TokensLib. sets
|
||||
set-groups
|
||||
(d/oupdate-in themes [theme-group theme-name]
|
||||
#(toggle-set % set-name)))
|
||||
#(toggle-set % set-name))
|
||||
active-themes)
|
||||
this))
|
||||
|
||||
(get-active-themes-set-names [this]
|
||||
(into #{}
|
||||
(mapcat :sets)
|
||||
(get-active-themes this)))
|
||||
|
||||
(get-active-themes-set-tokens [this]
|
||||
(let [sets-order (get-ordered-set-names this)
|
||||
active-themes (get-active-themes this)
|
||||
order-theme-set (fn [theme]
|
||||
(filter #(contains? (set (:sets theme)) %) sets-order))]
|
||||
(reduce
|
||||
(fn [tokens theme]
|
||||
(reduce
|
||||
(fn [tokens' cur]
|
||||
(merge tokens' (:tokens (get-set this cur))))
|
||||
tokens (order-theme-set theme)))
|
||||
(d/ordered-map) active-themes)))
|
||||
|
||||
;; TODO Move to `update-set`
|
||||
(update-set-name [_ old-set-name new-set-name]
|
||||
(TokensLib. sets
|
||||
set-groups
|
||||
(walk/postwalk
|
||||
(fn [form]
|
||||
(if (instance? TokenTheme form)
|
||||
(-> form
|
||||
(update :sets disj old-set-name)
|
||||
(update :sets conj new-set-name))
|
||||
form))
|
||||
themes)
|
||||
active-themes))
|
||||
|
||||
(validate [_]
|
||||
(and (valid-token-sets? sets) ;; TODO: validate set-groups
|
||||
(valid-token-themes? themes))))
|
||||
(valid-token-themes? themes)
|
||||
(valid-active-token-themes? active-themes))))
|
||||
|
||||
(defn valid-tokens-lib?
|
||||
[o]
|
||||
|
@ -513,10 +692,11 @@
|
|||
;; with pages and pages-index.
|
||||
(make-tokens-lib :sets (d/ordered-map)
|
||||
:set-groups {}
|
||||
:themes (d/ordered-map)))
|
||||
:themes (d/ordered-map)
|
||||
:active-themes #{}))
|
||||
|
||||
([& {:keys [sets set-groups themes]}]
|
||||
(let [tokens-lib (TokensLib. sets set-groups themes)]
|
||||
([& {:keys [sets set-groups themes active-themes]}]
|
||||
(let [tokens-lib (TokensLib. sets set-groups themes (or active-themes #{}))]
|
||||
|
||||
(dm/assert!
|
||||
"expected valid tokens lib"
|
||||
|
@ -541,16 +721,16 @@
|
|||
:class TokensLib
|
||||
:wfn deref
|
||||
:rfn #(make-tokens-lib %)}
|
||||
|
||||
|
||||
{:id "penpot/token-set"
|
||||
:class TokenSet
|
||||
:wfn #(into {} %)
|
||||
:rfn #(make-token-set %)}
|
||||
|
||||
:rfn #(make-token-set %)}
|
||||
|
||||
{:id "penpot/token-theme"
|
||||
:class TokenTheme
|
||||
:wfn #(into {} %)
|
||||
:rfn #(make-token-theme %)}
|
||||
:rfn #(make-token-theme %)}
|
||||
|
||||
{:id "penpot/token"
|
||||
:class Token
|
||||
|
@ -592,9 +772,11 @@
|
|||
(fres/write-tag! w n 3)
|
||||
(fres/write-object! w (.-sets o))
|
||||
(fres/write-object! w (.-set-groups o))
|
||||
(fres/write-object! w (.-themes o)))
|
||||
(fres/write-object! w (.-themes o))
|
||||
(fres/write-object! w (.-active-themes o)))
|
||||
:rfn (fn [r]
|
||||
(let [sets (fres/read-object! r)
|
||||
set-groups (fres/read-object! r)
|
||||
themes (fres/read-object! r)]
|
||||
(->TokensLib sets set-groups themes)))}))
|
||||
(let [sets (fres/read-object! r)
|
||||
set-groups (fres/read-object! r)
|
||||
themes (fres/read-object! r)
|
||||
active-themes (fres/read-object! r)]
|
||||
(->TokensLib sets set-groups themes active-themes)))}))
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
(ns common-tests.types.tokens-lib-test
|
||||
(:require
|
||||
#?(:clj [app.common.fressian :as fres])
|
||||
[app.common.data :as d]
|
||||
[app.common.fressian :as fres]
|
||||
[app.common.time :as dt]
|
||||
[app.common.transit :as tr]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
|
@ -182,6 +182,19 @@
|
|||
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))))
|
||||
|
||||
(t/deftest delete-token-set
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "test-token-set")))
|
||||
|
||||
tokens-lib' (-> tokens-lib
|
||||
(ctob/delete-set "test-token-set")
|
||||
(ctob/delete-set "not-existing-set"))
|
||||
|
||||
token-set' (ctob/get-set tokens-lib' "updated-name")]
|
||||
|
||||
(t/is (= (ctob/set-count tokens-lib') 0))
|
||||
(t/is (nil? token-set'))))
|
||||
|
||||
(t/deftest active-themes-set-names
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "test-token-set")))
|
||||
|
||||
|
@ -307,7 +320,35 @@
|
|||
(t/is (= (ctob/set-count tokens-lib') 1))
|
||||
(t/is (= (count (:tokens token-set')) 0))
|
||||
(t/is (nil? token'))
|
||||
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set))))))
|
||||
(t/is (dt/is-after? (:modified-at token-set') (:modified-at token-set)))))
|
||||
|
||||
(t/deftest list-active-themes-tokens-in-order
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-theme (ctob/make-token-theme :name "out-of-order-theme"
|
||||
;; Out of order sets in theme
|
||||
:sets ["unknown-set" "set-b" "set-a"]))
|
||||
(ctob/set-active-themes #{"/out-of-order-theme"})
|
||||
|
||||
(ctob/add-set (ctob/make-token-set :name "set-a"))
|
||||
(ctob/add-token-in-set "set-a" (ctob/make-token :name "set-a-token"
|
||||
:type :boolean
|
||||
:value true))
|
||||
(ctob/add-set (ctob/make-token-set :name "set-b"))
|
||||
(ctob/add-token-in-set "set-b" (ctob/make-token :name "set-b-token"
|
||||
:type :boolean
|
||||
:value true))
|
||||
;; Ignore this set
|
||||
(ctob/add-set (ctob/make-token-set :name "inactive-set"))
|
||||
(ctob/add-token-in-set "inactive-set" (ctob/make-token :name "inactive-set-token"
|
||||
:type :boolean
|
||||
:value true)))
|
||||
|
||||
|
||||
expected-order (ctob/get-ordered-set-names tokens-lib)
|
||||
expected-tokens (ctob/get-active-themes-set-tokens tokens-lib)
|
||||
expected-token-names (mapv key expected-tokens)]
|
||||
(t/is (= '("set-a" "set-b" "inactive-set") expected-order))
|
||||
(t/is (= ["set-a-token" "set-b-token"] expected-token-names)))))
|
||||
|
||||
|
||||
(t/testing "token-theme in a lib"
|
||||
|
|
7
frontend/dev/preload.cljs
Normal file
7
frontend/dev/preload.cljs
Normal file
|
@ -0,0 +1,7 @@
|
|||
(ns preload
|
||||
(:require
|
||||
[devtools.core :as devtools]))
|
||||
|
||||
;; Silence shadow-cljs devtools (ns reloading)
|
||||
(devtools/set-pref! :dont-display-banner true)
|
||||
(devtools/set-pref! :min-expandable-sequable-count-for-well-known-types 0)
|
|
@ -8,7 +8,9 @@
|
|||
{:target :browser
|
||||
:output-dir "resources/public/js/"
|
||||
:asset-path "/js"
|
||||
:devtools {:browser-inject :main
|
||||
:devtools {:preloads [preload devtools.preload]
|
||||
:log false
|
||||
:browser-inject :main
|
||||
:watch-dir "resources/public"
|
||||
:reload-strategy :full}
|
||||
:build-options {:manifest-name "manifest.json"}
|
||||
|
@ -65,7 +67,8 @@
|
|||
:compiler-options
|
||||
{:output-feature-set :es2020
|
||||
:output-wrapper false
|
||||
:warnings {:fn-deprecated false}}
|
||||
:warnings {:fn-deprecated false}
|
||||
:closure-defines {shadow.debug.LogLevel :warning}}
|
||||
|
||||
:release
|
||||
{:closure-defines {goog.DEBUG false
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -40,6 +40,13 @@
|
|||
(watch [_ _ _]
|
||||
(rx/of (dwsh/update-shapes [id] #(merge % attrs))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TOKENS Getters
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn get-tokens-lib [state]
|
||||
(get-in state [:workspace-data :tokens-lib]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TOKENS Actions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -81,11 +88,6 @@
|
|||
(let [workspace-data (deref refs/workspace-data)]
|
||||
(get (:tokens workspace-data) id)))
|
||||
|
||||
(defn get-token-set-data-from-token-set-id
|
||||
[id]
|
||||
(let [workspace-data (deref refs/workspace-data)]
|
||||
(get (:token-sets-index workspace-data) id)))
|
||||
|
||||
(defn set-selected-token-set-id
|
||||
[id]
|
||||
(ptk/reify ::set-selected-token-set-id
|
||||
|
@ -93,16 +95,8 @@
|
|||
(update [_ state]
|
||||
(wtts/assoc-selected-token-set-id state id))))
|
||||
|
||||
(defn get-token-set-tokens
|
||||
[token-set file]
|
||||
(map #(get-in file [:tokens %]) (:tokens token-set)))
|
||||
|
||||
(defn create-token-theme [token-theme]
|
||||
(let [new-token-theme (merge
|
||||
{:id (uuid/next)
|
||||
:sets #{}
|
||||
:selected :enabled}
|
||||
token-theme)]
|
||||
(let [new-token-theme token-theme]
|
||||
(ptk/reify ::create-token-theme
|
||||
ptk/WatchEvent
|
||||
(watch [it _ _]
|
||||
|
@ -111,199 +105,162 @@
|
|||
(rx/of
|
||||
(dch/commit-changes changes)))))))
|
||||
|
||||
(defn update-token-theme [token-theme]
|
||||
(defn update-token-theme [[group name] token-theme]
|
||||
(ptk/reify ::update-token-theme
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [prev-token-theme (wtts/get-workspace-token-theme (:id token-theme) state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/update-token-theme token-theme prev-token-theme))]
|
||||
(let [tokens-lib (get-tokens-lib state)
|
||||
prev-token-theme (some-> tokens-lib (ctob/get-theme group name))
|
||||
changes (pcb/update-token-theme (pcb/empty-changes it) token-theme prev-token-theme)]
|
||||
(rx/of
|
||||
(dch/commit-changes changes))))))
|
||||
|
||||
(defn ensure-token-theme-changes [changes state {:keys [id new-set?]}]
|
||||
(let [theme-id (wtts/update-theme-id state)
|
||||
theme (some-> theme-id (wtts/get-workspace-token-theme state))]
|
||||
(cond
|
||||
(not theme-id) (-> changes
|
||||
(pcb/add-temporary-token-theme
|
||||
{:id (uuid/next)
|
||||
:name "Test theme"
|
||||
:sets #{id}}))
|
||||
new-set? (-> changes
|
||||
(pcb/update-token-theme
|
||||
(wtts/add-token-set-to-token-theme id theme)
|
||||
theme))
|
||||
:else changes)))
|
||||
|
||||
(defn toggle-token-theme [token-theme-id]
|
||||
(ptk/reify ::toggle-token-theme
|
||||
(defn toggle-token-theme-active? [group name]
|
||||
(ptk/reify ::toggle-token-theme-active?
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [themes (wtts/get-active-theme-ids state)
|
||||
new-themes (wtts/toggle-active-theme-id token-theme-id state)
|
||||
(let [tokens-lib (get-tokens-lib state)
|
||||
prev-active-token-themes (some-> tokens-lib
|
||||
(ctob/get-active-theme-paths))
|
||||
active-token-themes (some-> tokens-lib
|
||||
(ctob/toggle-theme-active? group name)
|
||||
(ctob/get-active-theme-paths))
|
||||
active-token-themes' (if (= active-token-themes #{ctob/hidden-token-theme-path})
|
||||
active-token-themes
|
||||
(disj active-token-themes ctob/hidden-token-theme-path))
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/update-active-token-themes new-themes themes))]
|
||||
(pcb/update-active-token-themes active-token-themes' prev-active-token-themes))]
|
||||
(rx/of
|
||||
(dch/commit-changes changes)
|
||||
(wtu/update-workspace-tokens))))))
|
||||
|
||||
(defn delete-token-theme [token-theme-id]
|
||||
(defn delete-token-theme [group name]
|
||||
(ptk/reify ::delete-token-theme
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-token-theme token-theme-id))]
|
||||
(pcb/delete-token-theme group name))]
|
||||
(rx/of
|
||||
(dch/commit-changes changes)
|
||||
(wtu/update-workspace-tokens))))))
|
||||
|
||||
(defn create-token-set [token-set]
|
||||
(let [new-token-set (merge
|
||||
{:id (uuid/next)
|
||||
:name "Token Set"
|
||||
{:name "Token Set"
|
||||
:tokens []}
|
||||
token-set)]
|
||||
(ptk/reify ::create-token-set
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [changes (-> (pcb/empty-changes it)
|
||||
(pcb/add-token-set new-token-set)
|
||||
(ensure-token-theme-changes state {:id (:id new-token-set)
|
||||
:new-set? true}))]
|
||||
(pcb/add-token-set new-token-set))]
|
||||
(rx/of
|
||||
(set-selected-token-set-id (:id new-token-set))
|
||||
(set-selected-token-set-id (:name new-token-set))
|
||||
(dch/commit-changes changes)))))))
|
||||
|
||||
(defn update-token-set [token-set]
|
||||
(defn update-token-set [set-name token-set]
|
||||
(ptk/reify ::update-token-set
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [prev-token-set (wtts/get-token-set (:id token-set) state)
|
||||
(let [prev-token-set (some-> (get-tokens-lib state)
|
||||
(ctob/get-set set-name))
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/update-token-set token-set prev-token-set))]
|
||||
(rx/of
|
||||
(dch/commit-changes changes))))))
|
||||
|
||||
(defn toggle-token-set [{:keys [token-set-id]}]
|
||||
(defn toggle-token-set [{:keys [token-set-name]}]
|
||||
(ptk/reify ::toggle-token-set
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [target-theme-id (wtts/get-temp-theme-id state)
|
||||
active-set-ids (wtts/get-active-set-ids state)
|
||||
theme (-> (wtts/get-workspace-token-theme target-theme-id state)
|
||||
(assoc :sets active-set-ids))
|
||||
(let [tokens-lib (get-tokens-lib state)
|
||||
prev-theme (ctob/get-theme tokens-lib ctob/hidden-token-theme-group ctob/hidden-token-theme-name)
|
||||
active-token-set-names (ctob/get-active-themes-set-names tokens-lib)
|
||||
theme (-> (or (some-> prev-theme
|
||||
(ctob/set-sets active-token-set-names))
|
||||
(ctob/make-hidden-token-theme :sets active-token-set-names))
|
||||
(ctob/toggle-set token-set-name))
|
||||
prev-active-token-themes (ctob/get-active-theme-paths tokens-lib)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/update-token-theme
|
||||
(wtts/toggle-token-set-to-token-theme token-set-id theme)
|
||||
theme)
|
||||
(pcb/update-active-token-themes #{target-theme-id} (wtts/get-active-theme-ids state)))]
|
||||
(pcb/update-active-token-themes #{(ctob/token-theme-path ctob/hidden-token-theme-group ctob/hidden-token-theme-name)} prev-active-token-themes))
|
||||
changes' (if prev-theme
|
||||
(pcb/update-token-theme changes theme prev-theme)
|
||||
(pcb/add-token-theme changes theme))]
|
||||
(rx/of
|
||||
(dch/commit-changes changes)
|
||||
(dch/commit-changes changes')
|
||||
(wtu/update-workspace-tokens))))))
|
||||
|
||||
(defn delete-token-set [token-set-id token-set-name]
|
||||
(defn delete-token-set [token-set-name]
|
||||
(ptk/reify ::delete-token-set
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-token-set token-set-id token-set-name))]
|
||||
(pcb/delete-token-set token-set-name))]
|
||||
(rx/of
|
||||
(dch/commit-changes changes)
|
||||
(wtu/update-workspace-tokens))))))
|
||||
|
||||
(defn update-create-token
|
||||
[token]
|
||||
(let [token (update token :id #(or % (uuid/next)))]
|
||||
(ptk/reify ::update-create-token
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [token-set (wtts/get-selected-token-set state)
|
||||
create-set? (not token-set)
|
||||
token-set (or token-set
|
||||
{:id (uuid/next)
|
||||
:name "Global"
|
||||
:tokens []})
|
||||
[{:keys [token prev-token-name]}]
|
||||
(ptk/reify ::update-create-token
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [token-set (wtts/get-selected-token-set state)
|
||||
token-set-name (or (:name token-set) "Global")
|
||||
changes (if (not token-set)
|
||||
;; No set created add a global set
|
||||
(let [tokens-lib (get-tokens-lib state)
|
||||
token-set (ctob/make-token-set :name token-set-name :tokens {(:name token) token})
|
||||
hidden-theme (ctob/make-hidden-token-theme :sets [token-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} #{}))
|
||||
|
||||
changes (cond-> (pcb/empty-changes it)
|
||||
create-set?
|
||||
(pcb/add-token-set token-set))
|
||||
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)))
|
||||
|
||||
prev-token-id (d/seek #(= % (:id token)) (:tokens token-set))
|
||||
prev-token (get-token-data-from-token-id prev-token-id)
|
||||
create-token? (not prev-token)
|
||||
|
||||
changes (if create-token?
|
||||
(pcb/add-token changes (:id token-set) (:name token-set) token)
|
||||
(pcb/update-token changes (:id token-set) (:name token-set) token prev-token))
|
||||
|
||||
changes (-> changes
|
||||
(ensure-token-theme-changes state {:new-set? create-set?
|
||||
:id (:id token-set)}))]
|
||||
(rx/of
|
||||
(set-selected-token-set-id (:id token-set))
|
||||
(dch/commit-changes changes)))))))
|
||||
:else base-changes))
|
||||
;; Either update or add token to existing set
|
||||
(if-let [prev-token (ctob/get-token token-set (or prev-token-name (:name token)))]
|
||||
(pcb/update-token (pcb/empty-changes) (:name token-set) token prev-token)
|
||||
(pcb/add-token (pcb/empty-changes) (:name token-set) token)))]
|
||||
(rx/of
|
||||
(set-selected-token-set-id token-set-name)
|
||||
(dch/commit-changes changes))))))
|
||||
|
||||
(defn delete-token
|
||||
[set-name id name]
|
||||
[set-name token-name]
|
||||
(dm/assert! (string? set-name))
|
||||
(dm/assert! (uuid? id))
|
||||
(dm/assert! (string? name))
|
||||
(dm/assert! (string? token-name))
|
||||
(ptk/reify ::delete-token
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-token set-name id name))]
|
||||
(pcb/delete-token set-name token-name))]
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn duplicate-token
|
||||
[id]
|
||||
(let [new-token (-> (get-token-data-from-token-id id)
|
||||
(dissoc :id)
|
||||
(update :name #(str/concat % "-copy")))]
|
||||
(update-create-token new-token)))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TEMP (Move to test)
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(comment
|
||||
(def shape-1 {:r3 3})
|
||||
|
||||
(def token-1 {:rx 1
|
||||
:ry 1})
|
||||
|
||||
|
||||
(def shape-after-token-1-is-applied {:rx 1
|
||||
:ry 1
|
||||
:r3 3})
|
||||
|
||||
(def token-2 {:r3 1})
|
||||
|
||||
|
||||
(def shape-after-token-2-is-applied {:rx 1
|
||||
:ry 1
|
||||
:r3 1})
|
||||
|
||||
(def token-3 {:r3 1})
|
||||
|
||||
(def shape-after-token-3-is-applied {:rx 1
|
||||
:ry 1})
|
||||
|
||||
(= (toggle-or-apply-token shape-1 token-1)
|
||||
shape-after-token-1-is-applied)
|
||||
(= (toggle-or-apply-token shape-after-token-1-is-applied token-2)
|
||||
shape-after-token-2-is-applied)
|
||||
(= (toggle-or-apply-token shape-after-token-2-is-applied token-3)
|
||||
shape-after-token-3-is-applied)
|
||||
nil)
|
||||
[token-name]
|
||||
(dm/assert! (string? token-name))
|
||||
(ptk/reify ::duplicate-token
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when-let [token (some-> (wtts/get-selected-token-set state)
|
||||
(ctob/get-token token-name)
|
||||
(update :name #(str/concat % "-copy")))]
|
||||
(rx/of
|
||||
(update-create-token {:token token}))))))
|
||||
|
||||
(defn set-token-type-section-open
|
||||
[token-type open?]
|
||||
|
@ -315,7 +272,7 @@
|
|||
;; Token Context Menu Functions -------------------------------------------------
|
||||
|
||||
(defn show-token-context-menu
|
||||
[{:keys [position _token-id] :as params}]
|
||||
[{:keys [position _token-name] :as params}]
|
||||
(dm/assert! (gpt/point? position))
|
||||
(ptk/reify ::show-token-context-menu
|
||||
ptk/UpdateEvent
|
||||
|
@ -329,7 +286,7 @@
|
|||
(assoc-in state [:workspace-local :token-context-menu] nil))))
|
||||
|
||||
(defn show-token-set-context-menu
|
||||
[{:keys [position _token-set-id] :as params}]
|
||||
[{:keys [position _token-set-name] :as params}]
|
||||
(dm/assert! (gpt/point? position))
|
||||
(ptk/reify ::show-token-set-context-menu
|
||||
ptk/UpdateEvent
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
[app.common.files.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.workspace.tokens.token-set :as wtts]
|
||||
[okulary.core :as l]
|
||||
[app.common.types.tokens-lib :as ctob]))
|
||||
[okulary.core :as l]))
|
||||
|
||||
;; ---- Global refs
|
||||
|
||||
|
@ -235,59 +235,6 @@
|
|||
(def workspace-data
|
||||
(l/derived :workspace-data st/state))
|
||||
|
||||
(def workspace-selected-token-set-id
|
||||
(l/derived
|
||||
wtts/get-selected-token-set-id
|
||||
st/state
|
||||
=))
|
||||
|
||||
;; ---- Tokens
|
||||
|
||||
(def tokens-lib
|
||||
(l/derived :tokens-lib workspace-data))
|
||||
|
||||
(def workspace-token-theme-groups
|
||||
(l/derived #(some-> % ctob/get-theme-groups) tokens-lib))
|
||||
|
||||
(defn workspace-token-theme
|
||||
[id]
|
||||
(l/derived #(wtts/get-workspace-theme id %) st/state))
|
||||
|
||||
(def workspace-active-theme-ids
|
||||
(l/derived wtts/get-active-theme-ids st/state))
|
||||
|
||||
(def workspace-temp-theme-id
|
||||
(l/derived wtts/get-temp-theme-id st/state))
|
||||
|
||||
(def workspace-active-set-ids
|
||||
(l/derived wtts/get-active-set-ids st/state))
|
||||
|
||||
(def workspace-token-themes
|
||||
(l/derived wtts/get-workspace-themes-index st/state))
|
||||
|
||||
(def workspace-ordered-token-themes
|
||||
(l/derived wtts/get-workspace-ordered-themes st/state))
|
||||
|
||||
(def workspace-ordered-token-sets
|
||||
(l/derived
|
||||
(fn [data]
|
||||
(or (wtts/get-workspace-ordered-sets data) {}))
|
||||
st/state
|
||||
=))
|
||||
|
||||
(def workspace-active-theme-sets-tokens
|
||||
(l/derived wtts/get-active-theme-sets-tokens-names-map st/state =))
|
||||
|
||||
(def workspace-ordered-token-sets-tokens
|
||||
(l/derived wtts/get-workspace-ordered-sets-tokens st/state =))
|
||||
|
||||
(def workspace-selected-token-set-tokens
|
||||
(l/derived
|
||||
(fn [data]
|
||||
(or (wtts/get-selected-token-set-tokens data) {}))
|
||||
st/state
|
||||
=))
|
||||
|
||||
(def workspace-file-colors
|
||||
(l/derived (fn [data]
|
||||
(when data
|
||||
|
@ -496,6 +443,65 @@
|
|||
ids)))
|
||||
st/state =))
|
||||
|
||||
;; ---- Token refs
|
||||
|
||||
(def tokens-lib
|
||||
(l/derived :tokens-lib workspace-data))
|
||||
|
||||
(def workspace-token-theme-groups
|
||||
(l/derived (d/nilf ctob/get-theme-groups) tokens-lib))
|
||||
|
||||
(defn workspace-token-theme
|
||||
[group name]
|
||||
(l/derived
|
||||
(fn [lib]
|
||||
(when lib
|
||||
(ctob/get-theme lib group name)))
|
||||
tokens-lib))
|
||||
|
||||
(def workspace-token-theme-tree-no-hidden
|
||||
(l/derived (fn [lib]
|
||||
(or
|
||||
(some-> lib
|
||||
(ctob/delete-theme ctob/hidden-token-theme-group ctob/hidden-token-theme-name)
|
||||
(ctob/get-theme-tree))
|
||||
[]))
|
||||
tokens-lib))
|
||||
|
||||
(def workspace-token-themes
|
||||
(l/derived #(or (some-> % ctob/get-themes) []) tokens-lib))
|
||||
|
||||
(def workspace-token-themes-no-hidden
|
||||
(l/derived #(remove ctob/hidden-temporary-theme? %) workspace-token-themes))
|
||||
|
||||
(def workspace-selected-token-set-id
|
||||
(l/derived wtts/get-selected-token-set-id st/state))
|
||||
|
||||
(def workspace-ordered-token-sets
|
||||
(l/derived #(or (some-> % ctob/get-sets) []) tokens-lib))
|
||||
|
||||
(def workspace-active-theme-paths
|
||||
(l/derived (d/nilf ctob/get-active-theme-paths) tokens-lib))
|
||||
|
||||
(def workspace-active-theme-paths-no-hidden
|
||||
(l/derived #(disj % ctob/hidden-token-theme-path) workspace-active-theme-paths))
|
||||
|
||||
(def workspace-active-set-names
|
||||
(l/derived (d/nilf ctob/get-active-themes-set-names) tokens-lib))
|
||||
|
||||
(def workspace-active-theme-sets-tokens
|
||||
(l/derived #(or (some-> % ctob/get-active-themes-set-tokens) {}) tokens-lib))
|
||||
|
||||
(def workspace-selected-token-set-token
|
||||
(fn [token-name]
|
||||
(l/derived
|
||||
#(some-> (wtts/get-selected-token-set %)
|
||||
(ctob/get-token token-name))
|
||||
st/state)))
|
||||
|
||||
(def workspace-selected-token-set-tokens
|
||||
(l/derived #(or (wtts/get-selected-token-set-tokens %) {}) st/state))
|
||||
|
||||
;; ---- Viewer refs
|
||||
|
||||
(defn lookup-viewer-objects-by-id
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(set! *warn-on-infer* false)
|
||||
|
||||
(mf/defc tab-element
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [children]}]
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.config :as cf]
|
||||
[app.main.data.events :as-alias ev]
|
||||
[app.main.data.workspace :as udw]
|
||||
|
@ -27,10 +28,11 @@
|
|||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.hooks :as h]
|
||||
[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.editable-select :refer [editable-select]]
|
||||
[app.main.ui.workspace.tokens.style-dictionary :as sd]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[app.main.ui.workspace.tokens.changes :as wtch]
|
||||
[app.main.ui.workspace.tokens.token-types :as wtty]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
@ -856,8 +858,10 @@
|
|||
|
||||
shape (when-not multiple
|
||||
(first (deref (refs/objects-by-id ids))))
|
||||
tokens (mf/deref refs/workspace-selected-token-set-tokens)
|
||||
spacing-tokens (mf/use-memo (mf/deps tokens) #(:spacing (wtc/group-tokens-by-type tokens)))
|
||||
tokens (sd/use-active-theme-sets-tokens)
|
||||
spacing-tokens (mf/use-memo
|
||||
(mf/deps tokens)
|
||||
#(ctob/filter-by-type :spacing tokens))
|
||||
|
||||
spacing-column-options (mf/use-memo
|
||||
(mf/deps shape spacing-tokens)
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[clojure.set :refer [rename-keys union]]
|
||||
[rumext.v2 :as mf]))
|
||||
[rumext.v2 :as mf]
|
||||
[app.common.types.tokens-lib :as ctob]))
|
||||
|
||||
(def measure-attrs
|
||||
[:proportion-lock
|
||||
|
@ -101,28 +102,29 @@
|
|||
selection-parents-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
|
||||
selection-parents (mf/deref selection-parents-ref)
|
||||
|
||||
tokens (-> (mf/deref refs/workspace-active-theme-sets-tokens)
|
||||
(sd/use-resolved-tokens))
|
||||
tokens-by-type (mf/use-memo (mf/deps tokens) #(wtc/group-tokens-by-type tokens))
|
||||
tokens (sd/use-active-theme-sets-tokens)
|
||||
tokens-by-type (mf/use-memo
|
||||
(mf/deps tokens)
|
||||
#(ctob/group-by-type tokens))
|
||||
|
||||
border-radius-tokens (:border-radius tokens-by-type)
|
||||
border-radius-options (mf/use-memo
|
||||
(mf/deps shape border-radius-tokens)
|
||||
#(wtc/tokens-name-map->select-options
|
||||
#(wtc/tokens->select-options
|
||||
{:shape shape
|
||||
:tokens border-radius-tokens
|
||||
:attributes (wtty/token-attributes :border-radius)}))
|
||||
sizing-tokens (:sizing tokens-by-type)
|
||||
width-options (mf/use-memo
|
||||
(mf/deps shape sizing-tokens)
|
||||
#(wtc/tokens-name-map->select-options
|
||||
#(wtc/tokens->select-options
|
||||
{:shape shape
|
||||
:tokens sizing-tokens
|
||||
:attributes (wtty/token-attributes :sizing)
|
||||
:selected-attributes #{:width}}))
|
||||
height-options (mf/use-memo
|
||||
(mf/deps shape sizing-tokens)
|
||||
#(wtc/tokens-name-map->select-options
|
||||
#(wtc/tokens->select-options
|
||||
{:shape shape
|
||||
:tokens sizing-tokens
|
||||
:attributes (wtty/token-attributes :sizing)
|
||||
|
|
|
@ -8,19 +8,20 @@
|
|||
(:require
|
||||
[app.common.types.shape.radius :as ctsr]
|
||||
[app.common.types.token :as ctt]
|
||||
[app.main.data.workspace.colors :as wdc]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.workspace :as udw]
|
||||
[app.main.data.workspace.colors :as wdc]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.ui.workspace.tokens.style-dictionary :as sd]
|
||||
[app.main.ui.workspace.tokens.tinycolor :as tinycolor]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[beicon.v2.core :as rx]
|
||||
[clojure.set :as set]
|
||||
[potok.v2.core :as ptk]
|
||||
[app.main.ui.workspace.tokens.tinycolor :as tinycolor]))
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
;; Token Updates ---------------------------------------------------------------
|
||||
|
||||
|
@ -34,21 +35,23 @@
|
|||
(ptk/reify ::apply-token
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(->> (rx/from (sd/resolve-tokens+ (get-in state [:workspace-data :tokens])))
|
||||
(rx/mapcat
|
||||
(fn [resolved-tokens]
|
||||
(let [undo-id (js/Symbol)
|
||||
resolved-value (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])
|
||||
tokenized-attributes (wtt/attributes-map attributes token)]
|
||||
(rx/of
|
||||
(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
|
||||
(on-update-shape resolved-value shape-ids attributes))
|
||||
(dwu/commit-undo-transaction undo-id)))))))))
|
||||
(when-let [tokens (some-> (get-in state [:workspace-data :tokens-lib])
|
||||
(ctob/get-active-themes-set-tokens))]
|
||||
(->> (rx/from (sd/resolve-tokens+ tokens))
|
||||
(rx/mapcat
|
||||
(fn [resolved-tokens]
|
||||
(let [undo-id (js/Symbol)
|
||||
resolved-value (get-in resolved-tokens [(wtt/token-identifier token) :resolved-value])
|
||||
tokenized-attributes (wtt/attributes-map attributes token)]
|
||||
(rx/of
|
||||
(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
|
||||
(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`.
|
||||
|
|
|
@ -19,20 +19,10 @@
|
|||
[cuerdas.core :as str]
|
||||
[goog.events :as events]
|
||||
[rumext.v2 :as mf])
|
||||
(:import
|
||||
goog.events.EventType))
|
||||
(:import goog.events.EventType))
|
||||
|
||||
;; Helpers ---------------------------------------------------------------------
|
||||
|
||||
(defn workspace-shapes [workspace page-id shape-ids]
|
||||
(-> (get-in workspace [:pages-index page-id :objects])
|
||||
(keep shape-ids)))
|
||||
|
||||
(defn vec-remove
|
||||
"remove elem in coll"
|
||||
[pos coll]
|
||||
(into (subvec coll 0 pos) (subvec coll (inc pos))))
|
||||
|
||||
(defn camel-keys [m]
|
||||
(->> m
|
||||
(d/deep-mapm
|
||||
|
|
|
@ -202,16 +202,14 @@
|
|||
(generic-attribute-actions #{:y} "Y" (assoc context-data :on-update-shape wtch/update-shape-position))))}))
|
||||
|
||||
(defn default-actions [{:keys [token selected-token-set-id]}]
|
||||
(let [{:keys [modal]} (wtty/get-token-properties token)
|
||||
selected-token-set (dt/get-token-set-data-from-token-set-id selected-token-set-id)]
|
||||
(let [{:keys [modal]} (wtty/get-token-properties token)]
|
||||
[{:title "Delete Token"
|
||||
:action #(st/emit! (dt/delete-token (:name selected-token-set) (:id token) (:name token)))}
|
||||
:action #(st/emit! (dt/delete-token selected-token-set-id (:name token)))}
|
||||
{:title "Duplicate Token"
|
||||
:action #(st/emit! (dt/duplicate-token (:id token)))}
|
||||
:action #(st/emit! (dt/duplicate-token (:name token)))}
|
||||
{:title "Edit Token"
|
||||
:action (fn [event]
|
||||
(let [{:keys [key fields]} modal
|
||||
token (dt/get-token-data-from-token-id (:id token))]
|
||||
(let [{:keys [key fields]} modal]
|
||||
(st/emit! dt/hide-token-context-menu)
|
||||
(dom/stop-propagation event)
|
||||
(modal/show! key {:x (.-clientX ^js event)
|
||||
|
@ -301,19 +299,27 @@
|
|||
:on-click action
|
||||
:selected? selected?}])])))
|
||||
|
||||
(mf/defc token-context-menu-tree
|
||||
[{:keys [width] :as mdata}]
|
||||
(let [objects (mf/deref refs/workspace-page-objects)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected-shapes (into [] (keep (d/getf objects)) selected)
|
||||
token-name (:token-name mdata)
|
||||
token (mf/deref (refs/workspace-selected-token-set-token token-name))
|
||||
selected-token-set-id (mf/deref refs/workspace-selected-token-set-id)]
|
||||
[:ul {:class (stl/css :context-list)}
|
||||
[:& menu-tree {:submenu-offset width
|
||||
:token token
|
||||
:selected-token-set-id selected-token-set-id
|
||||
:selected-shapes selected-shapes}]]))
|
||||
|
||||
(mf/defc token-context-menu
|
||||
[]
|
||||
(let [mdata (mf/deref tokens-menu-ref)
|
||||
top (+ (get-in mdata [:position :y]) 5)
|
||||
left (+ (get-in mdata [:position :x]) 5)
|
||||
width (mf/use-state 0)
|
||||
dropdown-ref (mf/use-ref)
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
selected-shapes (into [] (keep (d/getf objects)) selected)
|
||||
token-id (:token-id mdata)
|
||||
token (get (mf/deref refs/workspace-selected-token-set-tokens) token-id)
|
||||
selected-token-set-id (mf/deref refs/workspace-selected-token-set-id)]
|
||||
dropdown-ref (mf/use-ref)]
|
||||
(mf/use-effect
|
||||
(mf/deps mdata)
|
||||
(fn []
|
||||
|
@ -325,9 +331,5 @@
|
|||
:ref dropdown-ref
|
||||
:style {:top top :left left}
|
||||
:on-context-menu prevent-default}
|
||||
(when token
|
||||
[:ul {:class (stl/css :context-list)}
|
||||
[:& menu-tree {:submenu-offset @width
|
||||
:token token
|
||||
:selected-token-set-id selected-token-set-id
|
||||
:selected-shapes selected-shapes}]])]]))
|
||||
(when mdata
|
||||
[:& token-context-menu-tree (assoc mdata :offset @width)])]]))
|
||||
|
|
|
@ -23,17 +23,19 @@
|
|||
(defn maybe-resolve-token-value [{:keys [value] :as token}]
|
||||
(when value (resolve-token-value token)))
|
||||
|
||||
(defn group-tokens-by-type
|
||||
"Groups tokens by their `:type` property."
|
||||
[tokens]
|
||||
(->> (vals tokens)
|
||||
(group-by :type)))
|
||||
(defn tokens->select-options [{:keys [shape tokens attributes selected-attributes]}]
|
||||
(map
|
||||
(fn [{:keys [name] :as token}]
|
||||
(cond-> (assoc token :label name)
|
||||
(wtt/token-applied? token shape (or selected-attributes attributes)) (assoc :selected? true)))
|
||||
tokens))
|
||||
|
||||
(defn tokens-name-map->select-options [{:keys [shape tokens attributes selected-attributes]}]
|
||||
(->> (wtt/token-names-map tokens)
|
||||
(map (fn [[_k {:keys [name] :as item}]]
|
||||
(cond-> (assoc item :label name)
|
||||
(wtt/token-applied? item shape (or selected-attributes attributes)) (assoc :selected? true))))))
|
||||
(map
|
||||
(fn [[_k {:keys [name] :as token}]]
|
||||
(cond-> (assoc token :label name)
|
||||
(wtt/token-applied? token shape (or selected-attributes attributes)) (assoc :selected? true)))
|
||||
tokens))
|
||||
|
||||
;; JSON export functions -------------------------------------------------------
|
||||
|
||||
|
@ -46,18 +48,18 @@
|
|||
(defn export-tokens-file [tokens-json]
|
||||
(let [file-name "tokens.json"
|
||||
file-content (encode-tokens tokens-json)
|
||||
blob (wapi/create-blob (clj->js file-content) "application/json")]
|
||||
blob (wapi/create-blob file-content "application/json")]
|
||||
(dom/trigger-download file-name blob)))
|
||||
|
||||
(defn transform-tokens-into-json-format [tokens]
|
||||
(defn tokens->dtcg-map [tokens]
|
||||
(let [global (reduce
|
||||
(fn [acc [_ {:keys [name value type]}]]
|
||||
(assoc acc name {:$value value
|
||||
:$type (str/camel type)}))
|
||||
(sorted-map) tokens)]
|
||||
(assoc acc name {"$value" value
|
||||
"$type" (str/camel type)}))
|
||||
(d/ordered-map) tokens)]
|
||||
{:global global}))
|
||||
|
||||
(defn download-tokens-as-json []
|
||||
(let [all-tokens (deref refs/workspace-selected-token-set-tokens)
|
||||
transformed-tokens-json (transform-tokens-into-json-format all-tokens)]
|
||||
(export-tokens-file transformed-tokens-json)))
|
||||
(let [tokens (deref refs/workspace-active-theme-sets-tokens)
|
||||
dtcg-format-tokens-map (tokens->dtcg-map tokens)]
|
||||
(export-tokens-file dtcg-format-tokens-map)))
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
["lodash.debounce" :as debounce]
|
||||
[app.common.colors :as c]
|
||||
[app.common.data :as d]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.tokens :as dt]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -99,30 +100,28 @@ Token names should only contain letters and digits separated by . characters.")}
|
|||
(defn validate-token-value+
|
||||
"Validates token value by resolving the value `input` using `StyleDictionary`.
|
||||
Returns a promise of either resolved tokens or rejects with an error state."
|
||||
[{:keys [input name-value token tokens]}]
|
||||
(let [ ;; When creating a new token we dont have a token name yet,
|
||||
[{:keys [value name-value token tokens]}]
|
||||
(let [;; When creating a new token we dont have a token name yet,
|
||||
;; so we use a temporary token name that hopefully doesn't clash with any of the users token names
|
||||
token-name (if (str/empty? name-value) "__TOKEN_STUDIO_SYSTEM.TEMP" name-value)]
|
||||
(cond
|
||||
(empty? (str/trim input))
|
||||
(empty? (str/trim value))
|
||||
(p/rejected {:errors [{:error/code :error/empty-input}]})
|
||||
|
||||
(token-self-reference? token-name input)
|
||||
(token-self-reference? token-name value)
|
||||
(p/rejected {:errors [(wte/get-error-code :error.token/direct-self-reference)]})
|
||||
|
||||
:else
|
||||
(let [token-id (or (:id token) (random-uuid))
|
||||
new-tokens (update tokens token-name merge {:id token-id
|
||||
:value input
|
||||
:name token-name
|
||||
:type (:type token)})]
|
||||
(-> (sd/resolve-tokens+ new-tokens {:names-map? true})
|
||||
(p/then
|
||||
(fn [resolved-tokens]
|
||||
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-name)]
|
||||
(cond
|
||||
resolved-value (p/resolved resolved-token)
|
||||
:else (p/rejected {:errors (or errors (wte/get-error-code :error/unknown-error))}))))))))))
|
||||
(-> (update tokens token-name merge {:value value
|
||||
:name token-name
|
||||
:type (:type token)})
|
||||
(sd/resolve-tokens+ {:names-map? true})
|
||||
(p/then
|
||||
(fn [resolved-tokens]
|
||||
(let [{:keys [errors resolved-value] :as resolved-token} (get resolved-tokens token-name)]
|
||||
(cond
|
||||
resolved-value (p/resolved resolved-token)
|
||||
:else (p/rejected {:errors (or errors (wte/get-error-code :error/unknown-error))})))))))))
|
||||
|
||||
(defn use-debonced-resolve-callback
|
||||
"Resolves a token values using `StyleDictionary`.
|
||||
|
@ -141,7 +140,7 @@ Token names should only contain letters and digits separated by . characters.")}
|
|||
(js/setTimeout
|
||||
(fn []
|
||||
(when (not (timeout-outdated-cb?))
|
||||
(-> (validate-token-value+ {:input value
|
||||
(-> (validate-token-value+ {:value value
|
||||
:name-value @name-ref
|
||||
:token token
|
||||
:tokens tokens})
|
||||
|
@ -203,8 +202,9 @@ Token names should only contain letters and digits separated by . characters.")}
|
|||
color? (wtt/color-token? token)
|
||||
selected-set-tokens (mf/deref refs/workspace-selected-token-set-tokens)
|
||||
active-theme-tokens (mf/deref refs/workspace-active-theme-sets-tokens)
|
||||
resolved-tokens (sd/use-resolved-tokens active-theme-tokens {:names-map? true
|
||||
:cache-atom form-token-cache-atom})
|
||||
resolved-tokens (sd/use-resolved-tokens active-theme-tokens
|
||||
{:names-map? true
|
||||
:cache-atom form-token-cache-atom})
|
||||
token-path (mf/use-memo
|
||||
(mf/deps (:name token))
|
||||
#(wtt/token-name->path (:name token)))
|
||||
|
@ -309,7 +309,7 @@ Token names should only contain letters and digits separated by . characters.")}
|
|||
valid-description?+ (some-> final-description validate-descripion schema-validation->promise)]
|
||||
(-> (p/all [valid-name?+
|
||||
valid-description?+
|
||||
(validate-token-value+ {:input final-value
|
||||
(validate-token-value+ {:value final-value
|
||||
:name-value final-name
|
||||
:token token
|
||||
:tokens resolved-tokens})])
|
||||
|
@ -317,14 +317,13 @@ Token names should only contain letters and digits separated by . characters.")}
|
|||
;; 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))
|
||||
(let [new-token (cond-> {:name final-name
|
||||
:type (or (:type token) token-type)
|
||||
:value final-value}
|
||||
final-description (assoc :description final-description)
|
||||
(:id token) (assoc :id (:id token)))]
|
||||
(st/emit! (dt/update-create-token new-token))
|
||||
(st/emit! (wtu/update-workspace-tokens))
|
||||
(modal/hide!)))))))))]
|
||||
(st/emit! (dt/update-create-token {:token (ctob/make-token :name final-name
|
||||
:type (or (:type token) token-type)
|
||||
:value final-value
|
||||
:description final-description)
|
||||
:prev-token-name (:name token)}))
|
||||
(st/emit! (wtu/update-workspace-tokens))
|
||||
(modal/hide!))))))))]
|
||||
[:form
|
||||
{:class (stl/css :form-wrapper)
|
||||
:on-submit on-submit}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.workspace.tokens.modals.themes
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.tokens :as wdt]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -15,12 +16,10 @@
|
|||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.tokens.common :refer [labeled-input] :as wtco]
|
||||
[app.main.ui.workspace.tokens.sets :as wts]
|
||||
[app.main.ui.workspace.tokens.token-set :as wtts]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]
|
||||
[cuerdas.core :as str]
|
||||
[app.main.ui.workspace.tokens.sets-context :as sets-context]
|
||||
[app.main.ui.shapes.group :as group]))
|
||||
[app.util.dom :as dom]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def ^:private chevron-icon
|
||||
(i/icon-xref :arrow (stl/css :chevron-icon)))
|
||||
|
@ -56,29 +55,30 @@
|
|||
|
||||
(mf/defc themes-overview
|
||||
[{:keys [set-state]}]
|
||||
(let [active-theme-ids (mf/deref refs/workspace-active-theme-ids)
|
||||
themes (mf/deref refs/workspace-ordered-token-themes)
|
||||
(let [active-theme-ids (mf/deref refs/workspace-active-theme-paths)
|
||||
themes-groups (mf/deref refs/workspace-token-theme-tree-no-hidden)
|
||||
on-edit-theme (fn [theme e]
|
||||
(dom/prevent-default e)
|
||||
(dom/stop-propagation e)
|
||||
(set-state (fn [_] {:type :edit-theme
|
||||
:theme-id (:id theme)})))]
|
||||
:theme-path [(:id theme) (:group theme) (:name theme)]})))]
|
||||
[:div
|
||||
[:ul {:class (stl/css :theme-group-wrapper)}
|
||||
(for [[group themes] themes]
|
||||
(for [[group themes] themes-groups]
|
||||
[:li {:key (str "token-theme-group" group)}
|
||||
(when (seq group)
|
||||
[:span {:class (stl/css :theme-group-label)} group])
|
||||
[:ul {:class (stl/css :theme-group-rows-wrapper)}
|
||||
(for [{:keys [id name] :as theme} themes
|
||||
:let [selected? (some? (get active-theme-ids id))]]
|
||||
[:li {:key (str "token-theme-" id)
|
||||
(for [[_ {:keys [group name] :as theme}] themes
|
||||
:let [theme-id (ctob/theme-path theme)
|
||||
selected? (some? (get active-theme-ids theme-id))]]
|
||||
[:li {:key theme-id
|
||||
:class (stl/css :theme-row)}
|
||||
[:div {:class (stl/css :theme-row-left)}
|
||||
[:div {:on-click (fn [e]
|
||||
(dom/prevent-default e)
|
||||
(dom/stop-propagation e)
|
||||
(st/emit! (wdt/toggle-token-theme id)))}
|
||||
(st/emit! (wdt/toggle-token-theme-active? group name)))}
|
||||
[:& switch {:name (str "Theme" name)
|
||||
:on-change (constantly nil)
|
||||
:selected? selected?}]]
|
||||
|
@ -97,7 +97,7 @@
|
|||
[:button {:on-click (fn [e]
|
||||
(dom/prevent-default e)
|
||||
(dom/stop-propagation e)
|
||||
(st/emit! (wdt/delete-token-theme id)))}
|
||||
(st/emit! (wdt/delete-token-theme group name)))}
|
||||
i/delete]]]])]])]
|
||||
[:div {:class (stl/css :button-footer)}
|
||||
[:button {:class (stl/css :create-theme-button)
|
||||
|
@ -109,43 +109,35 @@
|
|||
"Create theme"]]]))
|
||||
|
||||
(mf/defc edit-theme
|
||||
[{:keys [token-sets theme theme-groups on-back on-submit]}]
|
||||
[{:keys [edit? token-sets theme theme-groups on-back on-submit]}]
|
||||
(let [{:keys [dropdown-open? on-open-dropdown on-close-dropdown on-toggle-dropdown]} (wtco/use-dropdown-open-state)
|
||||
|
||||
edit? (some? (:id theme))
|
||||
theme-state (mf/use-state {:token-sets token-sets
|
||||
:theme theme})
|
||||
disabled? (-> (get-in @theme-state [:theme :name])
|
||||
theme-state (mf/use-state theme)
|
||||
disabled? (-> (:name @theme-state)
|
||||
(str/trim)
|
||||
(str/empty?))
|
||||
token-set-active? (mf/use-callback
|
||||
(mf/deps theme-state)
|
||||
(fn [id]
|
||||
(get-in @theme-state [:theme :sets id])))
|
||||
(fn [set-name]
|
||||
(get-in @theme-state [:sets set-name])))
|
||||
on-toggle-token-set (mf/use-callback
|
||||
(mf/deps theme-state)
|
||||
(fn [token-set-id]
|
||||
(swap! theme-state (fn [st]
|
||||
(update st :theme #(wtts/toggle-token-set-to-token-theme token-set-id %))))))
|
||||
on-change-field (fn [field]
|
||||
(fn [e]
|
||||
(swap! theme-state (fn [st] (assoc-in st field (dom/get-target-val e))))))
|
||||
(fn [set-name]
|
||||
(swap! theme-state #(ctob/toggle-set % set-name))))
|
||||
on-change-field (fn [field value]
|
||||
(swap! theme-state #(assoc % field value)))
|
||||
group-input-ref (mf/use-ref)
|
||||
on-update-group (on-change-field [:theme :group])
|
||||
on-update-name (on-change-field [:theme :name])
|
||||
on-update-group (partial on-change-field :group)
|
||||
on-update-name (partial on-change-field :name)
|
||||
on-save-form (mf/use-callback
|
||||
(mf/deps theme-state on-submit)
|
||||
(fn [e]
|
||||
(dom/prevent-default e)
|
||||
(let [theme (:theme @theme-state)
|
||||
final-name (str/trim (:name theme))
|
||||
final-group (-> (:group theme)
|
||||
(str/trim)
|
||||
(str/lower))]
|
||||
(when-not (str/empty? final-name)
|
||||
(cond-> theme
|
||||
(empty final-group) (dissoc :group)
|
||||
:always on-submit)))
|
||||
(let [theme (-> @theme-state
|
||||
(update :name str/trim)
|
||||
(update :group str/trim)
|
||||
(update :description str/trim))]
|
||||
(when-not (str/empty? (:name theme))
|
||||
(on-submit theme)))
|
||||
(on-back)))]
|
||||
[:form {:on-submit on-save-form}
|
||||
[:div {:class (stl/css :edit-theme-wrapper)}
|
||||
|
@ -165,23 +157,23 @@
|
|||
theme-groups)
|
||||
:on-select (fn [{:keys [value]}]
|
||||
(set! (.-value (mf/ref-val group-input-ref)) value)
|
||||
(swap! theme-state assoc-in [:theme :group] value))
|
||||
(on-update-group value))
|
||||
:on-close on-close-dropdown}])
|
||||
[:& labeled-input {:label "Group"
|
||||
:input-props {:ref group-input-ref
|
||||
:default-value (:group theme)
|
||||
:on-change on-update-group}
|
||||
:on-change (comp on-update-group dom/get-target-val)}
|
||||
:render-right (when (seq theme-groups)
|
||||
(mf/fnc []
|
||||
[:button {:class (stl/css :group-drop-down-button)
|
||||
:type "button"
|
||||
:on-click (fn [e]
|
||||
(dom/stop-propagation e)
|
||||
(on-toggle-dropdown))}
|
||||
i/arrow]))}]]
|
||||
[:button {:class (stl/css :group-drop-down-button)
|
||||
:type "button"
|
||||
:on-click (fn [e]
|
||||
(dom/stop-propagation e)
|
||||
(on-toggle-dropdown))}
|
||||
i/arrow]))}]]
|
||||
[:& labeled-input {:label "Theme"
|
||||
:input-props {:default-value (:name theme)
|
||||
:on-change on-update-name}}]]
|
||||
:on-change (comp on-update-name dom/get-target-val)}}]]
|
||||
[:div {:class (stl/css :sets-list-wrapper)}
|
||||
[:& wts/controlled-sets-list
|
||||
{:token-sets token-sets
|
||||
|
@ -195,7 +187,7 @@
|
|||
[:button {:class (stl/css :button-secondary)
|
||||
:type "button"
|
||||
:on-click (fn []
|
||||
(st/emit! (wdt/delete-token-theme (:id theme)))
|
||||
(st/emit! (wdt/delete-token-theme (:group theme) (:name theme)))
|
||||
(on-back))}
|
||||
"Delete"]
|
||||
[:div])
|
||||
|
@ -212,32 +204,35 @@
|
|||
|
||||
(mf/defc controlled-edit-theme
|
||||
[{:keys [state set-state]}]
|
||||
(let [{:keys [theme-id]} @state
|
||||
(let [{:keys [theme-path]} @state
|
||||
[_ theme-group theme-name] theme-path
|
||||
token-sets (mf/deref refs/workspace-ordered-token-sets)
|
||||
theme (mf/deref (refs/workspace-token-theme theme-id))
|
||||
theme (mf/deref (refs/workspace-token-theme theme-group theme-name))
|
||||
theme-groups (mf/deref refs/workspace-token-theme-groups)]
|
||||
[:& edit-theme
|
||||
{:token-sets token-sets
|
||||
{:edit? true
|
||||
:token-sets token-sets
|
||||
:theme theme
|
||||
:theme-groups theme-groups
|
||||
:on-back #(set-state (constantly {:type :themes-overview}))
|
||||
:on-submit #(st/emit! (wdt/update-token-theme %))}]))
|
||||
:on-submit #(st/emit! (wdt/update-token-theme [(:group theme) (:name theme)] %))}]))
|
||||
|
||||
(mf/defc create-theme
|
||||
[{:keys [set-state]}]
|
||||
(let [token-sets (mf/deref refs/workspace-ordered-token-sets)
|
||||
theme {:name "" :sets #{}}
|
||||
theme (ctob/make-token-theme :name "")
|
||||
theme-groups (mf/deref refs/workspace-token-theme-groups)]
|
||||
[:& edit-theme
|
||||
{:token-sets token-sets
|
||||
{:edit? false
|
||||
:token-sets token-sets
|
||||
:theme theme
|
||||
:theme-groups theme-groups
|
||||
:on-back #(set-state (constantly {:type :themes-overview}))
|
||||
:on-submit #(st/emit! (wdt/create-token-theme %))}]))
|
||||
|
||||
(mf/defc themes
|
||||
[{:keys [] :as _args}]
|
||||
(let [themes (mf/deref refs/workspace-ordered-token-themes)
|
||||
[_]
|
||||
(let [themes (mf/deref refs/workspace-token-themes-no-hidden)
|
||||
state (mf/use-state (if (empty? themes)
|
||||
{:type :create-theme}
|
||||
{:type :themes-overview}))
|
||||
|
@ -258,7 +253,7 @@
|
|||
|
||||
(mf/defc modal
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [] :as _args}]
|
||||
[_]
|
||||
(let [handle-close-dialog (mf/use-callback #(st/emit! (modal/hide)))]
|
||||
[:div {:class (stl/css :modal-overlay)}
|
||||
[:div {:class (stl/css :modal-dialog)}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.workspace.tokens.sets
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.data.messages :as msg]
|
||||
[app.main.data.tokens :as wdt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -20,18 +21,18 @@
|
|||
(def ^:private chevron-icon
|
||||
(i/icon-xref :arrow (stl/css :chevron-icon)))
|
||||
|
||||
(defn on-toggle-token-set-click [token-set-id]
|
||||
(st/emit! (wdt/toggle-token-set {:token-set-id token-set-id})))
|
||||
(defn on-toggle-token-set-click [token-set-name]
|
||||
(st/emit! (wdt/toggle-token-set {:token-set-name token-set-name})))
|
||||
|
||||
(defn on-select-token-set-click [id]
|
||||
(st/emit! (wdt/set-selected-token-set-id id)))
|
||||
(defn on-select-token-set-click [name]
|
||||
(st/emit! (wdt/set-selected-token-set-id name)))
|
||||
|
||||
(defn on-delete-token-set-click [id name event]
|
||||
(defn on-delete-token-set-click [name event]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (wdt/delete-token-set id name)))
|
||||
(st/emit! (wdt/delete-token-set name)))
|
||||
|
||||
(defn on-update-token-set [token-set]
|
||||
(st/emit! (wdt/update-token-set token-set)))
|
||||
(defn on-update-token-set [set-name token-set]
|
||||
(st/emit! (wdt/update-token-set set-name token-set)))
|
||||
|
||||
(defn on-create-token-set [token-set]
|
||||
(st/emit! (wdt/create-token-set token-set)))
|
||||
|
@ -71,21 +72,21 @@
|
|||
on-submit
|
||||
on-cancel]
|
||||
:as _props}]
|
||||
(let [{:keys [id name _children]} token-set
|
||||
selected? (and set? (token-set-selected? id))
|
||||
visible? (token-set-active? id)
|
||||
(let [{:keys [name _children]} token-set
|
||||
selected? (and set? (token-set-selected? name))
|
||||
visible? (token-set-active? name)
|
||||
collapsed? (mf/use-state false)
|
||||
set? true #_(= type :set)
|
||||
group? false #_(= type :group)
|
||||
editing-node? (editing? id)
|
||||
editing-node? (editing? name)
|
||||
on-select (mf/use-callback
|
||||
(mf/deps editing-node?)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when-not editing-node?
|
||||
(on-select id))))
|
||||
(on-select name))))
|
||||
on-context-menu (mf/use-callback
|
||||
(mf/deps editing-node? id)
|
||||
(mf/deps editing-node? name)
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
|
@ -93,11 +94,10 @@
|
|||
(st/emit!
|
||||
(wdt/show-token-set-context-menu
|
||||
{:position (dom/get-client-position event)
|
||||
:token-set-id id
|
||||
:token-set-name name})))))]
|
||||
[:div {:class (stl/css :set-item-container)
|
||||
:on-click on-select
|
||||
:on-double-click #(on-edit id)
|
||||
:on-double-click #(on-edit name)
|
||||
:on-context-menu on-context-menu}
|
||||
[:div {:class (stl/css-case :set-item-group group?
|
||||
:set-item-set set?
|
||||
|
@ -116,14 +116,14 @@
|
|||
[:*
|
||||
[:div {:class (stl/css :set-name)} name]
|
||||
[:div {:class (stl/css :delete-set)}
|
||||
[:button {:on-click #(on-delete-token-set-click id name %)
|
||||
[:button {:on-click #(on-delete-token-set-click name %)
|
||||
:type "button"}
|
||||
i/delete]]
|
||||
(if set?
|
||||
[:span {:class (stl/css :action-btn)
|
||||
:on-click (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(on-toggle id))}
|
||||
(on-toggle name))}
|
||||
(if visible? i/shown i/hide)]
|
||||
nil
|
||||
#_(when (and children (not @collapsed?))
|
||||
|
@ -134,6 +134,12 @@
|
|||
:set-id child-id
|
||||
:selected-set-id selected-token-set-id)])]))])]]))
|
||||
|
||||
(defn warn-on-try-create-token-set-group! []
|
||||
(st/emit! (msg/show {:content "Token Set grouping is not supported yet."
|
||||
:notification-type :toast
|
||||
:type :warning
|
||||
:timeout 3000})))
|
||||
|
||||
(mf/defc controlled-sets-list
|
||||
[{:keys [token-sets
|
||||
on-update-token-set
|
||||
|
@ -144,22 +150,27 @@
|
|||
on-select
|
||||
context]
|
||||
:as _props}]
|
||||
(let [{:keys [editing? new? on-edit on-create on-reset] :as ctx} (or context (sets-context/use-context))]
|
||||
(let [{:keys [editing? new? on-edit on-create on-reset] :as ctx} (or context (sets-context/use-context))
|
||||
avoid-token-set-grouping #(str/replace % "/" "-")]
|
||||
[:ul {:class (stl/css :sets-list)}
|
||||
(for [[id token-set] token-sets]
|
||||
(for [token-set token-sets]
|
||||
(when token-set
|
||||
[:& sets-tree {:key id
|
||||
:token-set token-set
|
||||
:token-set-selected? (if new? (constantly false) token-set-selected?)
|
||||
:token-set-active? token-set-active?
|
||||
:editing? editing?
|
||||
:on-select on-select
|
||||
:on-edit on-edit
|
||||
:on-toggle on-toggle-token-set
|
||||
:on-submit #(do
|
||||
(on-update-token-set %)
|
||||
(on-reset))
|
||||
:on-cancel on-reset}]))
|
||||
[:& sets-tree
|
||||
{:key (:name token-set)
|
||||
:token-set token-set
|
||||
:token-set-selected? (if new? (constantly false) token-set-selected?)
|
||||
:token-set-active? token-set-active?
|
||||
:editing? editing?
|
||||
:on-select on-select
|
||||
:on-edit on-edit
|
||||
:on-toggle on-toggle-token-set
|
||||
:on-submit #(do
|
||||
;; TODO: We don't support set grouping for now so we rename sets for now
|
||||
(when (str/includes? (:name %) "/")
|
||||
(warn-on-try-create-token-set-group!))
|
||||
(on-update-token-set (avoid-token-set-grouping (:name token-set)) (update % :name avoid-token-set-grouping))
|
||||
(on-reset))
|
||||
:on-cancel on-reset}]))
|
||||
(when new?
|
||||
[:& sets-tree {:token-set {:name ""}
|
||||
:token-set-selected? (constantly true)
|
||||
|
@ -168,7 +179,10 @@
|
|||
:on-select (constantly nil)
|
||||
:on-edit on-create
|
||||
:on-submit #(do
|
||||
(on-create-token-set %)
|
||||
;; TODO: We don't support set grouping for now so we rename sets for now
|
||||
(when (str/includes? (:name %) "/")
|
||||
(warn-on-try-create-token-set-group!))
|
||||
(on-create-token-set (update % :name avoid-token-set-grouping))
|
||||
(on-reset))
|
||||
:on-cancel on-reset}])]))
|
||||
|
||||
|
@ -178,9 +192,9 @@
|
|||
selected-token-set-id (mf/deref refs/workspace-selected-token-set-id)
|
||||
token-set-selected? (mf/use-callback
|
||||
(mf/deps selected-token-set-id)
|
||||
(fn [id]
|
||||
(= id selected-token-set-id)))
|
||||
active-token-set-ids (mf/deref refs/workspace-active-set-ids)
|
||||
(fn [set-name]
|
||||
(= set-name selected-token-set-id)))
|
||||
active-token-set-ids (mf/deref refs/workspace-active-set-names)
|
||||
token-set-active? (mf/use-callback
|
||||
(mf/deps active-token-set-ids)
|
||||
(fn [id]
|
||||
|
|
|
@ -28,11 +28,11 @@
|
|||
[:span {:class (stl/css :title)} title]])
|
||||
|
||||
(mf/defc menu
|
||||
[{:keys [token-set-id token-set-name]}]
|
||||
[{:keys [token-set-name]}]
|
||||
(let [{:keys [on-edit]} (sets-context/use-context)]
|
||||
[:ul {:class (stl/css :context-list)}
|
||||
[:& menu-entry {:title "Rename" :on-click #(on-edit token-set-id)}]
|
||||
[:& menu-entry {:title "Delete" :on-click #(st/emit! (wdt/delete-token-set token-set-id token-set-name))}]]))
|
||||
[:& menu-entry {:title "Rename" :on-click #(on-edit token-set-name)}]
|
||||
[:& menu-entry {:title "Delete" :on-click #(st/emit! (wdt/delete-token-set token-set-name))}]]))
|
||||
|
||||
(mf/defc sets-context-menu
|
||||
[]
|
||||
|
@ -41,7 +41,6 @@
|
|||
left (+ (get-in mdata [:position :x]) 5)
|
||||
width (mf/use-state 0)
|
||||
dropdown-ref (mf/use-ref)
|
||||
token-set-id (:token-set-id mdata)
|
||||
token-set-name (:token-set-name mdata)]
|
||||
(mf/use-effect
|
||||
(mf/deps mdata)
|
||||
|
@ -54,5 +53,4 @@
|
|||
:ref dropdown-ref
|
||||
:style {:top top :left left}
|
||||
:on-context-menu prevent-default}
|
||||
[:& menu {:token-set-id token-set-id
|
||||
:token-set-name token-set-name}]]]))
|
||||
[:& menu {:token-set-name token-set-name}]]]))
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
[app.common.data :as d]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.tokens :as dt]
|
||||
[app.main.data.tokens :as wdt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.color-bullet :refer [color-bullet]]
|
||||
|
@ -19,7 +18,6 @@
|
|||
[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.common :refer [labeled-input]]
|
||||
[app.main.ui.workspace.tokens.context-menu :refer [token-context-menu]]
|
||||
[app.main.ui.workspace.tokens.core :as wtc]
|
||||
[app.main.ui.workspace.tokens.sets :refer [sets-list]]
|
||||
|
@ -34,7 +32,8 @@
|
|||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]
|
||||
[shadow.resource]))
|
||||
[shadow.resource]
|
||||
[app.common.types.tokens-lib :as ctob]))
|
||||
|
||||
(def lens:token-type-open-status
|
||||
(l/derived (l/in [:workspace-tokens :open-status]) st/state))
|
||||
|
@ -42,15 +41,6 @@
|
|||
(def ^:private download-icon
|
||||
(i/icon-xref :download (stl/css :download-icon)))
|
||||
|
||||
(def selected-set-id
|
||||
(l/derived :selected-set-id st/state))
|
||||
|
||||
;; Event Functions -------------------------------------------------------------
|
||||
|
||||
(defn on-set-add-click [_event]
|
||||
(when-let [set-name (js/window.prompt "Set name")]
|
||||
(st/emit! (wdt/create-token-set {:name set-name}))))
|
||||
|
||||
;; Components ------------------------------------------------------------------
|
||||
|
||||
(mf/defc token-pill
|
||||
|
@ -107,7 +97,7 @@
|
|||
(dom/stop-propagation event)
|
||||
(st/emit! (dt/show-token-context-menu {:type :token
|
||||
:position (dom/get-client-position event)
|
||||
:token-id (:id token)}))))
|
||||
:token-name (:name token)}))))
|
||||
|
||||
on-toggle-open-click (mf/use-fn
|
||||
(mf/deps open? tokens)
|
||||
|
@ -117,7 +107,6 @@
|
|||
(let [{:keys [key fields]} modal]
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dt/set-token-type-section-open type true))
|
||||
(js/console.log "key" key)
|
||||
(modal/show! key {:x (.-clientX ^js event)
|
||||
:y (.-clientY ^js event)
|
||||
:position :right
|
||||
|
@ -151,7 +140,7 @@
|
|||
(for [token (sort-by :modified-at tokens)]
|
||||
(let [theme-token (get active-theme-tokens (wtt/token-identifier token))]
|
||||
[:& token-pill
|
||||
{:key (:id token)
|
||||
{:key (:name token)
|
||||
:token token
|
||||
:theme-token theme-token
|
||||
:highlighted? (wtt/shapes-token-applied? token selected-shapes (or all-attributes attributes))
|
||||
|
@ -162,7 +151,7 @@
|
|||
"Separate token-types into groups of `:empty` or `:filled` depending if tokens exist for that type.
|
||||
Sort each group alphabetically (by their `:token-key`)."
|
||||
[tokens]
|
||||
(let [tokens-by-type (wtc/group-tokens-by-type tokens)
|
||||
(let [tokens-by-type (ctob/group-by-type tokens)
|
||||
{:keys [empty filled]} (->> wtty/token-types
|
||||
(map (fn [[token-key token-type-props]]
|
||||
{:token-key token-key
|
||||
|
@ -173,23 +162,6 @@
|
|||
{:empty (sort-by :token-key empty)
|
||||
:filled (sort-by :token-key filled)}))
|
||||
|
||||
(mf/defc tokene-theme-create
|
||||
[_props]
|
||||
(let [group (mf/use-state "")
|
||||
name (mf/use-state "")]
|
||||
[:div {:style {:display "flex"
|
||||
:flex-direction "column"
|
||||
:gap "10px"}}
|
||||
[:& labeled-input {:label "Group name"
|
||||
:input-props {:value @group
|
||||
:on-change #(reset! group (dom/event->value %))}}]
|
||||
[:& labeled-input {:label "Theme name"
|
||||
:input-props {:value @name
|
||||
:on-change #(reset! name (dom/event->value %))}}]
|
||||
[:button {:on-click #(st/emit! (wdt/create-token-theme {:group @group
|
||||
:name @name}))}
|
||||
"Create"]]))
|
||||
|
||||
(mf/defc edit-button
|
||||
[{:keys [create?]}]
|
||||
[:button {:class (stl/css :themes-button)
|
||||
|
@ -200,7 +172,7 @@
|
|||
|
||||
(mf/defc themes-sidebar
|
||||
[_props]
|
||||
(let [ordered-themes (mf/deref refs/workspace-ordered-token-themes)]
|
||||
(let [ordered-themes (mf/deref refs/workspace-token-themes-no-hidden)]
|
||||
[:div {:class (stl/css :theme-sidebar)}
|
||||
[:span {:class (stl/css :themes-header)} "Themes"]
|
||||
[:div {:class (stl/css :theme-select-wrapper)}
|
||||
|
@ -241,7 +213,6 @@
|
|||
selected (mf/deref refs/selected-shapes)
|
||||
selected-shapes (into [] (keep (d/getf objects)) selected)
|
||||
|
||||
|
||||
active-theme-tokens (sd/use-active-theme-sets-tokens)
|
||||
|
||||
tokens (sd/use-resolved-workspace-tokens)
|
||||
|
|
|
@ -72,34 +72,33 @@
|
|||
|
||||
(defn resolve-tokens+
|
||||
[tokens & {:keys [names-map?] :as config}]
|
||||
(p/let [sd-tokens (-> (wtt/token-names-tree tokens)
|
||||
(resolve-sd-tokens+))]
|
||||
(let [resolved-tokens (reduce
|
||||
(fn [acc ^js cur]
|
||||
(let [identifier (if names-map?
|
||||
(.. cur -original -name)
|
||||
(uuid (.-uuid (.-id cur))))
|
||||
{:keys [type] :as origin-token} (get tokens identifier)
|
||||
value (.-value cur)
|
||||
token-or-err (case type
|
||||
:color (if-let [tc (tinycolor/valid-color value)]
|
||||
{:value value :unit (tinycolor/color-format tc)}
|
||||
{:errors [(wte/error-with-value :error.token/invalid-color value)]})
|
||||
(or (wtt/parse-token-value value)
|
||||
(if-let [references (-> (wtt/find-token-references value)
|
||||
(seq))]
|
||||
{:errors [(wte/error-with-value :error.style-dictionary/missing-reference references)]
|
||||
:references references}
|
||||
{:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]})))
|
||||
output-token (if (:errors token-or-err)
|
||||
(merge origin-token token-or-err)
|
||||
(assoc origin-token
|
||||
:resolved-value (:value token-or-err)
|
||||
:unit (:unit token-or-err)))]
|
||||
(assoc acc (wtt/token-identifier output-token) output-token)))
|
||||
{} sd-tokens)]
|
||||
(l/debug :hint "Resolved tokens" :js/tokens resolved-tokens)
|
||||
resolved-tokens)))
|
||||
(let [{:keys [tree ids-map]} (wtt/token-names-tree-id-map tokens)]
|
||||
(p/let [sd-tokens (resolve-sd-tokens+ tree)]
|
||||
(let [resolved-tokens (reduce
|
||||
(fn [acc ^js cur]
|
||||
(let [{:keys [type] :as origin-token} (if names-map?
|
||||
(get tokens (.. cur -original -name))
|
||||
(get ids-map (uuid (.-uuid (.-id cur)))))
|
||||
value (.-value cur)
|
||||
token-or-err (case type
|
||||
:color (if-let [tc (tinycolor/valid-color value)]
|
||||
{:value value :unit (tinycolor/color-format tc)}
|
||||
{:errors [(wte/error-with-value :error.token/invalid-color value)]})
|
||||
(or (wtt/parse-token-value value)
|
||||
(if-let [references (-> (wtt/find-token-references value)
|
||||
(seq))]
|
||||
{:errors [(wte/error-with-value :error.style-dictionary/missing-reference references)]
|
||||
:references references}
|
||||
{:errors [(wte/error-with-value :error.style-dictionary/invalid-token-value value)]})))
|
||||
output-token (if (:errors token-or-err)
|
||||
(merge origin-token token-or-err)
|
||||
(assoc origin-token
|
||||
:resolved-value (:value token-or-err)
|
||||
:unit (:unit token-or-err)))]
|
||||
(assoc acc (wtt/token-identifier output-token) output-token)))
|
||||
{} sd-tokens)]
|
||||
(l/debug :hint "Resolved tokens" :js/tokens resolved-tokens)
|
||||
resolved-tokens))))
|
||||
|
||||
;; Hooks -----------------------------------------------------------------------
|
||||
|
||||
|
@ -115,7 +114,7 @@
|
|||
|
||||
This hook will return the unresolved tokens as state until they are processed,
|
||||
then the state will be updated with the resolved tokens."
|
||||
[tokens & {:keys [cache-atom _names-map?]
|
||||
[tokens & {:keys [cache-atom names-map?]
|
||||
:or {cache-atom !tokens-cache}
|
||||
:as config}]
|
||||
(let [tokens-state (mf/use-state (get @cache-atom tokens))]
|
||||
|
@ -124,8 +123,11 @@
|
|||
(fn []
|
||||
(let [cached (get @cache-atom tokens)]
|
||||
(cond
|
||||
(nil? tokens) (if names-map? {} [])
|
||||
;; The tokens are already processing somewhere
|
||||
(p/promise? cached) (p/then cached #(reset! tokens-state %))
|
||||
(p/promise? cached) (-> cached
|
||||
(p/then #(reset! tokens-state %))
|
||||
#_(p/catch js/console.error))
|
||||
;; Get the cached entry
|
||||
(some? cached) (reset! tokens-state cached)
|
||||
;; No cached entry, start processing
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.workspace.tokens.theme-select
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.tokens :as wdt]
|
||||
|
@ -15,63 +16,58 @@
|
|||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc themes-list
|
||||
[{:keys [themes active-theme-ids on-close grouped?]}]
|
||||
[{:keys [themes active-theme-paths on-close grouped?]}]
|
||||
(when (seq themes)
|
||||
[:ul
|
||||
(for [{:keys [id name]} themes
|
||||
:let [selected? (get active-theme-ids id)]]
|
||||
[:li {:key id
|
||||
(for [[_ {:keys [group name] :as theme}] themes
|
||||
:let [theme-id (ctob/theme-path theme)
|
||||
selected? (get active-theme-paths theme-id)]]
|
||||
[:li {:key theme-id
|
||||
:class (stl/css-case
|
||||
:checked-element true
|
||||
:sub-item grouped?
|
||||
:is-selected selected?)
|
||||
:on-click (fn [e]
|
||||
(dom/stop-propagation e)
|
||||
(st/emit! (wdt/toggle-token-theme id))
|
||||
(st/emit! (wdt/toggle-token-theme-active? group name))
|
||||
(on-close))}
|
||||
[:span {:class (stl/css :label)} name]
|
||||
[:span {:class (stl/css :check-icon)} i/tick]])]))
|
||||
|
||||
(mf/defc theme-options
|
||||
[{:keys [on-close]}]
|
||||
(let [active-theme-ids (mf/deref refs/workspace-active-theme-ids)
|
||||
ordered-themes (mf/deref refs/workspace-ordered-token-themes)
|
||||
grouped-themes (dissoc ordered-themes nil)
|
||||
ungrouped-themes (get ordered-themes nil)]
|
||||
[:ul
|
||||
[:& themes-list {:themes ungrouped-themes
|
||||
:active-theme-ids active-theme-ids
|
||||
:on-close on-close}]
|
||||
(for [[group themes] grouped-themes]
|
||||
[:li {:key group}
|
||||
(when group
|
||||
[:span {:class (stl/css :group)} group])
|
||||
[:& themes-list {:themes themes
|
||||
:active-theme-ids active-theme-ids
|
||||
:on-close on-close
|
||||
:grouped? true}]])
|
||||
[:li {:class (stl/css-case :checked-element true
|
||||
:checked-element-button true)
|
||||
:on-click #(modal/show! :tokens/themes {})}
|
||||
[:span "Edit themes"]
|
||||
[:span {:class (stl/css :icon)} i/arrow]]]))
|
||||
[{:keys [active-theme-paths themes on-close]}]
|
||||
[:ul
|
||||
(for [[group themes] themes]
|
||||
[:li {:key group}
|
||||
(when (seq group)
|
||||
[:span {:class (stl/css :group)} group])
|
||||
[:& themes-list {:themes themes
|
||||
:active-theme-paths active-theme-paths
|
||||
:on-close on-close
|
||||
:grouped? true}]])
|
||||
[:li {:class (stl/css-case :checked-element true
|
||||
:checked-element-button true)
|
||||
:on-click #(modal/show! :tokens/themes {})}
|
||||
[:span "Edit themes"]
|
||||
[:span {:class (stl/css :icon)} i/arrow]]])
|
||||
|
||||
(mf/defc theme-select
|
||||
[{:keys []}]
|
||||
(let [;; Store
|
||||
temp-theme-id (mf/deref refs/workspace-temp-theme-id)
|
||||
active-theme-ids (-> (mf/deref refs/workspace-active-theme-ids)
|
||||
(disj temp-theme-id))
|
||||
active-themes-count (count active-theme-ids)
|
||||
themes (mf/deref refs/workspace-token-themes)
|
||||
active-theme-paths (mf/deref refs/workspace-active-theme-paths-no-hidden)
|
||||
active-themes-count (count active-theme-paths)
|
||||
themes (mf/deref refs/workspace-token-theme-tree-no-hidden)
|
||||
|
||||
;; Data
|
||||
current-label (cond
|
||||
(> active-themes-count 1) (str active-themes-count " themes active")
|
||||
(pos? active-themes-count) (get-in themes [(first active-theme-ids) :name])
|
||||
(= active-themes-count 1) (some->> (first active-theme-paths)
|
||||
(ctob/split-token-theme-path)
|
||||
(str/join " / "))
|
||||
:else "No theme active")
|
||||
|
||||
;; State
|
||||
|
@ -92,4 +88,6 @@
|
|||
[:& dropdown {:show is-open? :on-close on-close-dropdown}
|
||||
[:div {:ref dropdown-element*
|
||||
:class (stl/css :custom-select-dropdown)}
|
||||
[:& theme-options {:on-close on-close-dropdown}]]]]))
|
||||
[:& theme-options {:active-theme-paths active-theme-paths
|
||||
:themes themes
|
||||
:on-close on-close-dropdown}]]]]))
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
(:require
|
||||
["tinycolor2" :as tinycolor]))
|
||||
|
||||
(defn tinycolor? [x]
|
||||
(defn tinycolor? [^js x]
|
||||
(and (instance? tinycolor x) (.isValid x)))
|
||||
|
||||
(defn valid-color [color-str]
|
||||
(let [tc (tinycolor color-str)]
|
||||
(when (.isValid tc) tc)))
|
||||
|
||||
(defn ->hex [tc]
|
||||
(defn ->hex [^js tc]
|
||||
(assert (tinycolor? tc))
|
||||
(.toHex tc))
|
||||
|
||||
(defn color-format [tc]
|
||||
(defn color-format [^js tc]
|
||||
(assert (tinycolor? tc))
|
||||
(.getFormat tc))
|
||||
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
(ns app.main.ui.workspace.tokens.token
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.workspace.tokens.tinycolor :as tinycolor]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
[app.main.ui.workspace.tokens.tinycolor :as tinycolor]))
|
||||
|
||||
(defn get-workspace-tokens
|
||||
[state]
|
||||
(get-in state [:workspace-data :tokens] {}))
|
||||
|
||||
(defn get-workspace-token
|
||||
[token-id state]
|
||||
(get-in state [:workspace-data :tokens token-id]))
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(def parseable-token-value-regexp
|
||||
"Regexp that can be used to parse a number value out of resolved token value.
|
||||
|
@ -66,12 +59,6 @@
|
|||
[token shape token-attributes]
|
||||
(some #(token-attribute-applied? token shape %) token-attributes))
|
||||
|
||||
(defn token-applied-attributes
|
||||
"Return a set of which `token-attributes` are applied with `token`."
|
||||
[token shape token-attributes]
|
||||
(-> (filter #(token-attribute-applied? token shape %) token-attributes)
|
||||
(set)))
|
||||
|
||||
(defn shapes-token-applied?
|
||||
"Test if `token` is applied to to any of `shapes` with at least one of the one of the given `token-attributes`."
|
||||
[token shapes token-attributes]
|
||||
|
@ -117,6 +104,19 @@
|
|||
(->> (map (fn [{:keys [name] :as token}] [name token]) tokens)
|
||||
(into {})))
|
||||
|
||||
(defn token-names-tree-id-map [tokens]
|
||||
(reduce
|
||||
(fn [acc [_ {:keys [name] :as token}]]
|
||||
(when (string? name)
|
||||
(let [temp-id (random-uuid)
|
||||
token (assoc token :temp/id temp-id)]
|
||||
(-> acc
|
||||
(assoc-in (concat [:tree] (token-name->path name)) token)
|
||||
(assoc-in [:ids-map temp-id] token)))))
|
||||
{:tree {}
|
||||
:ids-map {}}
|
||||
tokens))
|
||||
|
||||
(defn token-names-tree
|
||||
"Convert tokens into a nested tree with their `:name` as the path."
|
||||
[tokens]
|
||||
|
|
|
@ -1,100 +1,18 @@
|
|||
(ns app.main.ui.workspace.tokens.token-set
|
||||
(:require
|
||||
[app.common.data :refer [ordered-map]]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[clojure.set :as set]))
|
||||
[app.common.types.tokens-lib :as ctob]))
|
||||
|
||||
(defn get-workspace-tokens-lib [state]
|
||||
(get-in state [:workspace-data :tokens-lib]))
|
||||
|
||||
;; Themes ----------------------------------------------------------------------
|
||||
|
||||
(defn get-workspace-themes [state]
|
||||
(get-in state [:workspace-data :token-themes] []))
|
||||
|
||||
(defn get-workspace-theme [id state]
|
||||
(get-in state [:workspace-data :token-themes-index id]))
|
||||
|
||||
(defn get-workspace-themes-index [state]
|
||||
(get-in state [:workspace-data :token-themes-index] {}))
|
||||
|
||||
(defn get-workspace-theme-groups [state]
|
||||
(reduce
|
||||
(fn [acc {:keys [group]}]
|
||||
(if group
|
||||
(conj acc group)
|
||||
acc))
|
||||
#{} (vals (get-workspace-themes-index state))))
|
||||
|
||||
(defn get-workspace-token-set-groups [state]
|
||||
(get-in state [:workspace-data :token-set-groups]))
|
||||
|
||||
(defn get-workspace-ordered-themes [state]
|
||||
(let [themes (get-workspace-themes state)
|
||||
themes-index (get-workspace-themes-index state)]
|
||||
(->> (map #(get themes-index %) themes)
|
||||
(group-by :group))))
|
||||
|
||||
(defn get-active-theme-ids [state]
|
||||
(get-in state [:workspace-data :token-active-themes] #{}))
|
||||
|
||||
(defn get-temp-theme-id [state]
|
||||
(get-in state [:workspace-data :token-theme-temporary-id]))
|
||||
|
||||
(defn get-active-theme-ids-or-fallback [state]
|
||||
(let [active-theme-ids (get-active-theme-ids state)
|
||||
temp-theme-id (get-temp-theme-id state)]
|
||||
(cond
|
||||
(seq active-theme-ids) active-theme-ids
|
||||
temp-theme-id #{temp-theme-id})))
|
||||
|
||||
(defn get-active-set-ids [state]
|
||||
(let [active-theme-ids (get-active-theme-ids-or-fallback state)
|
||||
themes-index (get-workspace-themes-index state)
|
||||
active-set-ids (reduce
|
||||
(fn [acc cur]
|
||||
(if-let [sets (get-in themes-index [cur :sets])]
|
||||
(set/union acc sets)
|
||||
acc))
|
||||
#{} active-theme-ids)]
|
||||
active-set-ids))
|
||||
|
||||
(defn get-ordered-active-set-ids [state]
|
||||
(let [active-set-ids (get-active-set-ids state)
|
||||
token-set-groups (get-workspace-token-set-groups state)]
|
||||
(filter active-set-ids token-set-groups)))
|
||||
|
||||
(defn theme-ids-with-group
|
||||
"Returns set of theme-ids that share the same `:group` property as the theme with `theme-id`.
|
||||
Will also return matching theme-ids without a `:group` property."
|
||||
[theme-id state]
|
||||
(let [themes (get-workspace-themes-index state)
|
||||
theme-group (get-in themes [theme-id :group])
|
||||
same-group-theme-ids (->> themes
|
||||
(eduction
|
||||
(map val)
|
||||
(filter #(= (:group %) theme-group))
|
||||
(map :id))
|
||||
(into #{}))]
|
||||
same-group-theme-ids))
|
||||
|
||||
(defn toggle-active-theme-id
|
||||
"Toggle a `theme-id` by checking `:token-active-themes`.
|
||||
Deactivate all theme-ids that have the same group as `theme-id` when activating `theme-id`.
|
||||
Ensures that the temporary theme id is selected when the resulting set is empty."
|
||||
[theme-id state]
|
||||
(let [temp-theme-id-set (some->> (get-temp-theme-id state) (conj #{}))
|
||||
active-theme-ids (get-active-theme-ids state)
|
||||
add? (not (get active-theme-ids theme-id))
|
||||
;; Deactivate themes with the same group when activating a theme
|
||||
same-group-ids (when add? (theme-ids-with-group theme-id state))
|
||||
theme-ids-without-same-group (set/difference active-theme-ids
|
||||
same-group-ids
|
||||
temp-theme-id-set)
|
||||
new-themes (if add?
|
||||
(conj theme-ids-without-same-group theme-id)
|
||||
(disj theme-ids-without-same-group theme-id))]
|
||||
(if (empty? new-themes)
|
||||
(or temp-theme-id-set #{})
|
||||
new-themes)))
|
||||
|
||||
(defn update-theme-id
|
||||
[state]
|
||||
(let [active-themes (get-active-theme-ids state)
|
||||
|
@ -110,67 +28,29 @@
|
|||
(defn add-token-set-to-token-theme [token-set-id token-theme]
|
||||
(update token-theme :sets conj token-set-id))
|
||||
|
||||
(defn toggle-token-set-to-token-theme [token-set-id token-theme]
|
||||
(update token-theme :sets #(if (get % token-set-id)
|
||||
(disj % token-set-id)
|
||||
(conj % token-set-id))))
|
||||
|
||||
;; Sets ------------------------------------------------------------------------
|
||||
|
||||
(defn get-workspace-sets [state]
|
||||
(get-in state [:workspace-data :token-sets-index]))
|
||||
(defn get-active-theme-sets-tokens-names-map [state]
|
||||
(when-let [lib (get-workspace-tokens-lib state)]
|
||||
(ctob/get-active-themes-set-tokens lib)))
|
||||
|
||||
(defn get-workspace-ordered-sets [state]
|
||||
;; TODO Include groups
|
||||
(let [top-level-set-ids (get-in state [:workspace-data :token-set-groups])
|
||||
token-sets (get-workspace-sets state)]
|
||||
(->> (map (fn [id] [id (get token-sets id)]) top-level-set-ids)
|
||||
(into (ordered-map)))))
|
||||
|
||||
(defn get-workspace-ordered-sets-tokens [state]
|
||||
(let [sets (get-workspace-ordered-sets state)]
|
||||
(reduce
|
||||
(fn [acc [_ {:keys [tokens] :as sets}]]
|
||||
(reduce (fn [acc' token-id]
|
||||
(if-let [token (wtt/get-workspace-token token-id state)]
|
||||
(assoc acc' (wtt/token-identifier token) token)
|
||||
acc'))
|
||||
acc tokens))
|
||||
{} sets)))
|
||||
|
||||
(defn get-token-set [set-id state]
|
||||
(some-> (get-workspace-sets state)
|
||||
(get set-id)))
|
||||
|
||||
(defn get-workspace-token-set-tokens [set-id state]
|
||||
(-> (get-token-set set-id state)
|
||||
:tokens))
|
||||
;; === Set selection
|
||||
|
||||
(defn get-selected-token-set-id [state]
|
||||
(or (get-in state [:workspace-local :selected-token-set-id])
|
||||
(get-in state [:workspace-data :token-set-groups 0])))
|
||||
(some-> (get-workspace-tokens-lib state)
|
||||
(ctob/get-sets)
|
||||
(first)
|
||||
(:name))))
|
||||
|
||||
(defn get-selected-token-set [state]
|
||||
(when-let [id (get-selected-token-set-id state)]
|
||||
(get-token-set id state)))
|
||||
(some-> (get-workspace-tokens-lib state)
|
||||
(ctob/get-set id))))
|
||||
|
||||
(defn get-selected-token-set-tokens [state]
|
||||
(when-let [token-set (get-selected-token-set state)]
|
||||
(let [tokens (or (wtt/get-workspace-tokens state) {})]
|
||||
(select-keys tokens (:tokens token-set)))))
|
||||
(some-> (get-selected-token-set state)
|
||||
:tokens))
|
||||
|
||||
(defn assoc-selected-token-set-id [state id]
|
||||
(assoc-in state [:workspace-local :selected-token-set-id] id))
|
||||
|
||||
(defn get-active-theme-sets-tokens-names-map [state]
|
||||
(let [active-set-ids (get-ordered-active-set-ids state)]
|
||||
(reduce
|
||||
(fn [names-map-acc set-id]
|
||||
(let [token-ids (get-workspace-token-set-tokens set-id state)]
|
||||
(reduce
|
||||
(fn [acc token-id]
|
||||
(if-let [token (wtt/get-workspace-token token-id state)]
|
||||
(assoc acc (wtt/token-identifier token) token)
|
||||
acc))
|
||||
names-map-acc token-ids)))
|
||||
(ordered-map) active-set-ids)))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns token-tests.helpers.state
|
||||
(:require
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.ui.workspace.tokens.style-dictionary :as sd]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -21,11 +22,10 @@
|
|||
(ptk/reify ::end+
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(->> (rx/from (sd/resolve-tokens+ (get-in state [:workspace-data :tokens])))
|
||||
(rx/mapcat
|
||||
(fn [_]
|
||||
(rx/of
|
||||
(end))))))))
|
||||
(->> (rx/from (-> (get-in state [:workspace-data :tokens-lib])
|
||||
(ctob/get-active-themes-set-tokens)
|
||||
(sd/resolve-tokens+ {:names-map? true})))
|
||||
(rx/mapcat #(rx/of (end)))))))
|
||||
|
||||
(defn stop-on
|
||||
"Helper function to be used with async version of run-store.
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
(ns token-tests.helpers.tokens
|
||||
(:require
|
||||
[app.common.test-helpers.ids-map :as thi]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]))
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[app.common.types.tokens-lib :as ctob]))
|
||||
|
||||
(defn add-token [state label params]
|
||||
(let [id (thi/new-id! label)
|
||||
token (assoc params :id id)]
|
||||
(update-in state [:data :tokens] assoc id token)))
|
||||
|
||||
(defn get-token [file label]
|
||||
(let [id (thi/id label)]
|
||||
(get-in file [:data :tokens id])))
|
||||
(defn get-token [file name]
|
||||
(some-> (get-in file [:data :tokens-lib])
|
||||
(ctob/get-active-themes-set-tokens)
|
||||
(get name)))
|
||||
|
||||
(defn apply-token-to-shape [file shape-label token-label attributes]
|
||||
(let [first-page-id (get-in file [:data :pages 0])
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
(ns token-tests.logic.token-actions-test
|
||||
(:require
|
||||
[app.common.pprint :refer [pprint]]
|
||||
[app.common.logging :as log]
|
||||
[app.common.test-helpers.compositions :as ctho]
|
||||
[app.common.test-helpers.files :as cthf]
|
||||
[app.common.test-helpers.shapes :as cths]
|
||||
[app.main.data.tokens :as wdt]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.ui.workspace.tokens.changes :as wtch]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[app.main.ui.workspace.tokens.token-set :as wtts]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.helpers.pages :as thp]
|
||||
[frontend-tests.helpers.state :as ths]
|
||||
|
@ -25,13 +22,13 @@
|
|||
(cthf/sample-file :file-1 :page-label :page-1))
|
||||
|
||||
(def border-radius-token
|
||||
{:value "12"
|
||||
:name "borderRadius.sm"
|
||||
{:name "borderRadius.sm"
|
||||
:value "12"
|
||||
:type :border-radius})
|
||||
|
||||
(def ^:private reference-border-radius-token
|
||||
{:value "{borderRadius.sm} * 2"
|
||||
:name "borderRadius.md"
|
||||
(def reference-border-radius-token
|
||||
{:name "borderRadius.md"
|
||||
:value "{borderRadius.sm} * 2"
|
||||
:type :border-radius})
|
||||
|
||||
(defn setup-file-with-tokens
|
||||
|
@ -40,45 +37,13 @@
|
|||
(ctho/add-rect :rect-1 rect-1)
|
||||
(ctho/add-rect :rect-2 rect-2)
|
||||
(ctho/add-rect :rect-3 rect-3)
|
||||
(toht/add-token :token-1 border-radius-token)
|
||||
(toht/add-token :token-2 reference-border-radius-token)))
|
||||
|
||||
(t/deftest test-create-token
|
||||
(t/testing "creates token in new token set"
|
||||
(t/async
|
||||
done
|
||||
(let [file (setup-file)
|
||||
store (ths/setup-store file)
|
||||
events [(wdt/update-create-token border-radius-token)]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [set-id (wtts/get-selected-token-set-id new-state)
|
||||
token-set (wtts/get-token-set set-id new-state)
|
||||
set-tokens (wtts/get-active-theme-sets-tokens-names-map new-state)]
|
||||
(t/testing "selects created workspace set and adds token to it"
|
||||
(t/is (some? token-set))
|
||||
(t/is (= 1 (count set-tokens)))
|
||||
(t/is (= (list border-radius-token) (->> (vals set-tokens)
|
||||
(map #(dissoc % :id :modified-at)))))))))))))
|
||||
|
||||
(t/deftest test-create-multiple-tokens
|
||||
(t/testing "uses selected tokens set when creating multiple tokens"
|
||||
(t/async
|
||||
done
|
||||
(let [file (setup-file)
|
||||
store (ths/setup-store file)
|
||||
events [(wdt/update-create-token border-radius-token)
|
||||
(wdt/update-create-token reference-border-radius-token)]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [set-tokens (wtts/get-active-theme-sets-tokens-names-map new-state)]
|
||||
(t/testing "selects created workspace set and adds token to it"
|
||||
(t/is (= 2 (count set-tokens)))
|
||||
(t/is (= (list border-radius-token reference-border-radius-token)
|
||||
(->> (vals set-tokens)
|
||||
(map #(dissoc % :id :modified-at)))))))))))))
|
||||
(assoc-in [:data :tokens-lib]
|
||||
(-> (ctob/make-tokens-lib)
|
||||
(ctob/add-theme (ctob/make-token-theme :name "Theme A" :sets #{"Set A"}))
|
||||
(ctob/set-active-themes #{"/Theme A"})
|
||||
(ctob/add-set (ctob/make-token-set :name "Set A"))
|
||||
(ctob/add-token-in-set "Set A" (ctob/make-token border-radius-token))
|
||||
(ctob/add-token-in-set "Set A" (ctob/make-token reference-border-radius-token))))))
|
||||
|
||||
(t/deftest test-apply-token
|
||||
(t/testing "applies token to shape and updates shape attributes to resolved value"
|
||||
|
@ -89,18 +54,18 @@
|
|||
rect-1 (cths/get-shape file :rect-1)
|
||||
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
|
||||
:attributes #{:rx :ry}
|
||||
:token (toht/get-token file :token-2)
|
||||
:token (toht/get-token file "borderRadius.md")
|
||||
:on-update-shape wtch/update-shape-radius-all})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-2' (toht/get-token file' :token-2)
|
||||
token (toht/get-token file' "borderRadius.md")
|
||||
rect-1' (cths/get-shape file' :rect-1)]
|
||||
(t/testing "shape `:applied-tokens` got updated"
|
||||
(t/is (some? (:applied-tokens rect-1')))
|
||||
(t/is (= (:rx (:applied-tokens rect-1')) (wtt/token-identifier token-2')))
|
||||
(t/is (= (:ry (:applied-tokens rect-1')) (wtt/token-identifier token-2'))))
|
||||
(t/is (= (:rx (:applied-tokens rect-1')) (:name token)))
|
||||
(t/is (= (:ry (:applied-tokens rect-1')) (:name token))))
|
||||
(t/testing "shape radius got update to the resolved token value."
|
||||
(t/is (= (:rx rect-1') 24))
|
||||
(t/is (= (:ry rect-1') 24))))))))))
|
||||
|
@ -114,22 +79,22 @@
|
|||
rect-1 (cths/get-shape file :rect-1)
|
||||
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
|
||||
:attributes #{:rx :ry}
|
||||
:token (toht/get-token file :token-1)
|
||||
:token (toht/get-token file "borderRadius.sm")
|
||||
: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)
|
||||
:token (toht/get-token file "borderRadius.md")
|
||||
:on-update-shape wtch/update-shape-radius-all})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-2' (toht/get-token file' :token-2)
|
||||
token (toht/get-token file' "borderRadius.md")
|
||||
rect-1' (cths/get-shape file' :rect-1)]
|
||||
(t/testing "shape `:applied-tokens` got updated"
|
||||
(t/is (some? (:applied-tokens rect-1')))
|
||||
(t/is (= (:rx (:applied-tokens rect-1')) (wtt/token-identifier token-2')))
|
||||
(t/is (= (:ry (:applied-tokens rect-1')) (wtt/token-identifier token-2'))))
|
||||
(t/is (= (:rx (:applied-tokens rect-1')) (:name token)))
|
||||
(t/is (= (:ry (:applied-tokens rect-1')) (:name token))))
|
||||
(t/testing "shape radius got update to the resolved token value."
|
||||
(t/is (= (:rx rect-1') 24))
|
||||
(t/is (= (:ry rect-1') 24))))))))))
|
||||
|
@ -141,9 +106,9 @@
|
|||
(let [file (setup-file-with-tokens)
|
||||
store (ths/setup-store file)
|
||||
rect-1 (cths/get-shape file :rect-1)
|
||||
events [;; Apply `:token-1` to all border radius attributes
|
||||
events [;; Apply "borderRadius.sm" to all border radius attributes
|
||||
(wtch/apply-token {:attributes #{:rx :ry :r1 :r2 :r3 :r4}
|
||||
:token (toht/get-token file :token-1)
|
||||
:token (toht/get-token file "borderRadius.sm")
|
||||
:shape-ids [(:id rect-1)]
|
||||
:on-update-shape wtch/update-shape-radius-all})
|
||||
;; Apply single `:r1` attribute to same shape
|
||||
|
@ -151,22 +116,22 @@
|
|||
;; but keep `:r4` for testing purposes
|
||||
(wtch/apply-token {:attributes #{:r1}
|
||||
:attributes-to-remove #{:rx :ry :r1 :r2 :r3}
|
||||
:token (toht/get-token file :token-2)
|
||||
:token (toht/get-token file "borderRadius.md")
|
||||
:shape-ids [(:id rect-1)]
|
||||
:on-update-shape wtch/update-shape-radius-all})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-1' (toht/get-token file' :token-1)
|
||||
token-2' (toht/get-token file' :token-2)
|
||||
token-sm (toht/get-token file' "borderRadius.sm")
|
||||
token-md (toht/get-token file' "borderRadius.md")
|
||||
rect-1' (cths/get-shape file' :rect-1)]
|
||||
(t/testing "other border-radius attributes got removed"
|
||||
(t/is (nil? (:rx (:applied-tokens rect-1')))))
|
||||
(t/testing "r1 got applied with :token-2"
|
||||
(t/is (= (:r1 (:applied-tokens rect-1')) (wtt/token-identifier token-2'))))
|
||||
(t/testing "while :r4 was kept"
|
||||
(t/is (= (:r4 (:applied-tokens rect-1')) (wtt/token-identifier token-1')))))))))));)))))))))))
|
||||
(t/testing "r1 got applied with borderRadius.md"
|
||||
(t/is (= (:r1 (:applied-tokens rect-1')) (:name token-md))))
|
||||
(t/testing "while :r4 was kept with borderRadius.sm"
|
||||
(t/is (= (:r4 (:applied-tokens rect-1')) (:name token-sm)))))))))))
|
||||
|
||||
(t/deftest test-apply-dimensions
|
||||
(t/testing "applies dimensions token and updates the shapes width and height"
|
||||
|
@ -196,30 +161,62 @@
|
|||
(t/is (= (:width rect-1') 100))
|
||||
(t/is (= (:height rect-1') 100))))))))))
|
||||
|
||||
(t/deftest test-apply-sizing
|
||||
(t/testing "applies sizing token and updates the shapes width and height"
|
||||
(t/deftest test-apply-dimensions
|
||||
(t/testing "applies dimensions token and updates the shapes width and height"
|
||||
(t/async
|
||||
done
|
||||
(let [file (-> (setup-file-with-tokens)
|
||||
(toht/add-token :token-target {:value "100"
|
||||
:name "sizing.sm"
|
||||
:type :sizing}))
|
||||
(let [dimensions-token {:name "dimensions.sm"
|
||||
:value "100"
|
||||
:type :dimensions}
|
||||
file (-> (setup-file-with-tokens)
|
||||
(update-in [:data :tokens-lib]
|
||||
#(ctob/add-token-in-set % "Set A" (ctob/make-token dimensions-token))))
|
||||
store (ths/setup-store file)
|
||||
rect-1 (cths/get-shape file :rect-1)
|
||||
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
|
||||
:attributes #{:width :height}
|
||||
:token (toht/get-token file :token-target)
|
||||
:token (toht/get-token file "dimensions.sm")
|
||||
:on-update-shape wtch/update-shape-dimensions})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-target' (toht/get-token file' :token-target)
|
||||
token-target' (toht/get-token file' "dimensions.sm")
|
||||
rect-1' (cths/get-shape file' :rect-1)]
|
||||
(t/testing "shape `:applied-tokens` got updated"
|
||||
(t/is (some? (:applied-tokens rect-1')))
|
||||
(t/is (= (:width (:applied-tokens rect-1')) (wtt/token-identifier token-target')))
|
||||
(t/is (= (:height (:applied-tokens rect-1')) (wtt/token-identifier token-target'))))
|
||||
(t/is (= (:width (:applied-tokens rect-1')) (:name token-target')))
|
||||
(t/is (= (:height (:applied-tokens rect-1')) (:name token-target'))))
|
||||
(t/testing "shapes width and height got updated"
|
||||
(t/is (= (:width rect-1') 100))
|
||||
(t/is (= (:height rect-1') 100))))))))))
|
||||
|
||||
(t/deftest test-apply-sizing
|
||||
(t/testing "applies sizing token and updates the shapes width and height"
|
||||
(t/async
|
||||
done
|
||||
(let [sizing-token {:name "sizing.sm"
|
||||
:value "100"
|
||||
:type :sizing}
|
||||
file (-> (setup-file-with-tokens)
|
||||
(update-in [:data :tokens-lib]
|
||||
#(ctob/add-token-in-set % "Set A" (ctob/make-token sizing-token))))
|
||||
store (ths/setup-store file)
|
||||
rect-1 (cths/get-shape file :rect-1)
|
||||
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
|
||||
:attributes #{:width :height}
|
||||
:token (toht/get-token file "sizing.sm")
|
||||
:on-update-shape wtch/update-shape-dimensions})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-target' (toht/get-token file' "sizing.sm")
|
||||
rect-1' (cths/get-shape file' :rect-1)]
|
||||
(t/testing "shape `:applied-tokens` got updated"
|
||||
(t/is (some? (:applied-tokens rect-1')))
|
||||
(t/is (= (:width (:applied-tokens rect-1')) (:name token-target')))
|
||||
(t/is (= (:height (:applied-tokens rect-1')) (:name token-target'))))
|
||||
(t/testing "shapes width and height got updated"
|
||||
(t/is (= (:width rect-1') 100))
|
||||
(t/is (= (:height rect-1') 100))))))))))
|
||||
|
@ -228,31 +225,36 @@
|
|||
(t/testing "applies opacity token and updates the shapes opacity"
|
||||
(t/async
|
||||
done
|
||||
(let [file (-> (setup-file-with-tokens)
|
||||
(toht/add-token :opacity-float {:value "0.3"
|
||||
:name "opacity.float"
|
||||
:type :opacity})
|
||||
(toht/add-token :opacity-percent {:value "40%"
|
||||
:name "opacity.percent"
|
||||
:type :opacity})
|
||||
(toht/add-token :opacity-invalid {:value "100"
|
||||
:name "opacity.invalid"
|
||||
:type :opacity}))
|
||||
(let [opacity-float {:name "opacity.float"
|
||||
:value "0.3"
|
||||
:type :opacity}
|
||||
opacity-percent {:name "opacity.percent"
|
||||
:value "40%"
|
||||
:type :opacity}
|
||||
opacity-invalid {:name "opacity.invalid"
|
||||
:value "100"
|
||||
:type :opacity}
|
||||
file (-> (setup-file-with-tokens)
|
||||
(update-in [:data :tokens-lib]
|
||||
#(-> %
|
||||
(ctob/add-token-in-set "Set A" (ctob/make-token opacity-float))
|
||||
(ctob/add-token-in-set "Set A" (ctob/make-token opacity-percent))
|
||||
(ctob/add-token-in-set "Set A" (ctob/make-token opacity-invalid)))))
|
||||
store (ths/setup-store file)
|
||||
rect-1 (cths/get-shape file :rect-1)
|
||||
rect-2 (cths/get-shape file :rect-2)
|
||||
rect-3 (cths/get-shape file :rect-3)
|
||||
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
|
||||
:attributes #{:opacity}
|
||||
:token (toht/get-token file :opacity-float)
|
||||
:token (toht/get-token file "opacity.float")
|
||||
:on-update-shape wtch/update-opacity})
|
||||
(wtch/apply-token {:shape-ids [(:id rect-2)]
|
||||
:attributes #{:opacity}
|
||||
:token (toht/get-token file :opacity-percent)
|
||||
:token (toht/get-token file "opacity.percent")
|
||||
:on-update-shape wtch/update-opacity})
|
||||
(wtch/apply-token {:shape-ids [(:id rect-3)]
|
||||
:attributes #{:opacity}
|
||||
:token (toht/get-token file :opacity-invalid)
|
||||
:token (toht/get-token file "opacity.invalid")
|
||||
:on-update-shape wtch/update-opacity})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
|
@ -261,74 +263,78 @@
|
|||
rect-1' (cths/get-shape file' :rect-1)
|
||||
rect-2' (cths/get-shape file' :rect-2)
|
||||
rect-3' (cths/get-shape file' :rect-3)
|
||||
token-opacity-float (toht/get-token file' :opacity-float)
|
||||
token-opacity-percent (toht/get-token file' :opacity-percent)
|
||||
token-opacity-invalid (toht/get-token file' :opacity-invalid)]
|
||||
token-opacity-float (toht/get-token file' "opacity.float")
|
||||
token-opacity-percent (toht/get-token file' "opacity.percent")
|
||||
token-opacity-invalid (toht/get-token file' "opacity.invalid")]
|
||||
(t/testing "float value got translated to float and applied to opacity"
|
||||
(t/is (= (:opacity (:applied-tokens rect-1')) (wtt/token-identifier token-opacity-float)))
|
||||
(t/is (= (:opacity (:applied-tokens rect-1')) (:name token-opacity-float)))
|
||||
(t/is (= (:opacity rect-1') 0.3)))
|
||||
(t/testing "percentage value got translated to float and applied to opacity"
|
||||
(t/is (= (:opacity (:applied-tokens rect-2')) (wtt/token-identifier token-opacity-percent)))
|
||||
(t/is (= (:opacity (:applied-tokens rect-2')) (:name token-opacity-percent)))
|
||||
(t/is (= (:opacity rect-2') 0.4)))
|
||||
(t/testing "invalid opacity value got applied but did not change shape"
|
||||
(t/is (= (:opacity (:applied-tokens rect-3')) (wtt/token-identifier token-opacity-invalid)))
|
||||
(t/is (= (:opacity (:applied-tokens rect-3')) (:name token-opacity-invalid)))
|
||||
(t/is (nil? (:opacity rect-3')))))))))))
|
||||
|
||||
(t/deftest test-apply-rotation
|
||||
(t/testing "applies rotation token and updates the shapes rotation"
|
||||
(t/async
|
||||
done
|
||||
(let [file (-> (setup-file-with-tokens)
|
||||
(toht/add-token :token-target {:value "120"
|
||||
:name "rotation.medium"
|
||||
:type :rotation}))
|
||||
(let [rotation-token {:name "rotation.medium"
|
||||
:value "120"
|
||||
:type :rotation}
|
||||
file (-> (setup-file-with-tokens)
|
||||
(update-in [:data :tokens-lib]
|
||||
#(ctob/add-token-in-set % "Set A" (ctob/make-token rotation-token))))
|
||||
store (ths/setup-store file)
|
||||
rect-1 (cths/get-shape file :rect-1)
|
||||
events [(wtch/apply-token {:shape-ids [(:id rect-1)]
|
||||
:attributes #{:rotation}
|
||||
:token (toht/get-token file :token-target)
|
||||
:token (toht/get-token file "rotation.medium")
|
||||
:on-update-shape wtch/update-rotation})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-target' (toht/get-token file' :token-target)
|
||||
token-target' (toht/get-token file' "rotation.medium")
|
||||
rect-1' (cths/get-shape file' :rect-1)]
|
||||
(t/is (some? (:applied-tokens rect-1')))
|
||||
(t/is (= (:rotation (:applied-tokens rect-1')) (wtt/token-identifier token-target')))
|
||||
(t/is (= (:rotation (:applied-tokens rect-1')) (:name token-target')))
|
||||
(t/is (= (:rotation rect-1') 120)))))))))
|
||||
|
||||
(t/deftest test-apply-stroke-width
|
||||
(t/testing "applies stroke-width token and updates the shapes with stroke"
|
||||
(t/async
|
||||
done
|
||||
(let [file (-> (setup-file-with-tokens {:rect-1 {:strokes [{:stroke-alignment :inner,
|
||||
(let [stroke-width-token {:name "stroke-width.sm"
|
||||
:value "10"
|
||||
:type :stroke-width}
|
||||
file (-> (setup-file-with-tokens {:rect-1 {:strokes [{:stroke-alignment :inner,
|
||||
:stroke-style :solid,
|
||||
:stroke-color "#000000",
|
||||
:stroke-opacity 1,
|
||||
:stroke-width 5}]}})
|
||||
(toht/add-token :token-target {:value "10"
|
||||
:name "stroke-width.sm"
|
||||
:type :stroke-width}))
|
||||
(update-in [:data :tokens-lib]
|
||||
#(ctob/add-token-in-set % "Set A" (ctob/make-token stroke-width-token))))
|
||||
store (ths/setup-store file)
|
||||
rect-with-stroke (cths/get-shape file :rect-1)
|
||||
rect-without-stroke (cths/get-shape file :rect-2)
|
||||
events [(wtch/apply-token {:shape-ids [(:id rect-with-stroke) (:id rect-without-stroke)]
|
||||
:attributes #{:stroke-width}
|
||||
:token (toht/get-token file :token-target)
|
||||
:token (toht/get-token file "stroke-width.sm")
|
||||
:on-update-shape wtch/update-stroke-width})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-target' (toht/get-token file' :token-target)
|
||||
token-target' (toht/get-token file' "stroke-width.sm")
|
||||
rect-with-stroke' (cths/get-shape file' :rect-1)
|
||||
rect-without-stroke' (cths/get-shape file' :rect-2)]
|
||||
(t/testing "token got applied to rect with stroke and shape stroke got updated"
|
||||
(t/is (= (:stroke-width (:applied-tokens rect-with-stroke')) (wtt/token-identifier token-target')))
|
||||
(t/is (= (:stroke-width (:applied-tokens rect-with-stroke')) (:name token-target')))
|
||||
(t/is (= (get-in rect-with-stroke' [:strokes 0 :stroke-width]) 10)))
|
||||
(t/testing "token got applied to rect without stroke but shape didnt get updated"
|
||||
(t/is (= (:stroke-width (:applied-tokens rect-without-stroke')) (wtt/token-identifier token-target')))
|
||||
(t/is (= (:stroke-width (:applied-tokens rect-without-stroke')) (:name token-target')))
|
||||
(t/is (empty? (:strokes rect-without-stroke')))))))))))
|
||||
|
||||
(t/deftest test-toggle-token-none
|
||||
|
@ -342,20 +348,20 @@
|
|||
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)})]]
|
||||
:token (toht/get-token file "borderRadius.md")})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
token-2' (toht/get-token file' :token-2)
|
||||
rect-1' (cths/get-shape file' :rect-1)
|
||||
rect-2' (cths/get-shape file' :rect-2)]
|
||||
token-2' (toht/get-token file' "borderRadius.md")
|
||||
rect-1' (cths/get-shape file' :rect-1)
|
||||
rect-2' (cths/get-shape file' :rect-2)]
|
||||
(t/is (some? (:applied-tokens rect-1')))
|
||||
(t/is (some? (:applied-tokens rect-2')))
|
||||
(t/is (= (:rx (:applied-tokens rect-1')) (wtt/token-identifier token-2')))
|
||||
(t/is (= (:rx (:applied-tokens rect-2')) (wtt/token-identifier token-2')))
|
||||
(t/is (= (:ry (:applied-tokens rect-1')) (wtt/token-identifier token-2')))
|
||||
(t/is (= (:ry (:applied-tokens rect-2')) (wtt/token-identifier token-2')))
|
||||
(t/is (= (:rx (:applied-tokens rect-1')) (:name token-2')))
|
||||
(t/is (= (:rx (:applied-tokens rect-2')) (:name token-2')))
|
||||
(t/is (= (:ry (:applied-tokens rect-1')) (:name token-2')))
|
||||
(t/is (= (:ry (:applied-tokens rect-2')) (:name token-2')))
|
||||
(t/is (= (:rx rect-1') 24))
|
||||
(t/is (= (:rx rect-2') 24)))))))))
|
||||
|
||||
|
@ -364,8 +370,8 @@
|
|||
(t/async
|
||||
done
|
||||
(let [file (-> (setup-file-with-tokens)
|
||||
(toht/apply-token-to-shape :rect-1 :token-1 #{:rx :ry})
|
||||
(toht/apply-token-to-shape :rect-3 :token-2 #{:rx :ry}))
|
||||
(toht/apply-token-to-shape :rect-1 "borderRadius.sm" #{:rx :ry})
|
||||
(toht/apply-token-to-shape :rect-3 "borderRadius.md" #{:rx :ry}))
|
||||
store (ths/setup-store file)
|
||||
|
||||
rect-with-token (cths/get-shape file :rect-1)
|
||||
|
@ -373,7 +379,7 @@
|
|||
rect-with-other-token (cths/get-shape file :rect-3)
|
||||
|
||||
events [(wtch/toggle-token {:shapes [rect-with-token rect-without-token rect-with-other-token]
|
||||
:token (toht/get-token file :token-1)
|
||||
:token (toht/get-token file "borderRadius.sm")
|
||||
:token-type-props {:attributes #{:rx :ry}}})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
|
@ -383,7 +389,7 @@
|
|||
rect-without-token' (cths/get-shape file' :rect-2)
|
||||
rect-with-other-token' (cths/get-shape file' :rect-3)]
|
||||
|
||||
(t/testing "rect-with-token got the token remove"
|
||||
(t/testing "rect-with-token got the token removed"
|
||||
(t/is (nil? (:rx (:applied-tokens rect-with-token'))))
|
||||
(t/is (nil? (:ry (:applied-tokens rect-with-token')))))
|
||||
|
||||
|
@ -398,8 +404,8 @@
|
|||
(t/async
|
||||
done
|
||||
(let [file (-> (setup-file-with-tokens)
|
||||
(toht/apply-token-to-shape :rect-1 :token-2 #{:rx :ry})
|
||||
(toht/apply-token-to-shape :rect-3 :token-2 #{:rx :ry}))
|
||||
(toht/apply-token-to-shape :rect-1 "borderRadius.md" #{:rx :ry})
|
||||
(toht/apply-token-to-shape :rect-3 "borderRadius.md" #{:rx :ry}))
|
||||
store (ths/setup-store file)
|
||||
|
||||
rect-with-other-token-1 (cths/get-shape file :rect-1)
|
||||
|
@ -407,22 +413,22 @@
|
|||
rect-with-other-token-2 (cths/get-shape file :rect-3)
|
||||
|
||||
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 (toht/get-token file "borderRadius.sm")
|
||||
:token-type-props {:attributes #{:rx :ry}}})]]
|
||||
(tohs/run-store-async
|
||||
store done events
|
||||
(fn [new-state]
|
||||
(let [file' (ths/get-file-from-store new-state)
|
||||
target-token (toht/get-token file' :token-1)
|
||||
target-token (toht/get-token file' "borderRadius.sm")
|
||||
rect-with-other-token-1' (cths/get-shape file' :rect-1)
|
||||
rect-without-token' (cths/get-shape file' :rect-2)
|
||||
rect-with-other-token-2' (cths/get-shape file' :rect-3)]
|
||||
|
||||
(t/testing "token got applied to all shapes"
|
||||
(t/is (= (:rx (:applied-tokens rect-with-other-token-1')) (wtt/token-identifier target-token)))
|
||||
(t/is (= (:rx (:applied-tokens rect-without-token')) (wtt/token-identifier target-token)))
|
||||
(t/is (= (:rx (:applied-tokens rect-with-other-token-2')) (wtt/token-identifier target-token)))
|
||||
(t/is (= (:rx (:applied-tokens rect-with-other-token-1')) (:name target-token)))
|
||||
(t/is (= (:rx (:applied-tokens rect-without-token')) (:name target-token)))
|
||||
(t/is (= (:rx (:applied-tokens rect-with-other-token-2')) (:name target-token)))
|
||||
|
||||
(t/is (= (:ry (:applied-tokens rect-with-other-token-1')) (wtt/token-identifier target-token)))
|
||||
(t/is (= (:ry (:applied-tokens rect-without-token')) (wtt/token-identifier target-token)))
|
||||
(t/is (= (:ry (:applied-tokens rect-with-other-token-2')) (wtt/token-identifier target-token)))))))))))
|
||||
(t/is (= (:ry (:applied-tokens rect-with-other-token-1')) (:name target-token)))
|
||||
(t/is (= (:ry (:applied-tokens rect-without-token')) (:name target-token)))
|
||||
(t/is (= (:ry (:applied-tokens rect-with-other-token-2')) (:name target-token)))))))))))
|
||||
|
|
|
@ -3,39 +3,42 @@
|
|||
[app.main.ui.workspace.tokens.style-dictionary :as sd]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[promesa.core :as p]
|
||||
[app.main.ui.workspace.tokens.token :as wtt]))
|
||||
[app.main.ui.workspace.tokens.token :as wtt]
|
||||
[app.common.data :as d]))
|
||||
|
||||
(def border-radius-token
|
||||
{:id #uuid "8c868278-7c8d-431b-bbc9-7d8f15c8edb9"
|
||||
:value "12px"
|
||||
{:value "12px"
|
||||
:name "borderRadius.sm"
|
||||
:type :border-radius})
|
||||
|
||||
(def reference-border-radius-token
|
||||
{:id #uuid "b9448d78-fd5b-4e3d-aa32-445904063f5b"
|
||||
:value "{borderRadius.sm} * 2"
|
||||
{:value "{borderRadius.sm} * 2"
|
||||
:name "borderRadius.md-with-dashes"
|
||||
:type :border-radius})
|
||||
|
||||
(def tokens {(:id border-radius-token) border-radius-token
|
||||
(:id reference-border-radius-token) reference-border-radius-token})
|
||||
|
||||
(def tokens (d/ordered-map
|
||||
(:name border-radius-token) border-radius-token
|
||||
(:name reference-border-radius-token) reference-border-radius-token))
|
||||
(t/deftest resolve-tokens-test
|
||||
(t/async
|
||||
done
|
||||
(t/testing "resolves tokens using style-dictionary from a ids map"
|
||||
(-> (sd/resolve-tokens+ tokens)
|
||||
(p/finally (fn [resolved-tokens]
|
||||
(let [expected-tokens {"borderRadius.sm"
|
||||
(assoc border-radius-token
|
||||
:resolved-value 12
|
||||
:resolved-unit "px")
|
||||
"borderRadius.md-with-dashes"
|
||||
(assoc reference-border-radius-token
|
||||
:resolved-value 24
|
||||
:resolved-unit "px")}]
|
||||
(t/is (= expected-tokens resolved-tokens))
|
||||
(done))))))))
|
||||
(p/finally
|
||||
(fn [resolved-tokens]
|
||||
(let [expected-tokens {"borderRadius.sm"
|
||||
(assoc border-radius-token
|
||||
:resolved-value 12
|
||||
:resolved-unit "px")
|
||||
"borderRadius.md-with-dashes"
|
||||
(assoc reference-border-radius-token
|
||||
:resolved-value 24
|
||||
:resolved-unit "px")}]
|
||||
(t/is (= 12 (get-in resolved-tokens ["borderRadius.sm" :resolved-value])))
|
||||
(t/is (= "px" (get-in resolved-tokens ["borderRadius.sm" :unit])))
|
||||
(t/is (= 24 (get-in resolved-tokens ["borderRadius.md-with-dashes" :resolved-value])))
|
||||
(t/is (= "px" (get-in resolved-tokens ["borderRadius.md-with-dashes" :unit])))
|
||||
(done))))))))
|
||||
|
||||
(t/deftest resolve-tokens-names-map-test
|
||||
(t/async
|
||||
|
@ -48,10 +51,10 @@
|
|||
(let [expected-tokens {"borderRadius.sm"
|
||||
(assoc border-radius-token
|
||||
:resolved-value 12
|
||||
:resolved-unit "px")
|
||||
:unit "px")
|
||||
"borderRadius.md-with-dashes"
|
||||
(assoc reference-border-radius-token
|
||||
:resolved-value 24
|
||||
:resolved-unit "px")}]
|
||||
:unit "px")}]
|
||||
(t/is (= expected-tokens resolved-tokens))
|
||||
(done))))))))
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
(ns token-tests.token-set-test
|
||||
(:require
|
||||
[app.main.ui.workspace.tokens.token-set :as wtts]
|
||||
[cljs.test :as t]))
|
||||
|
||||
(t/deftest toggle-active-theme-id-test
|
||||
(t/testing "toggles active theme id"
|
||||
(let [state {:workspace-data {:token-themes-index {1 {:id 1}}}}]
|
||||
(t/testing "activates theme with id")
|
||||
(t/is (= (wtts/toggle-active-theme-id 1 state) #{1})))
|
||||
|
||||
(let [state {:workspace-data {:token-active-themes #{1}
|
||||
:token-themes-index {1 {:id 1}}}}]
|
||||
(t/testing "missing temp theme returns empty set"
|
||||
(t/is (= #{} (wtts/toggle-active-theme-id 1 state)))))
|
||||
|
||||
(let [state {:workspace-data {:token-theme-temporary-id :temp
|
||||
:token-active-themes #{1}
|
||||
:token-themes-index {1 {:id 1}}}}]
|
||||
(t/testing "empty set returns temp theme"
|
||||
(t/is (= #{:temp} (wtts/toggle-active-theme-id 1 state)))))
|
||||
|
||||
(let [state {:workspace-data {:token-active-themes #{2 3 4}
|
||||
:token-themes-index {1 {:id 1}
|
||||
2 {:id 2}
|
||||
3 {:id 3}
|
||||
4 {:id 4 :group :different}}}}]
|
||||
(t/testing "removes same group themes and keeps different group themes"
|
||||
(t/is (= #{1 4} (wtts/toggle-active-theme-id 1 state)))))
|
||||
|
||||
(let [state {:workspace-data {:token-active-themes #{1 2 3 4}}
|
||||
:token-themes-index {1 {:id 1}
|
||||
2 {:id 2}
|
||||
3 {:id 3}
|
||||
4 {:id 4 :group :different}}}]
|
||||
(t/testing "removes theme when active"
|
||||
(t/is (= #{4 3 2} (wtts/toggle-active-theme-id 1 state)))))))
|
|
@ -50,10 +50,6 @@
|
|||
(t/testing "doesn't match passed `:token-attributes`"
|
||||
(t/is (nil? (wtt/token-applied? {:name "a"} {:applied-tokens {:x "a"}} #{:y})))))
|
||||
|
||||
(t/deftest token-applied-attributes
|
||||
(t/is (= #{:x} (wtt/token-applied-attributes {:name "a"}
|
||||
{:applied-tokens {:x "a" :y "b"}}
|
||||
#{:x :missing}))))
|
||||
(t/deftest shapes-ids-by-applied-attributes
|
||||
(t/testing "Returns set of matched attributes that fit the applied token"
|
||||
(let [attributes #{:x :y :z}
|
||||
|
|
Loading…
Add table
Reference in a new issue