mirror of
https://github.com/penpot/penpot.git
synced 2025-01-20 05:34:23 -05:00
Merge pull request #371 from tokens-studio/rebase-ui-updates
Sets UI Updates
This commit is contained in:
commit
bb337361b8
9 changed files with 72 additions and 178 deletions
|
@ -215,6 +215,10 @@
|
|||
(defn split-token-set-path [path]
|
||||
(split-path path set-separator))
|
||||
|
||||
(defn get-token-set-final-name [path]
|
||||
(-> (split-token-set-path path)
|
||||
(last)))
|
||||
|
||||
(defn set-name->prefixed-full-path [name-str]
|
||||
(-> (split-token-set-path name-str)
|
||||
(set-full-path->set-prefixed-full-path)))
|
||||
|
@ -223,6 +227,11 @@
|
|||
(let [path (get-path token-set set-separator)]
|
||||
(set-full-path->set-prefixed-full-path path)))
|
||||
|
||||
(defn get-prefixed-token-set-final-prefix [prefixed-path-str]
|
||||
(some-> (get-token-set-final-name prefixed-path-str)
|
||||
(split-set-str-path-prefix)
|
||||
(first)))
|
||||
|
||||
(defn set-name-string->prefixed-set-path-string [name-str]
|
||||
(-> (set-name->prefixed-full-path name-str)
|
||||
(join-set-path)))
|
||||
|
@ -235,6 +244,16 @@
|
|||
path-part)))
|
||||
(join-set-path)))
|
||||
|
||||
(defn prefixed-set-path-final-group?
|
||||
"Predicate if the given prefixed path string ends with a group."
|
||||
[prefixed-path-str]
|
||||
(= (get-prefixed-token-set-final-prefix prefixed-path-str) set-group-prefix))
|
||||
|
||||
(defn prefixed-set-path-final-set?
|
||||
"Predicate if the given prefixed path string ends with a set."
|
||||
[prefixed-path-str]
|
||||
(= (get-prefixed-token-set-final-prefix prefixed-path-str) set-prefix))
|
||||
|
||||
(defn tokens-tree
|
||||
"Convert tokens into a nested tree with their `:name` as the path.
|
||||
Optionally use `update-token-fn` option to transform the token."
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.common.types.tokens-list
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.time :as dt]))
|
||||
|
||||
(defn tokens-seq
|
||||
"Returns a sequence of all tokens within the file data."
|
||||
[file-data]
|
||||
(vals (:tokens file-data)))
|
||||
|
||||
(defn- touch
|
||||
"Updates the `modified-at` timestamp of a token."
|
||||
[token]
|
||||
(assoc token :modified-at (dt/now)))
|
||||
|
||||
(defn add-token
|
||||
"Adds a new token to the file data, setting its `modified-at` timestamp."
|
||||
[file-data token-set-id token]
|
||||
(-> file-data
|
||||
(update :tokens assoc (:id token) (touch token))
|
||||
(d/update-in-when [:token-sets-index token-set-id] #(->
|
||||
(update % :tokens conj (:id token))
|
||||
(touch)))))
|
||||
|
||||
(defn get-token
|
||||
"Retrieves a token by its ID from the file data."
|
||||
[file-data token-id]
|
||||
(get-in file-data [:tokens token-id]))
|
||||
|
||||
(defn set-token
|
||||
"Sets or updates a token in the file data, updating its `modified-at` timestamp."
|
||||
[file-data token]
|
||||
(d/assoc-in-when file-data [:tokens (:id token)] (touch token)))
|
||||
|
||||
(defn update-token
|
||||
"Applies a function to update a token in the file data, then touches it."
|
||||
[file-data token-id f & args]
|
||||
(d/update-in-when file-data [:tokens token-id] #(-> (apply f % args) (touch))))
|
||||
|
||||
(defn delete-token
|
||||
"Removes a token from the file data by its ID."
|
||||
[file-data token-id]
|
||||
(update file-data :tokens dissoc token-id))
|
|
@ -1,79 +0,0 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.common.types.tokens-theme-list
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.time :as dt]))
|
||||
|
||||
(defn- touch
|
||||
"Updates the `modified-at` timestamp of a token set."
|
||||
[token-set]
|
||||
(assoc token-set :modified-at (dt/now)))
|
||||
|
||||
(defn assoc-active-token-themes
|
||||
[file-data theme-ids]
|
||||
(assoc file-data :token-active-themes theme-ids))
|
||||
|
||||
(defn add-temporary-token-theme
|
||||
[file-data {:keys [id name] :as token-theme}]
|
||||
(-> file-data
|
||||
(d/dissoc-in [:token-themes-index (:token-theme-temporary-id file-data)])
|
||||
(assoc :token-theme-temporary-id id)
|
||||
(assoc :token-theme-temporary-name name)
|
||||
(update :token-themes-index assoc id token-theme)))
|
||||
|
||||
(defn delete-temporary-token-theme
|
||||
[file-data token-theme-id]
|
||||
(cond-> file-data
|
||||
(= (:token-theme-temporary-id file-data) token-theme-id) (dissoc :token-theme-temporary-id :token-theme-temporary-name)
|
||||
:always (d/dissoc-in [:token-themes-index (:token-theme-temporary-id file-data)])))
|
||||
|
||||
(defn add-token-theme
|
||||
[file-data {:keys [index id] :as token-theme}]
|
||||
(-> file-data
|
||||
(update :token-themes
|
||||
(fn [token-themes]
|
||||
(let [exists? (some (partial = id) token-themes)]
|
||||
(cond
|
||||
exists? token-themes
|
||||
(nil? index) (conj (or token-themes []) id)
|
||||
:else (d/insert-at-index token-themes index [id])))))
|
||||
(update :token-themes-index assoc id token-theme)))
|
||||
|
||||
(defn update-token-theme
|
||||
[file-data token-theme-id f & args]
|
||||
(d/update-in-when file-data [:token-themes-index token-theme-id] #(-> (apply f % args) (touch))))
|
||||
|
||||
(defn delete-token-theme
|
||||
[file-data theme-id]
|
||||
(-> file-data
|
||||
(update :token-themes (fn [ids] (d/removev #(= % theme-id) ids)))
|
||||
(update :token-themes-index dissoc theme-id)
|
||||
(update :token-active-themes disj theme-id)))
|
||||
|
||||
(defn add-token-set
|
||||
[file-data {:keys [index id] :as token-set}]
|
||||
(-> file-data
|
||||
(update :token-set-groups
|
||||
(fn [token-set-groups]
|
||||
(let [exists? (some (partial = id) token-set-groups)]
|
||||
(cond
|
||||
exists? token-set-groups
|
||||
(nil? index) (conj (or token-set-groups []) id)
|
||||
:else (d/insert-at-index token-set-groups index [id])))))
|
||||
(update :token-sets-index assoc id token-set)))
|
||||
|
||||
(defn update-token-set
|
||||
[file-data token-set-id f & args]
|
||||
(d/update-in-when file-data [:token-sets-index token-set-id] #(-> (apply f % args) (touch))))
|
||||
|
||||
(defn delete-token-set
|
||||
[file-data token-set-id]
|
||||
(-> file-data
|
||||
(update :token-set-groups (fn [xs] (into [] (remove #(= (:id %) token-set-id) xs))))
|
||||
(update :token-sets-index dissoc token-set-id)
|
||||
(update :token-themes-index (fn [xs] (update-vals xs #(update % :sets disj token-set-id))))))
|
|
@ -493,9 +493,6 @@
|
|||
(def workspace-selected-token-set-path
|
||||
(l/derived wtts/get-selected-token-set-path st/state))
|
||||
|
||||
(def workspace-token-set-group-selected?
|
||||
(l/derived wtts/token-group-selected? st/state))
|
||||
|
||||
(def workspace-ordered-token-sets
|
||||
(l/derived #(or (some-> % ctob/get-sets) []) tokens-lib))
|
||||
|
||||
|
|
|
@ -271,6 +271,11 @@
|
|||
(mf/deps theme-state)
|
||||
(fn [set-name]
|
||||
(swap! theme-state #(ctob/toggle-set % set-name))))
|
||||
on-click-token-set (mf/use-callback
|
||||
(mf/deps on-toggle-token-set)
|
||||
(fn [prefixed-set-path-str]
|
||||
(let [set-name (ctob/prefixed-set-path-string->set-name-string prefixed-set-path-str)]
|
||||
(on-toggle-token-set set-name))))
|
||||
on-change-field (fn [field value]
|
||||
(swap! theme-state #(assoc % field value)))
|
||||
on-save-form (mf/use-callback
|
||||
|
@ -322,7 +327,7 @@
|
|||
{:token-sets token-sets
|
||||
:token-set-selected? (constantly false)
|
||||
:token-set-active? token-set-active?
|
||||
:on-select on-toggle-token-set
|
||||
:on-select on-click-token-set
|
||||
:on-toggle-token-set on-toggle-token-set
|
||||
:origin "theme-modal"
|
||||
:context sets-context/static-context}]]
|
||||
|
|
|
@ -60,16 +60,8 @@
|
|||
:default-value default-value}]))
|
||||
|
||||
(mf/defc sets-tree-set-group
|
||||
[{:keys [label tree-depth tree-path selected? collapsed? on-select editing? on-edit on-edit-reset on-edit-submit]}]
|
||||
[{:keys [label tree-depth tree-path selected? collapsed? editing? on-edit on-edit-reset on-edit-submit]}]
|
||||
(let [editing?' (editing? tree-path)
|
||||
on-click
|
||||
(mf/use-fn
|
||||
(mf/deps editing? tree-path)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when-not (editing? tree-path)
|
||||
(on-select tree-path))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps editing? tree-path)
|
||||
|
@ -80,33 +72,34 @@
|
|||
(st/emit!
|
||||
(wdt/show-token-set-context-menu
|
||||
{:position (dom/get-client-position event)
|
||||
:tree-path tree-path})))))]
|
||||
[:div {;; :ref dref
|
||||
:role "button"
|
||||
:prefixed-set-path tree-path})))))
|
||||
on-click (mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! collapsed? not)))]
|
||||
[:div {:role "button"
|
||||
:data-testid "tokens-set-group-item"
|
||||
:style {"--tree-depth" tree-depth}
|
||||
:class (stl/css-case :set-item-container true
|
||||
:set-item-group true
|
||||
:selected-set selected?)
|
||||
:on-click on-click
|
||||
:on-context-menu on-context-menu
|
||||
:on-double-click #(on-edit tree-path)}
|
||||
:on-context-menu on-context-menu}
|
||||
[:> icon-button*
|
||||
{:on-click (fn [event]
|
||||
(.stopPropagation event)
|
||||
(swap! collapsed? not))
|
||||
{:class (stl/css :set-item-group-collapse-button)
|
||||
:on-click on-click
|
||||
:aria-label (tr "labels.collapse")
|
||||
:icon (if @collapsed? "arrow-right" "arrow-down")
|
||||
:variant "action"}]
|
||||
[:> icon*
|
||||
{:id "group"
|
||||
:class (stl/css :icon)}]
|
||||
(if editing?'
|
||||
[:& editing-label
|
||||
{:default-value label
|
||||
:on-cancel on-edit-reset
|
||||
:on-create on-edit-reset
|
||||
:on-submit #(on-edit-submit)}]
|
||||
[:div {:class (stl/css :set-name)} label])]))
|
||||
;; TODO Implement set group renaming
|
||||
:on-submit (constantly nil)}]
|
||||
[:div {:class (stl/css :set-name)
|
||||
:on-double-click #(on-edit tree-path)}
|
||||
label])]))
|
||||
|
||||
(mf/defc sets-tree-set
|
||||
[{:keys [set label tree-depth tree-path selected? on-select active? on-toggle editing? on-edit on-edit-reset on-edit-submit]}]
|
||||
|
@ -119,9 +112,7 @@
|
|||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when-not editing?'
|
||||
(on-toggle set-name)
|
||||
(on-select tree-path))))
|
||||
|
||||
on-context-menu
|
||||
(mf/use-fn
|
||||
(mf/deps editing?' tree-path)
|
||||
|
@ -132,16 +123,17 @@
|
|||
(st/emit!
|
||||
(wdt/show-token-set-context-menu
|
||||
{:position (dom/get-client-position event)
|
||||
:tree-path tree-path})))))]
|
||||
|
||||
[:div {;; :ref dref
|
||||
:role "button"
|
||||
:prefixed-set-path tree-path})))))
|
||||
on-checkbox-click (mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(on-toggle set-name)))]
|
||||
[:div {:role "button"
|
||||
:data-testid "tokens-set-item"
|
||||
: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
|
||||
:aria-checked active?'}
|
||||
[:> icon*
|
||||
|
@ -155,9 +147,11 @@
|
|||
:on-create on-edit-reset
|
||||
:on-submit #(on-edit-submit set-name (ctob/update-name set %))}]
|
||||
[:*
|
||||
[:div {:class (stl/css :set-name)} label]
|
||||
[:button {:on-click on-click
|
||||
:type "button"
|
||||
[:div {:class (stl/css :set-name)
|
||||
:on-double-click #(on-edit tree-path)}
|
||||
label]
|
||||
[:button {:type "button"
|
||||
:on-click on-checkbox-click
|
||||
:class (stl/css-case :checkbox-style true
|
||||
:checkbox-checked-style active?')}
|
||||
(when active?'
|
||||
|
@ -170,9 +164,9 @@
|
|||
[{:keys [set-path set-node tree-depth tree-path on-select selected? on-toggle active? editing? on-edit on-edit-reset on-edit-submit]
|
||||
:or {tree-depth 0}
|
||||
:as props}]
|
||||
(let [[set-prefix set-path'] (some-> set-path (ctob/split-set-str-path-prefix))
|
||||
(let [[set-path-prefix set-fname] (some-> set-path (ctob/split-set-str-path-prefix))
|
||||
set? (instance? ctob/TokenSet set-node)
|
||||
set-group? (= ctob/set-group-prefix set-prefix)
|
||||
set-group? (= ctob/set-group-prefix set-path-prefix)
|
||||
root? (= tree-depth 0)
|
||||
collapsed? (mf/use-state false)
|
||||
children? (and
|
||||
|
@ -187,7 +181,7 @@
|
|||
:active? active?
|
||||
:selected? (selected? tree-path)
|
||||
:on-select on-select
|
||||
:label set-path'
|
||||
:label set-fname
|
||||
:tree-path (or tree-path set-path)
|
||||
:tree-depth tree-depth
|
||||
:editing? editing?
|
||||
|
@ -199,7 +193,7 @@
|
|||
[:& sets-tree-set-group
|
||||
{:selected? (selected? tree-path)
|
||||
:on-select on-select
|
||||
:label set-path'
|
||||
:label set-fname
|
||||
:collapsed? collapsed?
|
||||
:tree-path (or tree-path set-path)
|
||||
:tree-depth tree-depth
|
||||
|
|
|
@ -34,6 +34,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
.set-item-group {
|
||||
cursor: unset;
|
||||
}
|
||||
|
||||
.set-item-group-collapse-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.set-name {
|
||||
@include textEllipsis;
|
||||
flex-grow: 1;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.workspace.tokens.sets-context-menu
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.tokens :as wdt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -35,11 +36,13 @@
|
|||
[:span {:class (stl/css :title)} title]])
|
||||
|
||||
(mf/defc menu
|
||||
[{:keys [tree-path]}]
|
||||
[{:keys [prefixed-set-path]}]
|
||||
(let [{:keys [on-edit]} (sets-context/use-context)
|
||||
edit-name (mf/use-fn #(on-edit tree-path))
|
||||
delete-set (mf/use-fn #(st/emit! (wdt/delete-token-set-path tree-path)))]
|
||||
edit-name (mf/use-fn #(on-edit prefixed-set-path))
|
||||
delete-set (mf/use-fn #(st/emit! (wdt/delete-token-set-path prefixed-set-path)))]
|
||||
[:ul {:class (stl/css :context-list)}
|
||||
(when (ctob/prefixed-set-path-final-group? prefixed-set-path)
|
||||
[:& menu-entry {:title "Add set to this group" :on-click js/console.log}])
|
||||
[:& menu-entry {:title (tr "labels.rename") :on-click edit-name}]
|
||||
[:& menu-entry {:title (tr "labels.delete") :on-click delete-set}]]))
|
||||
|
||||
|
@ -61,4 +64,4 @@
|
|||
:ref dropdown-ref
|
||||
:style {:top top :left left}
|
||||
:on-context-menu prevent-default}
|
||||
[:& menu {:tree-path (:tree-path mdata)}]]]))
|
||||
[:& menu {:prefixed-set-path (:prefixed-set-path mdata)}]]]))
|
||||
|
|
|
@ -245,11 +245,7 @@
|
|||
[:div {:class (stl/css :sets-sidebar)}
|
||||
[:& themes-header]
|
||||
[:div {:class (stl/css :sidebar-header)}
|
||||
[:& title-bar {:collapsable true
|
||||
:collapsed (not @open?)
|
||||
:all-clickable true
|
||||
:title (tr "labels.sets")
|
||||
:on-collapsed #(swap! open? not)}
|
||||
[:& title-bar {:title (tr "labels.sets")}
|
||||
[:& add-set-button {:on-open on-open
|
||||
:style "header"}]]]
|
||||
[:& theme-sets-list {:on-open on-open}]]]]))
|
||||
|
|
Loading…
Add table
Reference in a new issue