mirror of
https://github.com/penpot/penpot.git
synced 2025-01-20 13:42:59 -05:00
Merge pull request #365 from tokens-studio/sets-naming
Rename sets paths/name to match guidelines
This commit is contained in:
commit
030f074285
12 changed files with 170 additions and 107 deletions
|
@ -820,13 +820,13 @@
|
||||||
(apply-changes-local)))
|
(apply-changes-local)))
|
||||||
|
|
||||||
(defn delete-token-set-path
|
(defn delete-token-set-path
|
||||||
[changes token-set-path]
|
[changes prefixed-full-set-path]
|
||||||
(assert-library! changes)
|
(assert-library! changes)
|
||||||
(let [library-data (::library-data (meta changes))
|
(let [library-data (::library-data (meta changes))
|
||||||
prev-token-sets (some-> (get library-data :tokens-lib)
|
prev-token-sets (some-> (get library-data :tokens-lib)
|
||||||
(ctob/get-path-sets token-set-path))]
|
(ctob/get-sets-at-prefix-path prefixed-full-set-path))]
|
||||||
(-> changes
|
(-> changes
|
||||||
(update :redo-changes conj {:type :del-token-set-path :path token-set-path})
|
(update :redo-changes conj {:type :del-token-set-path :path prefixed-full-set-path})
|
||||||
(update :undo-changes conj {:type :add-token-sets :token-sets prev-token-sets})
|
(update :undo-changes conj {:type :add-token-sets :token-sets prev-token-sets})
|
||||||
(apply-changes-local))))
|
(apply-changes-local))))
|
||||||
|
|
||||||
|
|
|
@ -183,49 +183,54 @@
|
||||||
|
|
||||||
(def set-separator "/")
|
(def set-separator "/")
|
||||||
|
|
||||||
(defn join-set-path [set-path]
|
(defn join-set-path [path]
|
||||||
(join-path set-path set-separator))
|
(join-path path set-separator))
|
||||||
|
|
||||||
(defn split-set-prefix [set-path]
|
(defn split-set-str-path-prefix
|
||||||
(some->> set-path
|
"Split set-path
|
||||||
|
|
||||||
|
E.g.: \"S-some-set\" -> [\"S-\" \"some-set\"]
|
||||||
|
\"G-some-group\" -> [\"G-\" \"some-group\"]"
|
||||||
|
[path-str]
|
||||||
|
(some->> path-str
|
||||||
(re-matches #"^([SG]-)(.*)")
|
(re-matches #"^([SG]-)(.*)")
|
||||||
(rest)))
|
(rest)))
|
||||||
|
|
||||||
(defn add-set-prefix [set-name]
|
(defn add-set-path-prefix [set-name-str]
|
||||||
(str set-prefix set-name))
|
(str set-prefix set-name-str))
|
||||||
|
|
||||||
(defn add-set-group-prefix [group-path]
|
(defn add-set-path-group-prefix [group-path-str]
|
||||||
(str set-group-prefix group-path))
|
(str set-group-prefix group-path-str))
|
||||||
|
|
||||||
(defn add-token-set-paths-prefix
|
(defn set-full-path->set-prefixed-full-path
|
||||||
"Returns token-set paths with prefixes to differentiate between sets and set-groups.
|
"Returns token-set paths with prefixes to differentiate between sets and set-groups.
|
||||||
|
|
||||||
Sets will be prefixed with `set-prefix` (S-).
|
Sets will be prefixed with `set-prefix` (S-).
|
||||||
Set groups will be prefixed with `set-group-prefix` (G-)."
|
Set groups will be prefixed with `set-group-prefix` (G-)."
|
||||||
[paths]
|
[full-path]
|
||||||
(let [set-path (mapv add-set-group-prefix (butlast paths))
|
(let [set-path (mapv add-set-path-group-prefix (butlast full-path))
|
||||||
set-name (add-set-prefix (last paths))]
|
set-name (add-set-path-prefix (last full-path))]
|
||||||
(conj set-path set-name)))
|
(conj set-path set-name)))
|
||||||
|
|
||||||
(defn split-token-set-path [token-set-path]
|
(defn split-token-set-path [path]
|
||||||
(split-path token-set-path set-separator))
|
(split-path path set-separator))
|
||||||
|
|
||||||
(defn split-token-set-name [token-set-name]
|
(defn set-name->prefixed-full-path [name-str]
|
||||||
(-> (split-token-set-path token-set-name)
|
(-> (split-token-set-path name-str)
|
||||||
(add-token-set-paths-prefix)))
|
(set-full-path->set-prefixed-full-path)))
|
||||||
|
|
||||||
(defn get-token-set-path [token-set]
|
(defn get-token-set-prefixed-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)))
|
(set-full-path->set-prefixed-full-path path)))
|
||||||
|
|
||||||
(defn set-name->set-path-string [set-name]
|
(defn set-name-string->prefixed-set-path-string [name-str]
|
||||||
(-> (split-token-set-name set-name)
|
(-> (set-name->prefixed-full-path name-str)
|
||||||
(join-set-path)))
|
(join-set-path)))
|
||||||
|
|
||||||
(defn set-path->set-name [set-path]
|
(defn prefixed-set-path-string->set-name-string [path-str]
|
||||||
(->> (split-token-set-path set-path)
|
(->> (split-token-set-path path-str)
|
||||||
(map (fn [path-part]
|
(map (fn [path-part]
|
||||||
(or (-> (split-set-prefix path-part)
|
(or (-> (split-set-str-path-prefix path-part)
|
||||||
(second))
|
(second))
|
||||||
path-part)))
|
path-part)))
|
||||||
(join-set-path)))
|
(join-set-path)))
|
||||||
|
@ -263,7 +268,7 @@
|
||||||
(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-set-prefixed-path-string [_] "convert set name to prefixed full path string")
|
||||||
(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"))
|
||||||
|
|
||||||
|
@ -312,8 +317,8 @@
|
||||||
(get-tokens [_]
|
(get-tokens [_]
|
||||||
(vals tokens))
|
(vals tokens))
|
||||||
|
|
||||||
(get-set-path [_]
|
(get-set-prefixed-path-string [_]
|
||||||
(set-name->set-path-string name))
|
(set-name-string->prefixed-set-path-string name))
|
||||||
|
|
||||||
(get-tokens-tree [_]
|
(get-tokens-tree [_]
|
||||||
(tokens-tree tokens))
|
(tokens-tree tokens))
|
||||||
|
@ -358,9 +363,23 @@
|
||||||
;; === TokenSets (collection)
|
;; === TokenSets (collection)
|
||||||
|
|
||||||
(defprotocol ITokenSets
|
(defprotocol ITokenSets
|
||||||
|
"Collection of sets and set groups.
|
||||||
|
|
||||||
|
Naming conventions:
|
||||||
|
Set name: the complete name as a string, without prefix \"some-group/some-subgroup/some-set\".
|
||||||
|
Set final name or fname: the last part of the name \"some-set\".
|
||||||
|
Set path: the groups part of the name, as a vector [\"some-group\" \"some-subgroup\"].
|
||||||
|
Set path str: the set path as a string \"some-group/some-subgroup\".
|
||||||
|
Set full path: the path including the fname, as a vector [\"some-group\", \"some-subgroup\", \"some-set\"].
|
||||||
|
Set full path str: the set full path as a string \"some-group/some-subgroup/some-set\".
|
||||||
|
|
||||||
|
Set prefix: the two-characters prefix added to a full path item \"G-\" / \"S-\".
|
||||||
|
Prefixed set path or ppath: a path wit added prefixes [\"G-some-group\", \"G-some-subgroup\"].
|
||||||
|
Prefixed set full path or pfpath: a full path wit prefixes [\"G-some-group\", \"G-some-subgroup\", \"S-some-set\"].
|
||||||
|
Prefixed set final name or pfname: a final name with prefix \"S-some-set\"."
|
||||||
(add-set [_ token-set] "add a set to the library, at the end")
|
(add-set [_ token-set] "add a set to the library, at the end")
|
||||||
(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 library")
|
||||||
(delete-set-path [_ set-path] "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")
|
||||||
|
@ -368,7 +387,7 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
(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-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-sets-at-prefix-path [_ 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`"))
|
||||||
|
@ -613,7 +632,7 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
ITokenSets
|
ITokenSets
|
||||||
(add-set [_ token-set]
|
(add-set [_ token-set]
|
||||||
(dm/assert! "expected valid token set" (check-token-set! token-set))
|
(dm/assert! "expected valid token set" (check-token-set! token-set))
|
||||||
(let [path (get-token-set-path token-set)]
|
(let [path (get-token-set-prefixed-path token-set)]
|
||||||
(TokensLib. (d/oassoc-in sets path token-set)
|
(TokensLib. (d/oassoc-in sets path token-set)
|
||||||
themes
|
themes
|
||||||
active-themes)))
|
active-themes)))
|
||||||
|
@ -625,18 +644,18 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
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 [prefixed-full-path (set-name->prefixed-full-path set-name)
|
||||||
set (get-in sets path)]
|
set (get-in sets prefixed-full-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')
|
prefixed-full-path' (get-token-set-prefixed-path set')
|
||||||
name-changed? (not= (:name set) (:name set'))]
|
name-changed? (not= (:name set) (:name set'))]
|
||||||
(check-token-set! set')
|
(check-token-set! set')
|
||||||
(if name-changed?
|
(if name-changed?
|
||||||
(TokensLib. (-> sets
|
(TokensLib. (-> sets
|
||||||
(d/oassoc-in-before path path' set')
|
(d/oassoc-in-before prefixed-full-path prefixed-full-path' set')
|
||||||
(d/dissoc-in path))
|
(d/dissoc-in prefixed-full-path))
|
||||||
(walk/postwalk
|
(walk/postwalk
|
||||||
(fn [form]
|
(fn [form]
|
||||||
(if (instance? TokenTheme form)
|
(if (instance? TokenTheme form)
|
||||||
|
@ -644,33 +663,34 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
form))
|
form))
|
||||||
themes)
|
themes)
|
||||||
active-themes)
|
active-themes)
|
||||||
(TokensLib. (d/oassoc-in sets path set')
|
(TokensLib. (d/oassoc-in sets prefixed-full-path set')
|
||||||
themes
|
themes
|
||||||
active-themes)))
|
active-themes)))
|
||||||
this)))
|
this)))
|
||||||
|
|
||||||
(delete-set-path [_ set-path]
|
(delete-set-path [_ prefixed-set-name]
|
||||||
(let [path (split-token-set-path set-path)
|
(let [prefixed-set-path (split-token-set-path prefixed-set-name)
|
||||||
set-node (get-in sets path)
|
set-node (get-in sets prefixed-set-path)
|
||||||
set-group? (not (instance? TokenSet set-node))]
|
set-group? (not (instance? TokenSet set-node))
|
||||||
(TokensLib. (d/dissoc-in sets path)
|
set-name-string (prefixed-set-path-string->set-name-string prefixed-set-name)]
|
||||||
|
(TokensLib. (d/dissoc-in sets prefixed-set-path)
|
||||||
;; TODO: When deleting a set-group, also deactivate the child sets
|
;; TODO: When deleting a set-group, also deactivate the child sets
|
||||||
(if set-group?
|
(if set-group?
|
||||||
themes
|
themes
|
||||||
(walk/postwalk
|
(walk/postwalk
|
||||||
(fn [form]
|
(fn [form]
|
||||||
(if (instance? TokenTheme form)
|
(if (instance? TokenTheme form)
|
||||||
(disable-set form set-path)
|
(disable-set form set-name-string)
|
||||||
form))
|
form))
|
||||||
themes))
|
themes))
|
||||||
active-themes)))
|
active-themes)))
|
||||||
|
|
||||||
;; TODO Handle groups and nesting
|
;; TODO Handle groups and nesting
|
||||||
(move-set-before [this set-name before-set-name]
|
(move-set-before [this set-name before-set-name]
|
||||||
(let [source-path (split-token-set-name set-name)
|
(let [source-path (set-name->prefixed-full-path set-name)
|
||||||
token-set (-> (get-set this set-name)
|
token-set (-> (get-set this set-name)
|
||||||
(assoc :modified-at (dt/now)))
|
(assoc :modified-at (dt/now)))
|
||||||
target-path (split-token-set-name before-set-name)]
|
target-path (set-name->prefixed-full-path before-set-name)]
|
||||||
(if before-set-name
|
(if before-set-name
|
||||||
(TokensLib. (d/oassoc-in-before sets target-path source-path token-set)
|
(TokensLib. (d/oassoc-in-before sets target-path source-path token-set)
|
||||||
themes
|
themes
|
||||||
|
@ -691,7 +711,7 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
(->> (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]
|
(get-sets-at-prefix-path [_ path]
|
||||||
(some->> (get-in sets (split-token-set-path path))
|
(some->> (get-in sets (split-token-set-path path))
|
||||||
(tree-seq d/ordered-map? vals)
|
(tree-seq d/ordered-map? vals)
|
||||||
(filter (partial instance? TokenSet))))
|
(filter (partial instance? TokenSet))))
|
||||||
|
@ -703,7 +723,7 @@ When `before-set-name` is nil, move set to bottom")
|
||||||
(count (get-sets this)))
|
(count (get-sets this)))
|
||||||
|
|
||||||
(get-set [_ set-name]
|
(get-set [_ set-name]
|
||||||
(let [path (split-token-set-name set-name)]
|
(let [path (set-name->prefixed-full-path set-name)]
|
||||||
(get-in sets path)))
|
(get-in sets path)))
|
||||||
|
|
||||||
(get-neighbor-set-name [this set-name index-offset]
|
(get-neighbor-set-name [this set-name index-offset]
|
||||||
|
|
|
@ -100,7 +100,6 @@
|
||||||
(->> (ctob/move-set-before tokens-lib set-name before-set-name)
|
(->> (ctob/move-set-before tokens-lib set-name before-set-name)
|
||||||
(ctob/get-ordered-set-names)
|
(ctob/get-ordered-set-names)
|
||||||
(into [])))]
|
(into [])))]
|
||||||
;; TODO Nested moving doesn't work as expected
|
|
||||||
(t/testing "regular moving"
|
(t/testing "regular moving"
|
||||||
(t/is (= ["A" "Move" "B"] (move "Move" "B")))
|
(t/is (= ["A" "Move" "B"] (move "Move" "B")))
|
||||||
(t/is (= ["B" "A" "Move"] (move "A" "Move"))))
|
(t/is (= ["B" "A" "Move"] (move "A" "Move"))))
|
||||||
|
@ -241,11 +240,10 @@
|
||||||
(ctob/delete-set-path "S-not-existing-set"))
|
(ctob/delete-set-path "S-not-existing-set"))
|
||||||
|
|
||||||
token-set' (ctob/get-set tokens-lib' "updated-name")
|
token-set' (ctob/get-set tokens-lib' "updated-name")
|
||||||
;;token-theme' (ctob/get-theme tokens-lib' "" "test-token-theme")
|
token-theme' (ctob/get-theme tokens-lib' "" "test-token-theme")]
|
||||||
]
|
|
||||||
|
|
||||||
(t/is (= (ctob/set-count tokens-lib') 0))
|
(t/is (= (ctob/set-count tokens-lib') 0))
|
||||||
;; (t/is (= (:sets token-theme') #{})) TODO: fix this
|
(t/is (= (:sets token-theme') #{}))
|
||||||
(t/is (nil? token-set'))))
|
(t/is (nil? token-set'))))
|
||||||
|
|
||||||
(t/deftest active-themes-set-names
|
(t/deftest active-themes-set-names
|
||||||
|
|
|
@ -80,6 +80,8 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||||
"token-update-create-modal",
|
"token-update-create-modal",
|
||||||
);
|
);
|
||||||
this.tokenThemesSetsSidebar = page.getByTestId("token-themes-sets-sidebar");
|
this.tokenThemesSetsSidebar = page.getByTestId("token-themes-sets-sidebar");
|
||||||
|
this.tokenSetItems = page.getByTestId("tokens-set-item");
|
||||||
|
this.tokenSetGroupItems = page.getByTestId("tokens-set-group-item");
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToWorkspace({
|
async goToWorkspace({
|
||||||
|
|
|
@ -18,14 +18,21 @@ const setupFileWithTokens = async (page) => {
|
||||||
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
||||||
await tokensTabButton.click();
|
await tokensTabButton.click();
|
||||||
|
|
||||||
return { workspacePage };
|
return {
|
||||||
|
workspacePage,
|
||||||
|
tokensUpdateCreateModal: workspacePage.tokensUpdateCreateModal,
|
||||||
|
tokenThemesSetsSidebar: workspacePage.tokenThemesSetsSidebar,
|
||||||
|
tokenSetItems: workspacePage.tokenSetItems,
|
||||||
|
tokenSetGroupItems: workspacePage.tokenSetGroupItems,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
test.describe("Tokens: Tab", () => {
|
test.describe("Tokens: Tokens Tab", () => {
|
||||||
test("Clicking tokens tab button opens tokens sidebar tab", async ({
|
test("Clicking tokens tab button opens tokens sidebar tab", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
const { workspacePage } = await setupFileWithTokens(page);
|
const { workspacePage, tokensUpdateCreateModal, tokenThemesSetsSidebar } =
|
||||||
|
await setupFileWithTokens(page);
|
||||||
|
|
||||||
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
||||||
|
|
||||||
|
@ -36,18 +43,18 @@ test.describe("Tokens: Tab", () => {
|
||||||
test("User creates color token and auto created set show up in the sidebar", async ({
|
test("User creates color token and auto created set show up in the sidebar", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
const { workspacePage } = await setupFileWithTokens(page);
|
const { workspacePage, tokensUpdateCreateModal, tokenThemesSetsSidebar } =
|
||||||
|
await setupFileWithTokens(page);
|
||||||
|
|
||||||
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
||||||
await tokensTabPanel.getByTitle("Add token: Color").click();
|
await tokensTabPanel.getByTitle("Add token: Color").click();
|
||||||
|
|
||||||
// Create color token with mouse
|
// Create color token with mouse
|
||||||
|
|
||||||
await expect(workspacePage.tokensUpdateCreateModal).toBeVisible();
|
await expect(tokensUpdateCreateModal).toBeVisible();
|
||||||
|
|
||||||
const nameField = workspacePage.tokensUpdateCreateModal.getByLabel("Name");
|
const nameField = tokensUpdateCreateModal.getByLabel("Name");
|
||||||
const valueField =
|
const valueField = tokensUpdateCreateModal.getByLabel("Value");
|
||||||
workspacePage.tokensUpdateCreateModal.getByLabel("Value");
|
|
||||||
|
|
||||||
await nameField.click();
|
await nameField.click();
|
||||||
await nameField.fill("color.primary");
|
await nameField.fill("color.primary");
|
||||||
|
@ -55,12 +62,9 @@ test.describe("Tokens: Tab", () => {
|
||||||
await valueField.click();
|
await valueField.click();
|
||||||
await valueField.fill("red");
|
await valueField.fill("red");
|
||||||
|
|
||||||
const submitButton = workspacePage.tokensUpdateCreateModal.getByRole(
|
const submitButton = tokensUpdateCreateModal.getByRole("button", {
|
||||||
"button",
|
name: "Save",
|
||||||
{
|
});
|
||||||
name: "Save",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
await expect(submitButton).toBeEnabled();
|
await expect(submitButton).toBeEnabled();
|
||||||
await submitButton.click();
|
await submitButton.click();
|
||||||
|
|
||||||
|
@ -69,7 +73,7 @@ test.describe("Tokens: Tab", () => {
|
||||||
// Create token referencing the previous one with keyboard
|
// Create token referencing the previous one with keyboard
|
||||||
|
|
||||||
await tokensTabPanel.getByTitle("Add token: Color").click();
|
await tokensTabPanel.getByTitle("Add token: Color").click();
|
||||||
await expect(workspacePage.tokensUpdateCreateModal).toBeVisible();
|
await expect(tokensUpdateCreateModal).toBeVisible();
|
||||||
|
|
||||||
await nameField.click();
|
await nameField.click();
|
||||||
await nameField.fill("color.secondary");
|
await nameField.fill("color.secondary");
|
||||||
|
@ -89,14 +93,51 @@ test.describe("Tokens: Tab", () => {
|
||||||
|
|
||||||
// Global set has been auto created and is active
|
// Global set has been auto created and is active
|
||||||
await expect(
|
await expect(
|
||||||
workspacePage.tokenThemesSetsSidebar.getByRole("button", {
|
tokenThemesSetsSidebar.getByRole("button", {
|
||||||
name: "Global",
|
name: "Global",
|
||||||
}),
|
}),
|
||||||
).toHaveCount(1);
|
).toHaveCount(1);
|
||||||
await expect(
|
await expect(
|
||||||
workspacePage.tokenThemesSetsSidebar.getByRole("button", {
|
tokenThemesSetsSidebar.getByRole("button", {
|
||||||
name: "Global",
|
name: "Global",
|
||||||
}),
|
}),
|
||||||
).toHaveAttribute("aria-checked", "true");
|
).toHaveAttribute("aria-checked", "true");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.describe("Tokens: Sets Tab", () => {
|
||||||
|
const createSet = async (sidebar, setName, finalKey = "Enter") => {
|
||||||
|
const tokensTabButton = sidebar
|
||||||
|
.getByRole("button", { name: "Add set" })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
const setInput = sidebar.locator("input:focus");
|
||||||
|
await expect(setInput).toBeVisible();
|
||||||
|
await setInput.fill(setName);
|
||||||
|
await setInput.press(finalKey);
|
||||||
|
};
|
||||||
|
|
||||||
|
test("User creates sets tree structure by entering a set path", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const {
|
||||||
|
workspacePage,
|
||||||
|
tokenThemesSetsSidebar,
|
||||||
|
tokenSetItems,
|
||||||
|
tokenSetGroupItems,
|
||||||
|
} = await setupFileWithTokens(page);
|
||||||
|
|
||||||
|
const tokensTabButton = tokenThemesSetsSidebar
|
||||||
|
.getByRole("button", { name: "Add set" })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await createSet(tokenThemesSetsSidebar, "core/colors/light");
|
||||||
|
await createSet(tokenThemesSetsSidebar, "core/colors/dark");
|
||||||
|
|
||||||
|
// User cancels during editing
|
||||||
|
await createSet(tokenThemesSetsSidebar, "core/colors/dark", "Escape");
|
||||||
|
|
||||||
|
await expect(tokenSetItems).toHaveCount(2);
|
||||||
|
await expect(tokenSetGroupItems).toHaveCount(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -88,20 +88,20 @@
|
||||||
(let [workspace-data (deref refs/workspace-data)]
|
(let [workspace-data (deref refs/workspace-data)]
|
||||||
(get (:tokens workspace-data) id)))
|
(get (:tokens workspace-data) id)))
|
||||||
|
|
||||||
(defn set-selected-token-set-id
|
(defn set-selected-token-set-path
|
||||||
[id]
|
[full-path]
|
||||||
(ptk/reify ::set-selected-token-set-id
|
(ptk/reify ::set-selected-token-set-path
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(wtts/assoc-selected-token-set-id state id))))
|
(wtts/assoc-selected-token-set-path state full-path))))
|
||||||
|
|
||||||
(defn set-selected-token-set-id-from-name
|
(defn set-selected-token-set-path-from-name
|
||||||
[token-set-name]
|
[token-set-name]
|
||||||
(ptk/reify ::set-selected-token-set-id-from-name
|
(ptk/reify ::set-selected-token-set-path-from-name
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(->> (ctob/set-name->set-path-string token-set-name)
|
(->> (ctob/set-name-string->prefixed-set-path-string token-set-name)
|
||||||
(wtts/assoc-selected-token-set-id state)))))
|
(wtts/assoc-selected-token-set-path 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]
|
||||||
|
@ -165,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-from-name (:name new-token-set))
|
(set-selected-token-set-path-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]
|
||||||
|
@ -177,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-from-name (:name token-set))
|
(set-selected-token-set-path-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]}]
|
||||||
|
@ -210,7 +210,7 @@
|
||||||
(ctob/get-sets)
|
(ctob/get-sets)
|
||||||
(first)
|
(first)
|
||||||
(:name)
|
(:name)
|
||||||
(set-selected-token-set-id-from-name))
|
(set-selected-token-set-path-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))]
|
||||||
|
@ -219,14 +219,14 @@
|
||||||
update-token-set-change
|
update-token-set-change
|
||||||
(wtu/update-workspace-tokens))))))
|
(wtu/update-workspace-tokens))))))
|
||||||
|
|
||||||
(defn delete-token-set-path [token-set-path]
|
(defn delete-token-set-path [prefixed-full-set-path]
|
||||||
(ptk/reify ::delete-token-set-path
|
(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-path token-set-path))]
|
(pcb/delete-token-set-path prefixed-full-set-path))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(dch/commit-changes changes)
|
(dch/commit-changes changes)
|
||||||
(wtu/update-workspace-tokens))))))
|
(wtu/update-workspace-tokens))))))
|
||||||
|
@ -276,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-from-name token-set-name)
|
(set-selected-token-set-path-from-name token-set-name)
|
||||||
(dch/commit-changes changes))))))
|
(dch/commit-changes changes))))))
|
||||||
|
|
||||||
(defn delete-token
|
(defn delete-token
|
||||||
|
|
|
@ -490,8 +490,8 @@
|
||||||
(def workspace-token-themes-no-hidden
|
(def workspace-token-themes-no-hidden
|
||||||
(l/derived #(remove ctob/hidden-temporary-theme? %) workspace-token-themes))
|
(l/derived #(remove ctob/hidden-temporary-theme? %) workspace-token-themes))
|
||||||
|
|
||||||
(def workspace-selected-token-set-id
|
(def workspace-selected-token-set-path
|
||||||
(l/derived wtts/get-selected-token-set-id st/state))
|
(l/derived wtts/get-selected-token-set-path st/state))
|
||||||
|
|
||||||
(def workspace-token-set-group-selected?
|
(def workspace-token-set-group-selected?
|
||||||
(l/derived wtts/token-group-selected? st/state))
|
(l/derived wtts/token-group-selected? st/state))
|
||||||
|
|
|
@ -204,10 +204,10 @@
|
||||||
(generic-attribute-actions #{:x} "X" (assoc context-data :on-update-shape wtch/update-shape-position))
|
(generic-attribute-actions #{:x} "X" (assoc context-data :on-update-shape wtch/update-shape-position))
|
||||||
(generic-attribute-actions #{:y} "Y" (assoc context-data :on-update-shape wtch/update-shape-position))))}))
|
(generic-attribute-actions #{:y} "Y" (assoc context-data :on-update-shape wtch/update-shape-position))))}))
|
||||||
|
|
||||||
(defn default-actions [{:keys [token selected-token-set-id]}]
|
(defn default-actions [{:keys [token selected-token-set-path]}]
|
||||||
(let [{:keys [modal]} (wtty/get-token-properties token)]
|
(let [{:keys [modal]} (wtty/get-token-properties token)]
|
||||||
[{:title "Delete Token"
|
[{:title "Delete Token"
|
||||||
:action #(st/emit! (dt/delete-token (ctob/set-path->set-name selected-token-set-id) (:name token)))}
|
:action #(st/emit! (dt/delete-token (ctob/prefixed-set-path-string->set-name-string selected-token-set-path) (:name token)))}
|
||||||
{:title "Duplicate Token"
|
{:title "Duplicate Token"
|
||||||
:action #(st/emit! (dt/duplicate-token (:name token)))}
|
:action #(st/emit! (dt/duplicate-token (:name token)))}
|
||||||
{:title "Edit Token"
|
{:title "Edit Token"
|
||||||
|
@ -220,7 +220,7 @@
|
||||||
:position :right
|
:position :right
|
||||||
:fields fields
|
:fields fields
|
||||||
:action "edit"
|
:action "edit"
|
||||||
:selected-token-set-id selected-token-set-id
|
:selected-token-set-path selected-token-set-path
|
||||||
:token token})))}]))
|
:token token})))}]))
|
||||||
|
|
||||||
(defn selection-actions [{:keys [type token] :as context-data}]
|
(defn selection-actions [{:keys [type token] :as context-data}]
|
||||||
|
@ -311,11 +311,11 @@
|
||||||
selected-shapes (into [] (keep (d/getf objects)) selected)
|
selected-shapes (into [] (keep (d/getf objects)) selected)
|
||||||
token-name (:token-name mdata)
|
token-name (:token-name mdata)
|
||||||
token (mf/deref (refs/workspace-selected-token-set-token token-name))
|
token (mf/deref (refs/workspace-selected-token-set-token token-name))
|
||||||
selected-token-set-id (mf/deref refs/workspace-selected-token-set-id)]
|
selected-token-set-path (mf/deref refs/workspace-selected-token-set-path)]
|
||||||
[:ul {:class (stl/css :context-list)}
|
[:ul {:class (stl/css :context-list)}
|
||||||
[:& menu-tree {:submenu-offset width
|
[:& menu-tree {:submenu-offset width
|
||||||
:token token
|
:token token
|
||||||
:selected-token-set-id selected-token-set-id
|
:selected-token-set-path selected-token-set-path
|
||||||
:selected-shapes selected-shapes}]]))
|
:selected-shapes selected-shapes}]]))
|
||||||
|
|
||||||
(mf/defc token-context-menu
|
(mf/defc token-context-menu
|
||||||
|
|
|
@ -204,7 +204,7 @@ Token names should only contain letters and digits separated by . characters.")}
|
||||||
|
|
||||||
(mf/defc form
|
(mf/defc form
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[{:keys [token token-type action selected-token-set-id]}]
|
[{:keys [token token-type action selected-token-set-path]}]
|
||||||
(let [token (or token {:type token-type})
|
(let [token (or token {:type token-type})
|
||||||
token-properties (wtty/get-token-properties token)
|
token-properties (wtty/get-token-properties token)
|
||||||
color? (wtt/color-token? token)
|
color? (wtt/color-token? token)
|
||||||
|
@ -348,11 +348,11 @@ Token names should only contain letters and digits separated by . characters.")}
|
||||||
(modal/hide!))))))))
|
(modal/hide!))))))))
|
||||||
on-delete-token
|
on-delete-token
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps selected-token-set-id)
|
(mf/deps selected-token-set-path)
|
||||||
(fn [e]
|
(fn [e]
|
||||||
(dom/prevent-default e)
|
(dom/prevent-default e)
|
||||||
(modal/hide!)
|
(modal/hide!)
|
||||||
(st/emit! (dt/delete-token (ctob/set-path->set-name selected-token-set-id) (:name token)))))
|
(st/emit! (dt/delete-token (ctob/prefixed-set-path-string->set-name-string selected-token-set-path) (:name token)))))
|
||||||
|
|
||||||
on-cancel
|
on-cancel
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
(mf/defc token-update-create-modal
|
(mf/defc token-update-create-modal
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[{:keys [x y position token token-type action selected-token-set-id] :as _args}]
|
[{:keys [x y position token token-type action selected-token-set-path] :as _args}]
|
||||||
(let [wrapper-style (use-viewport-position-style x y position)
|
(let [wrapper-style (use-viewport-position-style x y position)
|
||||||
close-modal (mf/use-fn
|
close-modal (mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
:aria-label (tr "labels.close")}]
|
:aria-label (tr "labels.close")}]
|
||||||
[:& form {:token token
|
[:& form {:token token
|
||||||
:action action
|
:action action
|
||||||
:selected-token-set-id selected-token-set-id
|
:selected-token-set-path selected-token-set-path
|
||||||
:token-type token-type}]]))
|
:token-type token-type}]]))
|
||||||
|
|
||||||
;; Modals ----------------------------------------------------------------------
|
;; Modals ----------------------------------------------------------------------
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
(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 [tree-path]
|
(defn on-select-token-set-click [tree-path]
|
||||||
(st/emit! (wdt/set-selected-token-set-id tree-path)))
|
(st/emit! (wdt/set-selected-token-set-path 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)))
|
||||||
|
@ -83,6 +83,7 @@
|
||||||
:tree-path tree-path})))))]
|
:tree-path tree-path})))))]
|
||||||
[:div {;; :ref dref
|
[:div {;; :ref dref
|
||||||
:role "button"
|
:role "button"
|
||||||
|
:data-testid "tokens-set-group-item"
|
||||||
:style {"--tree-depth" tree-depth}
|
:style {"--tree-depth" tree-depth}
|
||||||
:class (stl/css-case :set-item-container true
|
:class (stl/css-case :set-item-container true
|
||||||
:selected-set selected?)
|
:selected-set selected?)
|
||||||
|
@ -133,6 +134,7 @@
|
||||||
:tree-path tree-path})))))]
|
:tree-path tree-path})))))]
|
||||||
[:div {;; :ref dref
|
[:div {;; :ref dref
|
||||||
:role "button"
|
:role "button"
|
||||||
|
:data-testid "tokens-set-item"
|
||||||
:style {"--tree-depth" tree-depth}
|
:style {"--tree-depth" tree-depth}
|
||||||
:class (stl/css-case :set-item-container true
|
:class (stl/css-case :set-item-container true
|
||||||
:selected-set selected?)
|
:selected-set selected?)
|
||||||
|
@ -167,7 +169,7 @@
|
||||||
[{:keys [set-path set-node tree-depth tree-path on-select selected? on-toggle active? editing? on-edit on-edit-reset on-edit-submit]
|
[{: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}
|
:or {tree-depth 0}
|
||||||
:as props}]
|
:as props}]
|
||||||
(let [[set-prefix set-path'] (some-> set-path (ctob/split-set-prefix))
|
(let [[set-prefix set-path'] (some-> set-path (ctob/split-set-str-path-prefix))
|
||||||
set? (instance? ctob/TokenSet set-node)
|
set? (instance? ctob/TokenSet set-node)
|
||||||
set-group? (= ctob/set-group-prefix set-prefix)
|
set-group? (= ctob/set-group-prefix set-prefix)
|
||||||
root? (= tree-depth 0)
|
root? (= tree-depth 0)
|
||||||
|
@ -270,11 +272,11 @@
|
||||||
(mf/defc sets-list
|
(mf/defc sets-list
|
||||||
[{:keys []}]
|
[{:keys []}]
|
||||||
(let [token-sets (mf/deref refs/workspace-token-sets-tree)
|
(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-path (mf/deref refs/workspace-selected-token-set-path)
|
||||||
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-path)
|
||||||
(fn [tree-path]
|
(fn [tree-path]
|
||||||
(= tree-path selected-token-set-id)))
|
(= tree-path selected-token-set-path)))
|
||||||
active-token-set-names (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-names)
|
(mf/deps active-token-set-names)
|
||||||
|
|
|
@ -36,15 +36,15 @@
|
||||||
|
|
||||||
;; === Set selection
|
;; === Set selection
|
||||||
|
|
||||||
(defn get-selected-token-set-id [state]
|
(defn get-selected-token-set-path [state]
|
||||||
(or (get-in state [:workspace-local :selected-token-set-id])
|
(or (get-in state [:workspace-local :selected-token-set-path])
|
||||||
(some-> (get-workspace-tokens-lib state)
|
(some-> (get-workspace-tokens-lib state)
|
||||||
(ctob/get-sets)
|
(ctob/get-sets)
|
||||||
(first)
|
(first)
|
||||||
(ctob/get-set-path))))
|
(ctob/get-set-prefixed-path-string))))
|
||||||
|
|
||||||
(defn get-selected-token-set-node [state]
|
(defn get-selected-token-set-node [state]
|
||||||
(when-let [path (some-> (get-selected-token-set-id state)
|
(when-let [path (some-> (get-selected-token-set-path state)
|
||||||
(ctob/split-token-set-path))]
|
(ctob/split-token-set-path))]
|
||||||
(some-> (get-workspace-tokens-lib state)
|
(some-> (get-workspace-tokens-lib state)
|
||||||
(ctob/get-in-set-tree path))))
|
(ctob/get-in-set-tree path))))
|
||||||
|
@ -66,5 +66,5 @@
|
||||||
(defn token-group-selected? [state]
|
(defn token-group-selected? [state]
|
||||||
(some? (get-selected-token-set-group state)))
|
(some? (get-selected-token-set-group state)))
|
||||||
|
|
||||||
(defn assoc-selected-token-set-id [state id]
|
(defn assoc-selected-token-set-path [state id]
|
||||||
(assoc-in state [:workspace-local :selected-token-set-id] id))
|
(assoc-in state [:workspace-local :selected-token-set-path] id))
|
||||||
|
|
Loading…
Add table
Reference in a new issue