mirror of
https://github.com/penpot/penpot.git
synced 2025-07-21 12:57:15 +02:00
✨ Render sets and set groups tree
This commit is contained in:
parent
1d2c7dd20e
commit
a19d85fb10
10 changed files with 373 additions and 237 deletions
|
@ -410,6 +410,11 @@
|
||||||
[:type [:= :add-token-set]]
|
[:type [:= :add-token-set]]
|
||||||
[:token-set ::ctot/token-set]]]
|
[:token-set ::ctot/token-set]]]
|
||||||
|
|
||||||
|
[:add-token-sets
|
||||||
|
[:map {:title "AddTokenSetsChange"}
|
||||||
|
[:type [:= :add-token-sets]]
|
||||||
|
[:token-sets [:sequential ::ctot/token-set]]]]
|
||||||
|
|
||||||
[:mod-token-set
|
[:mod-token-set
|
||||||
[:map {:title "ModTokenSetChange"}
|
[:map {:title "ModTokenSetChange"}
|
||||||
[:type [:= :mod-token-set]]
|
[:type [:= :mod-token-set]]
|
||||||
|
@ -427,6 +432,11 @@
|
||||||
[:type [:= :del-token-set]]
|
[:type [:= :del-token-set]]
|
||||||
[:name :string]]]
|
[:name :string]]]
|
||||||
|
|
||||||
|
[:del-token-set-path
|
||||||
|
[:map {:title "DelTokenSetPathChange"}
|
||||||
|
[:type [:= :del-token-set-path]]
|
||||||
|
[:path :string]]]
|
||||||
|
|
||||||
[:set-tokens-lib
|
[:set-tokens-lib
|
||||||
[:map {:title "SetTokensLib"}
|
[:map {:title "SetTokensLib"}
|
||||||
[:type [:= :set-tokens-lib]]
|
[:type [:= :set-tokens-lib]]
|
||||||
|
@ -1046,6 +1056,12 @@
|
||||||
(ctob/ensure-tokens-lib)
|
(ctob/ensure-tokens-lib)
|
||||||
(ctob/add-set (ctob/make-token-set token-set)))))
|
(ctob/add-set (ctob/make-token-set token-set)))))
|
||||||
|
|
||||||
|
(defmethod process-change :add-token-sets
|
||||||
|
[data {:keys [token-sets]}]
|
||||||
|
(update data :tokens-lib #(-> %
|
||||||
|
(ctob/ensure-tokens-lib)
|
||||||
|
(ctob/add-sets (map ctob/make-token-set token-sets)))))
|
||||||
|
|
||||||
(defmethod process-change :mod-token-set
|
(defmethod process-change :mod-token-set
|
||||||
[data {:keys [name token-set]}]
|
[data {:keys [name token-set]}]
|
||||||
(update data :tokens-lib (fn [lib]
|
(update data :tokens-lib (fn [lib]
|
||||||
|
@ -1066,6 +1082,12 @@
|
||||||
(ctob/ensure-tokens-lib)
|
(ctob/ensure-tokens-lib)
|
||||||
(ctob/delete-set name))))
|
(ctob/delete-set name))))
|
||||||
|
|
||||||
|
(defmethod process-change :del-token-set-path
|
||||||
|
[data {:keys [path]}]
|
||||||
|
(update data :tokens-lib #(-> %
|
||||||
|
(ctob/ensure-tokens-lib)
|
||||||
|
(ctob/delete-set-path path))))
|
||||||
|
|
||||||
;; === Operations
|
;; === Operations
|
||||||
|
|
||||||
(def ^:private decode-shape
|
(def ^:private decode-shape
|
||||||
|
|
|
@ -818,15 +818,15 @@
|
||||||
(update :undo-changes conj {:type :mod-token-set :name (:name token-set) :token-set (or prev-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)))
|
(apply-changes-local)))
|
||||||
|
|
||||||
(defn delete-token-set
|
(defn delete-token-set-path
|
||||||
[changes token-set-name]
|
[changes token-set-path]
|
||||||
(assert-library! changes)
|
(assert-library! changes)
|
||||||
(let [library-data (::library-data (meta changes))
|
(let [library-data (::library-data (meta changes))
|
||||||
prev-token-theme (some-> (get library-data :tokens-lib)
|
prev-token-sets (some-> (get library-data :tokens-lib)
|
||||||
(ctob/get-set token-set-name))]
|
(ctob/get-path-sets token-set-path))]
|
||||||
(-> changes
|
(-> changes
|
||||||
(update :redo-changes conj {:type :del-token-set :name token-set-name})
|
(update :redo-changes conj {:type :del-token-set-path :path token-set-path})
|
||||||
(update :undo-changes conj {:type :add-token-set :token-set prev-token-theme})
|
(update :undo-changes conj {:type :add-token-sets :token-sets prev-token-sets})
|
||||||
(apply-changes-local))))
|
(apply-changes-local))))
|
||||||
|
|
||||||
(defn move-token-set-before
|
(defn move-token-set-before
|
||||||
|
|
|
@ -183,6 +183,14 @@
|
||||||
|
|
||||||
(def set-separator "/")
|
(def set-separator "/")
|
||||||
|
|
||||||
|
(defn join-set-path [set-path]
|
||||||
|
(join-path set-path set-separator))
|
||||||
|
|
||||||
|
(defn split-set-prefix [set-path]
|
||||||
|
(some->> set-path
|
||||||
|
(re-matches #"^([SG]-)(.*)")
|
||||||
|
(rest)))
|
||||||
|
|
||||||
(defn add-set-prefix [set-name]
|
(defn add-set-prefix [set-name]
|
||||||
(str set-prefix set-name))
|
(str set-prefix set-name))
|
||||||
|
|
||||||
|
@ -199,14 +207,29 @@
|
||||||
set-name (add-set-prefix (last paths))]
|
set-name (add-set-prefix (last paths))]
|
||||||
(conj set-path set-name)))
|
(conj set-path set-name)))
|
||||||
|
|
||||||
|
(defn split-token-set-path [token-set-path]
|
||||||
|
(split-path token-set-path set-separator))
|
||||||
|
|
||||||
(defn split-token-set-name [token-set-name]
|
(defn split-token-set-name [token-set-name]
|
||||||
(-> (split-path token-set-name set-separator)
|
(-> (split-token-set-path token-set-name)
|
||||||
(add-token-set-paths-prefix)))
|
(add-token-set-paths-prefix)))
|
||||||
|
|
||||||
(defn get-token-set-path [token-set]
|
(defn get-token-set-path [token-set]
|
||||||
(let [path (get-path token-set set-separator)]
|
(let [path (get-path token-set set-separator)]
|
||||||
(add-token-set-paths-prefix path)))
|
(add-token-set-paths-prefix path)))
|
||||||
|
|
||||||
|
(defn set-name->set-path-string [set-name]
|
||||||
|
(-> (split-token-set-name set-name)
|
||||||
|
(join-set-path)))
|
||||||
|
|
||||||
|
(defn set-path->set-name [set-path]
|
||||||
|
(->> (split-token-set-path set-path)
|
||||||
|
(map (fn [path-part]
|
||||||
|
(or (-> (split-set-prefix path-part)
|
||||||
|
(second))
|
||||||
|
path-part)))
|
||||||
|
(join-set-path)))
|
||||||
|
|
||||||
(defn tokens-tree
|
(defn tokens-tree
|
||||||
"Convert tokens into a nested tree with their `:name` as the path.
|
"Convert tokens into a nested tree with their `:name` as the path.
|
||||||
Optionally use `update-token-fn` option to transform the token."
|
Optionally use `update-token-fn` option to transform the token."
|
||||||
|
@ -234,16 +257,27 @@
|
||||||
{:tokens-tree {} :ids {}} tokens))
|
{:tokens-tree {} :ids {}} tokens))
|
||||||
|
|
||||||
(defprotocol ITokenSet
|
(defprotocol ITokenSet
|
||||||
|
(update-name [_ set-name] "change a token set name while keeping the path")
|
||||||
(add-token [_ token] "add a token at the end of the list")
|
(add-token [_ token] "add a token at the end of the list")
|
||||||
(update-token [_ token-name f] "update a token in the list")
|
(update-token [_ token-name f] "update a token in the list")
|
||||||
(delete-token [_ token-name] "delete a token from the list")
|
(delete-token [_ token-name] "delete a token from the list")
|
||||||
(get-token [_ token-name] "return token by token-name")
|
(get-token [_ token-name] "return token by token-name")
|
||||||
(get-tokens [_] "return an ordered sequence of all tokens in the set")
|
(get-tokens [_] "return an ordered sequence of all tokens in the set")
|
||||||
|
(get-set-path [_] "returns name of set converted to the path with prefix identifiers")
|
||||||
(get-tokens-tree [_] "returns a tree of tokens split & nested by their name path")
|
(get-tokens-tree [_] "returns a tree of tokens split & nested by their name path")
|
||||||
(get-dtcg-tokens-tree [_] "returns tokens tree formated to the dtcg spec"))
|
(get-dtcg-tokens-tree [_] "returns tokens tree formated to the dtcg spec"))
|
||||||
|
|
||||||
(defrecord TokenSet [name description modified-at tokens]
|
(defrecord TokenSet [name description modified-at tokens]
|
||||||
ITokenSet
|
ITokenSet
|
||||||
|
(update-name [_ set-name]
|
||||||
|
(TokenSet. (-> (split-token-set-path name)
|
||||||
|
(drop-last)
|
||||||
|
(concat [set-name])
|
||||||
|
(join-set-path))
|
||||||
|
description
|
||||||
|
(dt/now)
|
||||||
|
tokens))
|
||||||
|
|
||||||
(add-token [_ token]
|
(add-token [_ token]
|
||||||
(dm/assert! "expected valid token" (check-token! token))
|
(dm/assert! "expected valid token" (check-token! token))
|
||||||
(TokenSet. name
|
(TokenSet. name
|
||||||
|
@ -278,6 +312,9 @@
|
||||||
(get-tokens [_]
|
(get-tokens [_]
|
||||||
(vals tokens))
|
(vals tokens))
|
||||||
|
|
||||||
|
(get-set-path [_]
|
||||||
|
(set-name->set-path-string name))
|
||||||
|
|
||||||
(get-tokens-tree [_]
|
(get-tokens-tree [_]
|
||||||
(tokens-tree tokens))
|
(tokens-tree tokens))
|
||||||
|
|
||||||
|
@ -325,11 +362,14 @@
|
||||||
(add-sets [_ token-set] "add a collection of sets to the library, at the end")
|
(add-sets [_ token-set] "add a collection of sets to the library, at the end")
|
||||||
(update-set [_ set-name f] "modify a set in the ilbrary")
|
(update-set [_ set-name f] "modify a set in the ilbrary")
|
||||||
(delete-set [_ set-name] "delete a set in the library")
|
(delete-set [_ set-name] "delete a set in the library")
|
||||||
|
(delete-set-path [_ set-path] "delete a set in the library")
|
||||||
(move-set-before [_ set-name before-set-name] "move a set with `set-name` before a set with `before-set-name` in the library.
|
(move-set-before [_ set-name before-set-name] "move a set with `set-name` before a set with `before-set-name` in the library.
|
||||||
When `before-set-name` is nil, move set to bottom")
|
When `before-set-name` is nil, move set to bottom")
|
||||||
(set-count [_] "get the total number if sets in the library")
|
(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-set-tree [_] "get a nested tree of all sets in the library")
|
||||||
|
(get-in-set-tree [_ path] "get `path` in nested tree of all sets in the library")
|
||||||
(get-sets [_] "get an ordered sequence of all sets in the library")
|
(get-sets [_] "get an ordered sequence of all sets in the library")
|
||||||
|
(get-path-sets [_ path] "get an ordered sequence of sets at `path` in the library")
|
||||||
(get-ordered-set-names [_] "get an ordered sequence of all sets names 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 [_ set-name] "get one set looking for name")
|
||||||
(get-neighbor-set-name [_ set-name index-offset] "get neighboring set name offset by `index-offset`"))
|
(get-neighbor-set-name [_ set-name index-offset] "get neighboring set name offset by `index-offset`"))
|
||||||
|
@ -381,6 +421,8 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
(set-sets [_ set-names] "set the active token sets")
|
(set-sets [_ set-names] "set the active token sets")
|
||||||
(disable-set [_ set-name] "disable set in theme")
|
(disable-set [_ set-name] "disable set in theme")
|
||||||
(toggle-set [_ set-name] "toggle a set enabled / disabled in the theme")
|
(toggle-set [_ set-name] "toggle a set enabled / disabled in the theme")
|
||||||
|
|
||||||
|
(update-set-name [_ prev-set-name set-name] "update set-name from `prev-set-name` to `set-name` when it exists")
|
||||||
(theme-path [_] "get `token-theme-path` from theme")
|
(theme-path [_] "get `token-theme-path` from theme")
|
||||||
(theme-matches-group-name [_ group name] "if a theme matches the given group & name")
|
(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"))
|
(hidden-temporary-theme? [_] "if a theme is the (from the user ui) hidden temporary theme"))
|
||||||
|
@ -403,6 +445,16 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
(disj sets set-name)
|
(disj sets set-name)
|
||||||
(conj sets set-name))))
|
(conj sets set-name))))
|
||||||
|
|
||||||
|
(update-set-name [this prev-set-name set-name]
|
||||||
|
(if (get sets prev-set-name)
|
||||||
|
(TokenTheme. name
|
||||||
|
group
|
||||||
|
description
|
||||||
|
is-source
|
||||||
|
(dt/now)
|
||||||
|
(conj (disj sets prev-set-name) set-name))
|
||||||
|
this))
|
||||||
|
|
||||||
(theme-path [_]
|
(theme-path [_]
|
||||||
(token-theme-path group name))
|
(token-theme-path group name))
|
||||||
|
|
||||||
|
@ -569,36 +621,49 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
|
|
||||||
(add-sets [this token-sets]
|
(add-sets [this token-sets]
|
||||||
(reduce
|
(reduce
|
||||||
(fn [lib set]
|
(fn [lib set]
|
||||||
(add-set lib set))
|
(add-set lib set))
|
||||||
this token-sets))
|
this token-sets))
|
||||||
|
|
||||||
(update-set [this set-name f]
|
(update-set [this set-name f]
|
||||||
(let [path (split-token-set-name set-name)
|
(let [path (split-token-set-name set-name)
|
||||||
set (get-in sets path)]
|
set (get-in sets path)]
|
||||||
(if set
|
(if set
|
||||||
(let [set' (-> (make-token-set (f set))
|
(let [set' (-> (make-token-set (f set))
|
||||||
(assoc :modified-at (dt/now)))
|
(assoc :modified-at (dt/now)))
|
||||||
path' (get-token-set-path set')]
|
path' (get-token-set-path set')
|
||||||
|
name-changed? (not= (:name set) (:name set'))]
|
||||||
(check-token-set! set')
|
(check-token-set! set')
|
||||||
(TokensLib. (if (= (:name set) (:name set'))
|
(if name-changed?
|
||||||
(d/oassoc-in sets path set')
|
(TokensLib. (-> sets
|
||||||
(-> sets
|
|
||||||
(d/oassoc-in-before path path' set')
|
(d/oassoc-in-before path path' set')
|
||||||
(d/dissoc-in path)))
|
(d/dissoc-in path))
|
||||||
themes
|
(walk/postwalk
|
||||||
active-themes))
|
(fn [form]
|
||||||
|
(if (instance? TokenTheme form)
|
||||||
|
(update-set-name form (:name set) (:name set'))
|
||||||
|
form))
|
||||||
|
themes)
|
||||||
|
active-themes)
|
||||||
|
(TokensLib. (d/oassoc-in sets path set')
|
||||||
|
themes
|
||||||
|
active-themes)))
|
||||||
this)))
|
this)))
|
||||||
|
|
||||||
(delete-set [_ set-name]
|
(delete-set-path [_ set-path]
|
||||||
(let [path (split-token-set-name set-name)]
|
(let [path (split-token-set-path set-path)
|
||||||
|
set-node (get-in sets path)
|
||||||
|
set-group? (not (instance? TokenSet set-node))]
|
||||||
(TokensLib. (d/dissoc-in sets path)
|
(TokensLib. (d/dissoc-in sets path)
|
||||||
(walk/postwalk
|
;; TODO: When deleting a set-group, also deactivate the child sets
|
||||||
(fn [form]
|
(if set-group?
|
||||||
(if (instance? TokenTheme form)
|
themes
|
||||||
(disable-set form set-name)
|
(walk/postwalk
|
||||||
form))
|
(fn [form]
|
||||||
themes)
|
(if (instance? TokenTheme form)
|
||||||
|
(disable-set form set-path)
|
||||||
|
form))
|
||||||
|
themes))
|
||||||
active-themes)))
|
active-themes)))
|
||||||
|
|
||||||
;; TODO Handle groups and nesting
|
;; TODO Handle groups and nesting
|
||||||
|
@ -620,10 +685,18 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
(get-set-tree [_]
|
(get-set-tree [_]
|
||||||
sets)
|
sets)
|
||||||
|
|
||||||
|
(get-in-set-tree [_ path]
|
||||||
|
(get-in sets path))
|
||||||
|
|
||||||
(get-sets [_]
|
(get-sets [_]
|
||||||
(->> (tree-seq d/ordered-map? vals sets)
|
(->> (tree-seq d/ordered-map? vals sets)
|
||||||
(filter (partial instance? TokenSet))))
|
(filter (partial instance? TokenSet))))
|
||||||
|
|
||||||
|
(get-path-sets [_ path]
|
||||||
|
(some->> (get-in sets (split-token-set-path path))
|
||||||
|
(tree-seq d/ordered-map? vals)
|
||||||
|
(filter (partial instance? TokenSet))))
|
||||||
|
|
||||||
(get-ordered-set-names [this]
|
(get-ordered-set-names [this]
|
||||||
(map :name (get-sets this)))
|
(map :name (get-sets this)))
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,14 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(wtts/assoc-selected-token-set-id state id))))
|
(wtts/assoc-selected-token-set-id state id))))
|
||||||
|
|
||||||
|
(defn set-selected-token-set-id-from-name
|
||||||
|
[token-set-name]
|
||||||
|
(ptk/reify ::set-selected-token-set-id-from-name
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(->> (ctob/set-name->set-path-string token-set-name)
|
||||||
|
(wtts/assoc-selected-token-set-id state)))))
|
||||||
|
|
||||||
(defn create-token-theme [token-theme]
|
(defn create-token-theme [token-theme]
|
||||||
(let [new-token-theme token-theme]
|
(let [new-token-theme token-theme]
|
||||||
(ptk/reify ::create-token-theme
|
(ptk/reify ::create-token-theme
|
||||||
|
@ -157,7 +165,7 @@
|
||||||
(let [changes (-> (pcb/empty-changes it)
|
(let [changes (-> (pcb/empty-changes it)
|
||||||
(pcb/add-token-set new-token-set))]
|
(pcb/add-token-set new-token-set))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(set-selected-token-set-id (:name new-token-set))
|
(set-selected-token-set-id-from-name (:name new-token-set))
|
||||||
(dch/commit-changes changes)))))))
|
(dch/commit-changes changes)))))))
|
||||||
|
|
||||||
(defn update-token-set [set-name token-set]
|
(defn update-token-set [set-name token-set]
|
||||||
|
@ -169,7 +177,7 @@
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/update-token-set token-set prev-token-set))]
|
(pcb/update-token-set token-set prev-token-set))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(set-selected-token-set-id (:name token-set))
|
(set-selected-token-set-id-from-name (:name token-set))
|
||||||
(dch/commit-changes changes))))))
|
(dch/commit-changes changes))))))
|
||||||
|
|
||||||
(defn toggle-token-set [{:keys [token-set-name]}]
|
(defn toggle-token-set [{:keys [token-set-name]}]
|
||||||
|
@ -202,7 +210,7 @@
|
||||||
(ctob/get-sets)
|
(ctob/get-sets)
|
||||||
(first)
|
(first)
|
||||||
(:name)
|
(:name)
|
||||||
(set-selected-token-set-id))
|
(set-selected-token-set-id-from-name))
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/with-library-data data)
|
(pcb/with-library-data data)
|
||||||
(pcb/set-tokens-lib lib))]
|
(pcb/set-tokens-lib lib))]
|
||||||
|
@ -211,14 +219,14 @@
|
||||||
update-token-set-change
|
update-token-set-change
|
||||||
(wtu/update-workspace-tokens))))))
|
(wtu/update-workspace-tokens))))))
|
||||||
|
|
||||||
(defn delete-token-set [token-set-name]
|
(defn delete-token-set-path [token-set-path]
|
||||||
(ptk/reify ::delete-token-set
|
(ptk/reify ::delete-token-set-path
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [data (get state :workspace-data)
|
(let [data (get state :workspace-data)
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/with-library-data data)
|
(pcb/with-library-data data)
|
||||||
(pcb/delete-token-set token-set-name))]
|
(pcb/delete-token-set-path token-set-path))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(dch/commit-changes changes)
|
(dch/commit-changes changes)
|
||||||
(wtu/update-workspace-tokens))))))
|
(wtu/update-workspace-tokens))))))
|
||||||
|
@ -268,7 +276,7 @@
|
||||||
(pcb/update-token (pcb/empty-changes) (:name token-set) token prev-token)
|
(pcb/update-token (pcb/empty-changes) (:name token-set) token prev-token)
|
||||||
(pcb/add-token (pcb/empty-changes) (:name token-set) token)))]
|
(pcb/add-token (pcb/empty-changes) (:name token-set) token)))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(set-selected-token-set-id token-set-name)
|
(set-selected-token-set-id-from-name token-set-name)
|
||||||
(dch/commit-changes changes))))))
|
(dch/commit-changes changes))))))
|
||||||
|
|
||||||
(defn delete-token
|
(defn delete-token
|
||||||
|
|
|
@ -493,9 +493,15 @@
|
||||||
(def workspace-selected-token-set-id
|
(def workspace-selected-token-set-id
|
||||||
(l/derived wtts/get-selected-token-set-id st/state))
|
(l/derived wtts/get-selected-token-set-id st/state))
|
||||||
|
|
||||||
|
(def workspace-token-set-group-selected?
|
||||||
|
(l/derived wtts/token-group-selected? st/state))
|
||||||
|
|
||||||
(def workspace-ordered-token-sets
|
(def workspace-ordered-token-sets
|
||||||
(l/derived #(or (some-> % ctob/get-sets) []) tokens-lib))
|
(l/derived #(or (some-> % ctob/get-sets) []) tokens-lib))
|
||||||
|
|
||||||
|
(def workspace-token-sets-tree
|
||||||
|
(l/derived (d/nilf ctob/get-set-tree) tokens-lib))
|
||||||
|
|
||||||
(def workspace-active-theme-paths
|
(def workspace-active-theme-paths
|
||||||
(l/derived (d/nilf ctob/get-active-theme-paths) tokens-lib))
|
(l/derived (d/nilf ctob/get-active-theme-paths) tokens-lib))
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,13 @@
|
||||||
(ns app.main.ui.workspace.tokens.sets
|
(ns app.main.ui.workspace.tokens.sets
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.notifications :as ntf]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
[app.main.data.tokens :as wdt]
|
[app.main.data.tokens :as wdt]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as ic]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as ic]
|
||||||
[app.main.ui.ds.foundations.typography.text :refer [text*]]
|
[app.main.ui.ds.foundations.typography.text :refer [text*]]
|
||||||
[app.main.ui.hooks :as h]
|
|
||||||
[app.main.ui.workspace.tokens.sets-context :as sets-context]
|
[app.main.ui.workspace.tokens.sets-context :as sets-context]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
|
@ -25,8 +24,8 @@
|
||||||
(defn on-toggle-token-set-click [token-set-name]
|
(defn on-toggle-token-set-click [token-set-name]
|
||||||
(st/emit! (wdt/toggle-token-set {:token-set-name token-set-name})))
|
(st/emit! (wdt/toggle-token-set {:token-set-name token-set-name})))
|
||||||
|
|
||||||
(defn on-select-token-set-click [name]
|
(defn on-select-token-set-click [tree-path]
|
||||||
(st/emit! (wdt/set-selected-token-set-id name)))
|
(st/emit! (wdt/set-selected-token-set-id tree-path)))
|
||||||
|
|
||||||
(defn on-update-token-set [set-name token-set]
|
(defn on-update-token-set [set-name token-set]
|
||||||
(st/emit! (wdt/update-token-set set-name token-set)))
|
(st/emit! (wdt/update-token-set set-name token-set)))
|
||||||
|
@ -34,7 +33,7 @@
|
||||||
(defn on-create-token-set [token-set]
|
(defn on-create-token-set [token-set]
|
||||||
(st/emit! (wdt/create-token-set token-set)))
|
(st/emit! (wdt/create-token-set token-set)))
|
||||||
|
|
||||||
(mf/defc editing-node
|
(mf/defc editing-label
|
||||||
[{:keys [default-value on-cancel on-submit]}]
|
[{:keys [default-value on-cancel on-submit]}]
|
||||||
(let [ref (mf/use-ref)
|
(let [ref (mf/use-ref)
|
||||||
on-submit-valid (mf/use-fn
|
on-submit-valid (mf/use-fn
|
||||||
|
@ -43,7 +42,9 @@
|
||||||
(if (or (str/empty? value)
|
(if (or (str/empty? value)
|
||||||
(= value default-value))
|
(= value default-value))
|
||||||
(on-cancel)
|
(on-cancel)
|
||||||
(on-submit value)))))
|
(do
|
||||||
|
(on-submit value)
|
||||||
|
(on-cancel))))))
|
||||||
on-key-down (mf/use-fn
|
on-key-down (mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(cond
|
(cond
|
||||||
|
@ -58,136 +59,166 @@
|
||||||
:auto-focus true
|
:auto-focus true
|
||||||
:default-value default-value}]))
|
:default-value default-value}]))
|
||||||
|
|
||||||
(mf/defc sets-tree
|
(mf/defc sets-tree-set-group
|
||||||
[{:keys [token-set
|
[{:keys [label tree-depth tree-path selected? collapsed? on-select editing? on-edit on-edit-submit]}]
|
||||||
token-set-active?
|
(let [editing?' (editing? tree-path)
|
||||||
token-set-selected?
|
{:keys [on-create on-reset] :as ctx} (sets-context/use-context)
|
||||||
editing?
|
|
||||||
on-select
|
|
||||||
on-toggle
|
|
||||||
on-edit
|
|
||||||
on-submit
|
|
||||||
on-cancel]
|
|
||||||
:as _props}]
|
|
||||||
(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? name)
|
|
||||||
|
|
||||||
on-click
|
on-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps editing-node?)
|
(mf/deps editing? tree-path)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(when-not editing-node?
|
(when-not (editing? tree-path)
|
||||||
(on-select name))))
|
(on-select tree-path))))
|
||||||
|
|
||||||
on-context-menu
|
on-context-menu
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps editing-node? name)
|
(mf/deps editing? tree-path)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(when-not editing-node?
|
(when-not (editing? tree-path)
|
||||||
(st/emit!
|
(st/emit!
|
||||||
(wdt/show-token-set-context-menu
|
(wdt/show-token-set-context-menu
|
||||||
{:position (dom/get-client-position event)
|
{:position (dom/get-client-position event)
|
||||||
:token-set-name name})))))
|
:tree-path tree-path})))))]
|
||||||
|
[:div {;; :ref dref
|
||||||
on-drag
|
:role "button"
|
||||||
(mf/use-fn
|
:style {"--tree-depth" tree-depth}
|
||||||
(mf/deps name)
|
|
||||||
(fn [_]
|
|
||||||
(when-not selected?
|
|
||||||
(on-select name))))
|
|
||||||
|
|
||||||
on-drop
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps name)
|
|
||||||
(fn [position data]
|
|
||||||
(st/emit! (wdt/move-token-set (:name data) name position))))
|
|
||||||
|
|
||||||
on-submit-edit
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps on-submit token-set)
|
|
||||||
#(on-submit (assoc token-set :name %)))
|
|
||||||
|
|
||||||
on-edit-name
|
|
||||||
(mf/use-fn
|
|
||||||
(fn [e]
|
|
||||||
(let [name (-> (dom/get-current-target e)
|
|
||||||
(dom/get-data "name"))]
|
|
||||||
(on-edit name))))
|
|
||||||
|
|
||||||
on-toggle-set (fn [event]
|
|
||||||
(dom/prevent-default event)
|
|
||||||
(dom/stop-propagation event)
|
|
||||||
(on-toggle name))
|
|
||||||
|
|
||||||
on-collapse (mf/use-fn #(swap! collapsed? not))
|
|
||||||
|
|
||||||
|
|
||||||
[dprops dref]
|
|
||||||
(h/use-sortable
|
|
||||||
:data-type "penpot/token-set"
|
|
||||||
:on-drag on-drag
|
|
||||||
:on-drop on-drop
|
|
||||||
:data {:name name}
|
|
||||||
:draggable? true)]
|
|
||||||
[:div {:ref dref
|
|
||||||
:class (stl/css-case :set-item-container true
|
:class (stl/css-case :set-item-container true
|
||||||
:dnd-over (= (:over dprops) :center)
|
:selected-set selected?)
|
||||||
:dnd-over-top (= (:over dprops) :top)
|
|
||||||
:dnd-over-bot (= (:over dprops) :bot))
|
|
||||||
:on-click on-click
|
:on-click on-click
|
||||||
:on-double-click on-edit-name
|
|
||||||
:on-context-menu on-context-menu
|
:on-context-menu on-context-menu
|
||||||
:data-name name}
|
:on-double-click #(on-edit tree-path)}
|
||||||
[:div {:class (stl/css-case :set-item-group group?
|
[:> icon-button*
|
||||||
:set-item-set set?
|
{:on-click (fn [event]
|
||||||
:selected-set selected?)}
|
(.stopPropagation event)
|
||||||
(when group?
|
(swap! collapsed? not))
|
||||||
[:> icon-button* {:on-click on-collapse
|
:aria-label (tr "labels.collapse")
|
||||||
:aria-label (tr "labels.collapse")
|
:icon (if @collapsed? "arrow-right" "arrow-down")
|
||||||
:icon (if @collapsed?
|
:variant "action"}]
|
||||||
"arrow-right"
|
[:> icon*
|
||||||
"arrow-down")
|
{:id "group"
|
||||||
:variant "action"}])
|
:class (stl/css :icon)}]
|
||||||
|
(if editing?'
|
||||||
|
[:& editing-label
|
||||||
|
{:default-value label
|
||||||
|
:on-cancel on-reset
|
||||||
|
:on-create on-reset
|
||||||
|
:on-submit #(on-edit-submit)}]
|
||||||
|
[:div {:class (stl/css :set-name)} label])]))
|
||||||
|
|
||||||
[:> icon* {:id (if set? "document" "group")
|
(mf/defc sets-tree-set
|
||||||
:class (stl/css :icon)}]
|
[{:keys [set label tree-depth tree-path selected? on-select active? on-toggle editing? on-edit on-edit-submit]}]
|
||||||
(if editing-node?
|
(let [set-name (.-name set)
|
||||||
[:& editing-node {:default-value name
|
{:keys [on-create on-reset] :as ctx} (sets-context/use-context)
|
||||||
:on-submit on-submit-edit
|
editing?' (editing? tree-path)
|
||||||
:on-cancel on-cancel}]
|
active?' (active? set-name)
|
||||||
[:*
|
on-click
|
||||||
[:div {:class (stl/css :set-name)} name]
|
(mf/use-fn
|
||||||
(if set?
|
(mf/deps editing?' tree-path)
|
||||||
[:button {:on-click on-toggle-set
|
(fn [event]
|
||||||
:class (stl/css-case :checkbox-style true
|
(dom/stop-propagation event)
|
||||||
:checkbox-checked-style visible?)}
|
(when-not editing?'
|
||||||
(when visible?
|
(on-select tree-path))))
|
||||||
[:> icon* {:aria-label (tr "workspace.token.select-set")
|
|
||||||
:class (stl/css :check-icon)
|
|
||||||
:size "s"
|
|
||||||
:id ic/tick}])]
|
|
||||||
nil
|
|
||||||
#_(when (and children (not @collapsed?))
|
|
||||||
[:div {:class (stl/css :set-children)}
|
|
||||||
(for [child-id children]
|
|
||||||
[:& sets-tree (assoc props :key child-id
|
|
||||||
{:key child-id}
|
|
||||||
:set-id child-id
|
|
||||||
:selected-set-id selected-token-set-id)])]))])]]))
|
|
||||||
|
|
||||||
(defn warn-on-try-create-token-set-group! []
|
on-context-menu
|
||||||
(st/emit! (ntf/show {:content (tr "workspace.token.grouping-set-alert")
|
(mf/use-fn
|
||||||
:notification-type :toast
|
(mf/deps editing?' tree-path)
|
||||||
:type :warning
|
(fn [event]
|
||||||
:timeout 3000})))
|
(dom/prevent-default event)
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(when-not editing?'
|
||||||
|
(st/emit!
|
||||||
|
(wdt/show-token-set-context-menu
|
||||||
|
{:position (dom/get-client-position event)
|
||||||
|
:tree-path tree-path})))))]
|
||||||
|
[:div {;; :ref dref
|
||||||
|
:role "button"
|
||||||
|
:style {"--tree-depth" tree-depth}
|
||||||
|
:class (stl/css-case :set-item-container true
|
||||||
|
:selected-set selected?)
|
||||||
|
:on-click on-click
|
||||||
|
:on-double-click #(on-edit tree-path)
|
||||||
|
:on-context-menu on-context-menu}
|
||||||
|
[:> icon*
|
||||||
|
{:id "document"
|
||||||
|
:class (stl/css-case :icon true
|
||||||
|
:root-icon (not tree-depth))}]
|
||||||
|
(if editing?'
|
||||||
|
[:& editing-label
|
||||||
|
{:default-value label
|
||||||
|
:on-cancel on-reset
|
||||||
|
:on-create on-reset
|
||||||
|
:on-submit #(on-edit-submit set-name (ctob/update-name set %))}]
|
||||||
|
[:*
|
||||||
|
[:div {:class (stl/css :set-name)} label]
|
||||||
|
[:button {:on-click (fn [event]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(on-toggle set-name))
|
||||||
|
:class (stl/css-case :checkbox-style true
|
||||||
|
:checkbox-checked-style active?')}
|
||||||
|
(when active?'
|
||||||
|
[:> icon* {:aria-label (tr "workspace.token.select-set")
|
||||||
|
:class (stl/css :check-icon)
|
||||||
|
:size "s"
|
||||||
|
:id ic/tick}])]])]))
|
||||||
|
|
||||||
|
(mf/defc sets-tree
|
||||||
|
[{:keys [set-path set-node tree-depth tree-path on-select selected? on-toggle active? editing? on-edit on-edit-submit]
|
||||||
|
:or {tree-depth 0}
|
||||||
|
:as props}]
|
||||||
|
(let [[set-prefix set-path'] (some-> set-path (ctob/split-set-prefix))
|
||||||
|
set? (instance? ctob/TokenSet set-node)
|
||||||
|
set-group? (= ctob/set-group-prefix set-prefix)
|
||||||
|
root? (= tree-depth 0)
|
||||||
|
collapsed? (mf/use-state false)
|
||||||
|
children? (and
|
||||||
|
(or root? set-group?)
|
||||||
|
(not @collapsed?))]
|
||||||
|
[:*
|
||||||
|
(cond
|
||||||
|
root? nil
|
||||||
|
set?
|
||||||
|
[:& sets-tree-set
|
||||||
|
{:set set-node
|
||||||
|
:active? active?
|
||||||
|
:selected? (selected? tree-path)
|
||||||
|
:on-select on-select
|
||||||
|
:label set-path'
|
||||||
|
:tree-path (or tree-path set-path)
|
||||||
|
:tree-depth tree-depth
|
||||||
|
:editing? editing?
|
||||||
|
:on-toggle on-toggle
|
||||||
|
:on-edit on-edit
|
||||||
|
:on-edit-submit on-edit-submit}]
|
||||||
|
set-group?
|
||||||
|
[:& sets-tree-set-group
|
||||||
|
{:selected? (selected? tree-path)
|
||||||
|
:on-select on-select
|
||||||
|
:label set-path'
|
||||||
|
:collapsed? collapsed?
|
||||||
|
:tree-path (or tree-path set-path)
|
||||||
|
:tree-depth tree-depth
|
||||||
|
:editing? editing?
|
||||||
|
:on-edit on-edit
|
||||||
|
:on-edit-submit on-edit-submit}])
|
||||||
|
(when children?
|
||||||
|
(for [[set-path set-node] set-node
|
||||||
|
:let [tree-path' (str (when tree-path (str tree-path "/")) set-path)]]
|
||||||
|
[:& sets-tree
|
||||||
|
{:key tree-path'
|
||||||
|
:set-path set-path
|
||||||
|
:set-node set-node
|
||||||
|
:tree-depth (when-not root? (inc tree-depth))
|
||||||
|
:tree-path tree-path'
|
||||||
|
:on-select on-select
|
||||||
|
:selected? selected?
|
||||||
|
:on-toggle on-toggle
|
||||||
|
:active? active?
|
||||||
|
:editing? editing?
|
||||||
|
:on-edit on-edit
|
||||||
|
:on-edit-submit on-edit-submit}]))]))
|
||||||
|
|
||||||
(mf/defc controlled-sets-list
|
(mf/defc controlled-sets-list
|
||||||
[{:keys [token-sets
|
[{:keys [token-sets
|
||||||
|
@ -200,59 +231,40 @@
|
||||||
on-select
|
on-select
|
||||||
context]
|
context]
|
||||||
:as _props}]
|
: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))]
|
||||||
submit-token
|
|
||||||
#(do
|
|
||||||
(on-create-token-set %)
|
|
||||||
(on-reset))]
|
|
||||||
[:ul {:class (stl/css :sets-list)}
|
[:ul {:class (stl/css :sets-list)}
|
||||||
(if (and
|
(if (and
|
||||||
(= origin "theme-modal")
|
(= origin "theme-modal")
|
||||||
(empty? token-sets))
|
(empty? token-sets))
|
||||||
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message-sets)}
|
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message-sets)}
|
||||||
(tr "workspace.token.no-sets-create")]
|
(tr "workspace.token.no-sets-create")]
|
||||||
(for [token-set token-sets]
|
(if (and (= origin "theme-modal")
|
||||||
(when token-set
|
(empty? token-sets))
|
||||||
(let [update-token
|
[:> text* {:as "span" :typography "body-small" :class (stl/css :empty-state-message-sets)}
|
||||||
#(do
|
(tr "workspace.token.no-sets-create")]
|
||||||
(on-update-token-set (:name token-set) %)
|
[:& sets-tree
|
||||||
(on-reset))]
|
{:set-node token-sets
|
||||||
[:& sets-tree
|
:selected? token-set-selected?
|
||||||
{:key (:name token-set)
|
:on-select on-select
|
||||||
:token-set token-set
|
:active? token-set-active?
|
||||||
:token-set-selected? (if new? (constantly false) token-set-selected?)
|
:on-toggle on-toggle-token-set
|
||||||
:token-set-active? token-set-active?
|
:editing? editing?
|
||||||
:editing? editing?
|
:on-edit on-edit
|
||||||
:on-select on-select
|
:on-edit-submit on-update-token-set}]))]))
|
||||||
:on-edit on-edit
|
|
||||||
:on-toggle on-toggle-token-set
|
|
||||||
:on-submit update-token
|
|
||||||
:on-cancel on-reset}]))))
|
|
||||||
|
|
||||||
(when new?
|
|
||||||
[:& sets-tree
|
|
||||||
{:token-set {:name ""}
|
|
||||||
:token-set-selected? (constantly true)
|
|
||||||
:token-set-active? (constantly true)
|
|
||||||
:editing? (constantly true)
|
|
||||||
:on-select (constantly nil)
|
|
||||||
:on-edit on-create
|
|
||||||
:on-submit submit-token
|
|
||||||
:on-cancel on-reset}])]))
|
|
||||||
|
|
||||||
(mf/defc sets-list
|
(mf/defc sets-list
|
||||||
[{:keys []}]
|
[{:keys []}]
|
||||||
(let [token-sets (mf/deref refs/workspace-ordered-token-sets)
|
(let [token-sets (mf/deref refs/workspace-token-sets-tree)
|
||||||
selected-token-set-id (mf/deref refs/workspace-selected-token-set-id)
|
selected-token-set-id (mf/deref refs/workspace-selected-token-set-id)
|
||||||
token-set-selected? (mf/use-fn
|
token-set-selected? (mf/use-fn
|
||||||
(mf/deps token-sets selected-token-set-id)
|
(mf/deps token-sets selected-token-set-id)
|
||||||
(fn [set-name]
|
(fn [tree-path]
|
||||||
(= set-name selected-token-set-id)))
|
(= tree-path selected-token-set-id)))
|
||||||
active-token-set-ids (mf/deref refs/workspace-active-set-names)
|
active-token-set-names (mf/deref refs/workspace-active-set-names)
|
||||||
token-set-active? (mf/use-fn
|
token-set-active? (mf/use-fn
|
||||||
(mf/deps active-token-set-ids)
|
(mf/deps active-token-set-names)
|
||||||
(fn [id]
|
(fn [set-name]
|
||||||
(get active-token-set-ids id)))]
|
(get active-token-set-names set-name)))]
|
||||||
[:& controlled-sets-list
|
[:& controlled-sets-list
|
||||||
{:token-sets token-sets
|
{:token-sets token-sets
|
||||||
:token-set-selected? token-set-selected?
|
:token-set-selected? token-set-selected?
|
||||||
|
|
|
@ -13,10 +13,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.set-item-container {
|
.set-item-container {
|
||||||
|
@include bodySmallTypography;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
min-height: $s-32;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--layer-row-foreground-color);
|
color: var(--layer-row-foreground-color);
|
||||||
padding-left: $s-20;
|
padding-left: calc($s-32 * var(--tree-depth, 0));
|
||||||
border: $s-2 solid transparent;
|
border: $s-2 solid transparent;
|
||||||
|
|
||||||
&.dnd-over-bot {
|
&.dnd-over-bot {
|
||||||
|
@ -30,17 +34,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.set-item-set,
|
|
||||||
.set-item-group {
|
|
||||||
@include bodySmallTypography;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
min-height: $s-32;
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
color: var(--layer-row-foreground-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.set-name {
|
.set-name {
|
||||||
@include textEllipsis;
|
@include textEllipsis;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
@ -55,6 +48,10 @@
|
||||||
padding-right: $s-4;
|
padding-right: $s-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.root-icon {
|
||||||
|
margin-left: $s-8;
|
||||||
|
}
|
||||||
|
|
||||||
.checkbox-style {
|
.checkbox-style {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -76,7 +73,7 @@
|
||||||
color: var(--color-background-secondary);
|
color: var(--color-background-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.set-item-set:hover {
|
.set-item-container:hover {
|
||||||
background-color: var(--layer-row-background-color-hover);
|
background-color: var(--layer-row-background-color-hover);
|
||||||
color: var(--layer-row-foreground-color-hover);
|
color: var(--layer-row-foreground-color-hover);
|
||||||
box-shadow: -100px 0 0 0 var(--layer-row-background-color-hover);
|
box-shadow: -100px 0 0 0 var(--layer-row-background-color-hover);
|
||||||
|
|
|
@ -35,10 +35,10 @@
|
||||||
[:span {:class (stl/css :title)} title]])
|
[:span {:class (stl/css :title)} title]])
|
||||||
|
|
||||||
(mf/defc menu
|
(mf/defc menu
|
||||||
[{:keys [token-set-name]}]
|
[{:keys [tree-path]}]
|
||||||
(let [{:keys [on-edit]} (sets-context/use-context)
|
(let [{:keys [on-edit]} (sets-context/use-context)
|
||||||
edit-name (mf/use-fn #(on-edit token-set-name))
|
edit-name (mf/use-fn #(on-edit tree-path))
|
||||||
delete-set (mf/use-fn #(st/emit! (wdt/delete-token-set token-set-name)))]
|
delete-set (mf/use-fn #(st/emit! (wdt/delete-token-set-path tree-path)))]
|
||||||
[:ul {:class (stl/css :context-list)}
|
[:ul {:class (stl/css :context-list)}
|
||||||
[:& menu-entry {:title (tr "labels.rename") :on-click edit-name}]
|
[:& menu-entry {:title (tr "labels.rename") :on-click edit-name}]
|
||||||
[:& menu-entry {:title (tr "labels.delete") :on-click delete-set}]]))
|
[:& menu-entry {:title (tr "labels.delete") :on-click delete-set}]]))
|
||||||
|
@ -49,8 +49,7 @@
|
||||||
top (+ (get-in mdata [:position :y]) 5)
|
top (+ (get-in mdata [:position :y]) 5)
|
||||||
left (+ (get-in mdata [:position :x]) 5)
|
left (+ (get-in mdata [:position :x]) 5)
|
||||||
width (mf/use-state 0)
|
width (mf/use-state 0)
|
||||||
dropdown-ref (mf/use-ref)
|
dropdown-ref (mf/use-ref)]
|
||||||
token-set-name (:token-set-name mdata)]
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps mdata)
|
(mf/deps mdata)
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -62,4 +61,4 @@
|
||||||
:ref dropdown-ref
|
:ref dropdown-ref
|
||||||
:style {:top top :left left}
|
:style {:top top :left left}
|
||||||
:on-context-menu prevent-default}
|
:on-context-menu prevent-default}
|
||||||
[:& menu {:token-set-name token-set-name}]]]))
|
[:& menu {:tree-path (:tree-path mdata)}]]]))
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]
|
[rumext.v2 :as mf]
|
||||||
[shadow.resource]))
|
[shadow.resource]
|
||||||
|
[app.main.data.tokens :as wdt]))
|
||||||
|
|
||||||
(def lens:token-type-open-status
|
(def lens:token-type-open-status
|
||||||
(l/derived (l/in [:workspace-tokens :open-status]) st/state))
|
(l/derived (l/in [:workspace-tokens :open-status]) st/state))
|
||||||
|
@ -204,7 +205,10 @@
|
||||||
(let [{:keys [on-create new?]} (sets-context/use-context)
|
(let [{:keys [on-create new?]} (sets-context/use-context)
|
||||||
on-click #(do
|
on-click #(do
|
||||||
(on-open)
|
(on-open)
|
||||||
(on-create))]
|
(let [set-path (some-> (js/prompt "Token Set Path")
|
||||||
|
(str/trim))]
|
||||||
|
(when-not (str/empty? set-path)
|
||||||
|
(st/emit! (wdt/create-token-set {:name set-path})))))]
|
||||||
(if (= style "inline")
|
(if (= style "inline")
|
||||||
(when-not new?
|
(when-not new?
|
||||||
[:div {:class (stl/css :empty-sets-wrapper)}
|
[:div {:class (stl/css :empty-sets-wrapper)}
|
||||||
|
@ -219,28 +223,30 @@
|
||||||
:aria-label (tr "workspace.token.add set")}])))
|
:aria-label (tr "workspace.token.add set")}])))
|
||||||
|
|
||||||
(mf/defc themes-sets-tab
|
(mf/defc themes-sets-tab
|
||||||
[]
|
[{:keys [resize-height]}]
|
||||||
(let [token-sets (mf/deref refs/workspace-ordered-token-sets)
|
(let [token-sets (mf/deref refs/workspace-ordered-token-sets)
|
||||||
open? (mf/use-state true)
|
open? (mf/use-state true)
|
||||||
on-open (mf/use-fn #(reset! open? true))]
|
on-open (mf/use-fn #(reset! open? true))]
|
||||||
[:& sets-context/provider {}
|
[:& sets-context/provider {}
|
||||||
[:& sets-context-menu]
|
[:& sets-context-menu]
|
||||||
[:div {:class (stl/css :sets-sidebar)}
|
[:article {:class (stl/css :sets-section-wrapper)
|
||||||
[:& themes-header]
|
:style {"--resize-height" (str resize-height "px")}}
|
||||||
[:div {:class (stl/css :sidebar-header)}
|
[:div {:class (stl/css :sets-sidebar)}
|
||||||
[:& title-bar {:collapsable true
|
[:& themes-header]
|
||||||
:collapsed (not @open?)
|
[:div {:class (stl/css :sidebar-header)}
|
||||||
:all-clickable true
|
[:& title-bar {:collapsable true
|
||||||
:title (tr "labels.sets")
|
:collapsed (not @open?)
|
||||||
:on-collapsed #(swap! open? not)}
|
:all-clickable true
|
||||||
[:& add-set-button {:on-open on-open
|
:title (tr "labels.sets")
|
||||||
:style "header"}]]]
|
:on-collapsed #(swap! open? not)}
|
||||||
(when @open?
|
[:& add-set-button {:on-open on-open
|
||||||
[:& h/sortable-container {}
|
:style "header"}]]]
|
||||||
(when (empty? token-sets)
|
(when @open?
|
||||||
|
(if (empty? token-sets)
|
||||||
[:& add-set-button {:on-open on-open
|
[:& add-set-button {:on-open on-open
|
||||||
:style "inline"}])
|
:style "inline"}]
|
||||||
[:& sets-list]])]]))
|
[:& h/sortable-container {}
|
||||||
|
[:& sets-list]]))]]]))
|
||||||
|
|
||||||
(mf/defc tokens-tab
|
(mf/defc tokens-tab
|
||||||
[_props]
|
[_props]
|
||||||
|
@ -343,15 +349,14 @@
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/wrap-props false}
|
::mf/wrap-props false}
|
||||||
[_props]
|
[_props]
|
||||||
(let [{on-pointer-down-pages :on-pointer-down
|
(let [tokens-tab? (not (mf/deref refs/workspace-token-set-group-selected?))
|
||||||
|
{on-pointer-down-pages :on-pointer-down
|
||||||
on-lost-pointer-capture-pages :on-lost-pointer-capture
|
on-lost-pointer-capture-pages :on-lost-pointer-capture
|
||||||
on-pointer-move-pages :on-pointer-move
|
on-pointer-move-pages :on-pointer-move
|
||||||
size-pages-opened :size}
|
size-pages-opened :size}
|
||||||
(use-resize-hook :tokens 200 38 400 :y false nil)]
|
(use-resize-hook :tokens 200 38 400 :y false nil)]
|
||||||
[:div {:class (stl/css :sidebar-wrapper)}
|
[:div {:class (stl/css :sidebar-wrapper)}
|
||||||
[:article {:class (stl/css :sets-section-wrapper)
|
[:& themes-sets-tab {:resize-height size-pages-opened}]
|
||||||
:style {"--resize-height" (str size-pages-opened "px")}}
|
|
||||||
[:& themes-sets-tab]]
|
|
||||||
[:article {:class (stl/css :tokens-section-wrapper)}
|
[:article {:class (stl/css :tokens-section-wrapper)}
|
||||||
[:div {:class (stl/css :resize-area-horiz)
|
[:div {:class (stl/css :resize-area-horiz)
|
||||||
:on-pointer-down on-pointer-down-pages
|
:on-pointer-down on-pointer-down-pages
|
||||||
|
|
|
@ -41,16 +41,30 @@
|
||||||
(some-> (get-workspace-tokens-lib state)
|
(some-> (get-workspace-tokens-lib state)
|
||||||
(ctob/get-sets)
|
(ctob/get-sets)
|
||||||
(first)
|
(first)
|
||||||
(:name))))
|
(ctob/get-set-path))))
|
||||||
|
|
||||||
|
(defn get-selected-token-set-node [state]
|
||||||
|
(when-let [path (some-> (get-selected-token-set-id state)
|
||||||
|
(ctob/split-token-set-path))]
|
||||||
|
(some-> (get-workspace-tokens-lib state)
|
||||||
|
(ctob/get-in-set-tree path))))
|
||||||
|
|
||||||
(defn get-selected-token-set [state]
|
(defn get-selected-token-set [state]
|
||||||
(when-let [id (get-selected-token-set-id state)]
|
(let [set-node (get-selected-token-set-node state)]
|
||||||
(some-> (get-workspace-tokens-lib state)
|
(when (instance? ctob/TokenSet set-node)
|
||||||
(ctob/get-set id))))
|
set-node)))
|
||||||
|
|
||||||
|
(defn get-selected-token-set-group [state]
|
||||||
|
(let [set-node (get-selected-token-set-node state)]
|
||||||
|
(when (and set-node (not (instance? ctob/TokenSet set-node)))
|
||||||
|
set-node)))
|
||||||
|
|
||||||
(defn get-selected-token-set-tokens [state]
|
(defn get-selected-token-set-tokens [state]
|
||||||
(some-> (get-selected-token-set state)
|
(some-> (get-selected-token-set state)
|
||||||
:tokens))
|
:tokens))
|
||||||
|
|
||||||
|
(defn token-group-selected? [state]
|
||||||
|
(some? (get-selected-token-set-group state)))
|
||||||
|
|
||||||
(defn assoc-selected-token-set-id [state id]
|
(defn assoc-selected-token-set-id [state id]
|
||||||
(assoc-in state [:workspace-local :selected-token-set-id] id))
|
(assoc-in state [:workspace-local :selected-token-set-id] id))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue