mirror of
https://github.com/penpot/penpot.git
synced 2026-09-08 13:09:22 +00:00
🎉 Display autocomplete combobox on token creation (#9109)
Co-authored-by: Eva Marco <evamarcod@gmail.com>
This commit is contained in:
parent
e65ce8bdeb
commit
0ea3ea332f
@ -554,10 +554,17 @@
|
|||||||
:opacity [:opacity]
|
:opacity [:opacity]
|
||||||
:stroke-width [:stroke-width :dimensions]
|
:stroke-width [:stroke-width :dimensions]
|
||||||
:font-size [:font-size]
|
:font-size [:font-size]
|
||||||
|
:font-weight [:font-weight]
|
||||||
|
:text-decoration [:text-decoration]
|
||||||
|
:text-case [:text-case]
|
||||||
:letter-spacing [:letter-spacing]
|
:letter-spacing [:letter-spacing]
|
||||||
|
:dimensions [:dimensions]
|
||||||
:fill [:color]
|
:fill [:color]
|
||||||
:stroke-color [:color]
|
:stroke-color [:color]
|
||||||
:typography [:typography]})
|
:typography [:typography]
|
||||||
|
:number [:number]
|
||||||
|
:sizing [:sizing :dimensions]
|
||||||
|
:spacing [:spacing :dimensions]})
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; HELPERS for tokens application
|
;; HELPERS for tokens application
|
||||||
|
|||||||
@ -1386,8 +1386,14 @@ test.describe("Numeric Input and Token Integration Tests", () => {
|
|||||||
flags: ["enable-token-combobox", "enable-feature-token-input"],
|
flags: ["enable-token-combobox", "enable-feature-token-input"],
|
||||||
});
|
});
|
||||||
// Create a token with a reference value in other set.
|
// Create a token with a reference value in other set.
|
||||||
await createToken(page, "Dimensions", "reference-token", "Value", "{card.padding}");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Dimensions",
|
||||||
|
"reference-token",
|
||||||
|
"Value",
|
||||||
|
"combobox",
|
||||||
|
"{card.padding}",
|
||||||
|
);
|
||||||
|
|
||||||
// Apply this token to a shape
|
// Apply this token to a shape
|
||||||
await page.getByRole("tab", { name: "Layers" }).click();
|
await page.getByRole("tab", { name: "Layers" }).click();
|
||||||
@ -1410,11 +1416,16 @@ test.describe("Numeric Input and Token Integration Tests", () => {
|
|||||||
});
|
});
|
||||||
await expect(measuresSection).toBeVisible();
|
await expect(measuresSection).toBeVisible();
|
||||||
|
|
||||||
await expect(measuresSection.getByRole('button', { name: 'reference-token' })).toBeVisible();
|
await expect(
|
||||||
|
measuresSection.getByRole("button", { name: "reference-token" }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
// Deactivate token set where reference token exist to make token broken
|
// Deactivate token set where reference token exist to make token broken
|
||||||
await tokenThemesSetsSidebar.getByRole('button', { name: 'theme' }).getByRole('checkbox').click();
|
await tokenThemesSetsSidebar
|
||||||
|
.getByRole("button", { name: "theme" })
|
||||||
|
.getByRole("checkbox")
|
||||||
|
.click();
|
||||||
|
|
||||||
// Check if token pill show broken reference state
|
// Check if token pill show broken reference state
|
||||||
const brokenPill = measuresSection.getByRole("button", {
|
const brokenPill = measuresSection.getByRole("button", {
|
||||||
name: "is not in any active set",
|
name: "is not in any active set",
|
||||||
|
|||||||
@ -1794,22 +1794,33 @@ test("User duplicate color token", async ({ page }) => {
|
|||||||
test("User disables the current set but token still have resolved values shown in the sidebar", async ({
|
test("User disables the current set but token still have resolved values shown in the sidebar", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
const { tokenThemesSetsSidebar, tokensSidebar } = await setupEmptyTokensFileRender(page);
|
const { tokenThemesSetsSidebar, tokensSidebar } =
|
||||||
|
await setupEmptyTokensFileRender(page);
|
||||||
|
|
||||||
// Create color token
|
// Create color token
|
||||||
await createToken(page, "Color", "color.primary", "Value", "#ff0000");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Color",
|
||||||
|
"color.primary",
|
||||||
|
"Value",
|
||||||
|
"textbox",
|
||||||
|
"#ff0000",
|
||||||
|
);
|
||||||
await unfoldTokenType(tokensSidebar, "color");
|
await unfoldTokenType(tokensSidebar, "color");
|
||||||
|
|
||||||
// Deactivate current set
|
// Deactivate current set
|
||||||
await tokenThemesSetsSidebar
|
await tokenThemesSetsSidebar.getByRole("checkbox").click();
|
||||||
.getByRole("checkbox")
|
|
||||||
.click();
|
|
||||||
|
|
||||||
// Tokens tab panel should have a token with the color #ff0000 and correct resolved value in the tooltip
|
// Tokens tab panel should have a token with the color #ff0000 and correct resolved value in the tooltip
|
||||||
const colorTokenPill = tokensSidebar.getByRole("button", { name: "#ff0000 color.primary" });
|
const colorTokenPill = tokensSidebar.getByRole("button", {
|
||||||
|
name: "#ff0000 color.primary",
|
||||||
|
});
|
||||||
await expect(colorTokenPill).toHaveCount(1);
|
await expect(colorTokenPill).toHaveCount(1);
|
||||||
await colorTokenPill.hover(); // Force title attribute to be attached to the button
|
await colorTokenPill.hover(); // Force title attribute to be attached to the button
|
||||||
await expect(colorTokenPill).toHaveAttribute("title", /Resolved value: #ff0000/);
|
await expect(colorTokenPill).toHaveAttribute(
|
||||||
|
"title",
|
||||||
|
/Resolved value: #ff0000/,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe("Tokens tab - edition", () => {
|
test.describe("Tokens tab - edition", () => {
|
||||||
|
|||||||
@ -332,7 +332,26 @@ const unfoldTokenType = async (tokensTabPanel, type) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createToken = async (page, type, name, textFieldName, value) => {
|
/**
|
||||||
|
* Creates a token from the Tokens sidebar modal.
|
||||||
|
*
|
||||||
|
* @param {import("@playwright/test").Page} page - Playwright page instance.
|
||||||
|
* @param {string} type - Token category label shown in UI (e.g. "Color", "Typography", "Shadow").
|
||||||
|
* @param {string} name - Token name to create.
|
||||||
|
* @param {string} textFieldName - Accessible label of the value textbox in the modal (e.g. "Value", "Color", "Font size").
|
||||||
|
* @param {"textbox" | "combobox"} textFieldType - Type of the token value field, wether it's a simple text field or a combo box, to properly fill the value.
|
||||||
|
* @param {string} value - Token value to set in the modal.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const createToken = async (
|
||||||
|
page,
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
textFieldName,
|
||||||
|
textFieldType,
|
||||||
|
value,
|
||||||
|
) => {
|
||||||
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
||||||
|
|
||||||
const { tokensUpdateCreateModal } = await setupTokensFileRender(page, {
|
const { tokensUpdateCreateModal } = await setupTokensFileRender(page, {
|
||||||
@ -348,7 +367,7 @@ const createToken = async (page, type, name, textFieldName, value) => {
|
|||||||
const nameField = tokensUpdateCreateModal.getByLabel("Name");
|
const nameField = tokensUpdateCreateModal.getByLabel("Name");
|
||||||
await nameField.fill(name);
|
await nameField.fill(name);
|
||||||
|
|
||||||
const colorField = tokensUpdateCreateModal.getByRole("textbox", {
|
const colorField = tokensUpdateCreateModal.getByRole(textFieldType, {
|
||||||
name: textFieldName,
|
name: textFieldName,
|
||||||
});
|
});
|
||||||
await colorField.fill(value);
|
await colorField.fill(value);
|
||||||
|
|||||||
@ -106,7 +106,14 @@ test.describe("Remapping a single token", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create base shadow token
|
// Create base shadow token
|
||||||
await createToken(page, "Shadow", "base-shadow", "Color", "#000000");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Shadow",
|
||||||
|
"base-shadow",
|
||||||
|
"Color",
|
||||||
|
"textbox",
|
||||||
|
"#000000",
|
||||||
|
);
|
||||||
|
|
||||||
// Create derived shadow token that references base-shadow
|
// Create derived shadow token that references base-shadow
|
||||||
await createCompositeDerivedToken(
|
await createCompositeDerivedToken(
|
||||||
@ -150,7 +157,14 @@ test.describe("Remapping a single token", () => {
|
|||||||
} = await setupTokensFileRender(page, { flags: ["enable-token-shadow"] });
|
} = await setupTokensFileRender(page, { flags: ["enable-token-shadow"] });
|
||||||
|
|
||||||
// Create base shadow token
|
// Create base shadow token
|
||||||
await createToken(page, "Shadow", "primary-shadow", "Color", "#000000");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Shadow",
|
||||||
|
"primary-shadow",
|
||||||
|
"Color",
|
||||||
|
"textbox",
|
||||||
|
"#000000",
|
||||||
|
);
|
||||||
|
|
||||||
// Create derived shadow token that references base
|
// Create derived shadow token that references base
|
||||||
await createCompositeDerivedToken(
|
await createCompositeDerivedToken(
|
||||||
@ -257,7 +271,14 @@ test.describe("Remapping a single token", () => {
|
|||||||
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
||||||
|
|
||||||
// Create base typography token
|
// Create base typography token
|
||||||
await createToken(page, "Typography", "base-text", "Font size", "16");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Typography",
|
||||||
|
"base-text",
|
||||||
|
"Font size",
|
||||||
|
"textbox",
|
||||||
|
"16",
|
||||||
|
);
|
||||||
|
|
||||||
// Create derived typography token
|
// Create derived typography token
|
||||||
await createCompositeDerivedToken(
|
await createCompositeDerivedToken(
|
||||||
@ -301,7 +322,14 @@ test.describe("Remapping a single token", () => {
|
|||||||
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
const tokensTabPanel = page.getByRole("tabpanel", { name: "tokens" });
|
||||||
|
|
||||||
// Create base typography token
|
// Create base typography token
|
||||||
await createToken(page, "Typography", "body-style", "Font size", "16");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Typography",
|
||||||
|
"body-style",
|
||||||
|
"Font size",
|
||||||
|
"textbox",
|
||||||
|
"16",
|
||||||
|
);
|
||||||
|
|
||||||
// Create derived typography token
|
// Create derived typography token
|
||||||
await tokensTabPanel
|
await tokensTabPanel
|
||||||
@ -536,7 +564,14 @@ test.describe("Remapping a single token", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create base shadow token
|
// Create base shadow token
|
||||||
await createToken(page, "Shadow", "base-shadow", "Color", "#000000");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Shadow",
|
||||||
|
"base-shadow",
|
||||||
|
"Color",
|
||||||
|
"textbox",
|
||||||
|
"#000000",
|
||||||
|
);
|
||||||
|
|
||||||
// Create derived shadow token that references base-shadow
|
// Create derived shadow token that references base-shadow
|
||||||
await createCompositeDerivedToken(
|
await createCompositeDerivedToken(
|
||||||
@ -575,7 +610,14 @@ test.describe("Remapping a single token", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create base shadow token
|
// Create base shadow token
|
||||||
await createToken(page, "Shadow", "base-shadow", "Color", "#000000");
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Shadow",
|
||||||
|
"base-shadow",
|
||||||
|
"Color",
|
||||||
|
"textbox",
|
||||||
|
"#000000",
|
||||||
|
);
|
||||||
|
|
||||||
// Create derived shadow token that references base-shadow
|
// Create derived shadow token that references base-shadow
|
||||||
await createCompositeDerivedToken(
|
await createCompositeDerivedToken(
|
||||||
@ -615,8 +657,22 @@ test.describe("Remapping group of tokens", () => {
|
|||||||
const rightSidebar = workspacePage.rightSidebar;
|
const rightSidebar = workspacePage.rightSidebar;
|
||||||
|
|
||||||
// Create multiple tokens in a group
|
// Create multiple tokens in a group
|
||||||
await createToken(page, "Color", "light.primary", "Value", "#FFFFFF");
|
await createToken(
|
||||||
await createToken(page, "Color", "light.secondary", "Value", "#EEEEEE");
|
page,
|
||||||
|
"Color",
|
||||||
|
"light.primary",
|
||||||
|
"Value",
|
||||||
|
"textbox",
|
||||||
|
"#FFFFFF",
|
||||||
|
);
|
||||||
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Color",
|
||||||
|
"light.secondary",
|
||||||
|
"Value",
|
||||||
|
"textbox",
|
||||||
|
"#EEEEEE",
|
||||||
|
);
|
||||||
|
|
||||||
// Verify that the node and child token are visible before deletion
|
// Verify that the node and child token are visible before deletion
|
||||||
const lightNode = tokensSidebar.getByRole("button", {
|
const lightNode = tokensSidebar.getByRole("button", {
|
||||||
@ -687,7 +743,9 @@ test.describe("Remapping group of tokens", () => {
|
|||||||
await expect(lighterNode).toBeVisible();
|
await expect(lighterNode).toBeVisible();
|
||||||
|
|
||||||
// Verify that the applied token reference has been updated in the right sidebar for the selected shape
|
// Verify that the applied token reference has been updated in the right sidebar for the selected shape
|
||||||
const fillSection = rightSidebar.getByRole("region", { name: "Fill section" });
|
const fillSection = rightSidebar.getByRole("region", {
|
||||||
|
name: "Fill section",
|
||||||
|
});
|
||||||
await expect(fillSection).toBeVisible();
|
await expect(fillSection).toBeVisible();
|
||||||
|
|
||||||
const tokenReference = fillSection.getByLabel("lighter.primary", {
|
const tokenReference = fillSection.getByLabel("lighter.primary", {
|
||||||
|
|||||||
@ -32,8 +32,22 @@ test.describe("Tokens - node tree", () => {
|
|||||||
const { tokensSidebar } = await setupTokensFileRender(page);
|
const { tokensSidebar } = await setupTokensFileRender(page);
|
||||||
|
|
||||||
// Create multiple tokens in a group
|
// Create multiple tokens in a group
|
||||||
await createToken(page, "Color", "dark.primary", "Value", "#000000");
|
await createToken(
|
||||||
await createToken(page, "Color", "dark.secondary", "Value", "#111111");
|
page,
|
||||||
|
"Color",
|
||||||
|
"dark.primary",
|
||||||
|
"Value",
|
||||||
|
"textbox",
|
||||||
|
"#000000",
|
||||||
|
);
|
||||||
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Color",
|
||||||
|
"dark.secondary",
|
||||||
|
"Value",
|
||||||
|
"textbox",
|
||||||
|
"#111111",
|
||||||
|
);
|
||||||
|
|
||||||
// Verify that the node and child token are visible before deletion
|
// Verify that the node and child token are visible before deletion
|
||||||
const darkNode = tokensSidebar.getByRole("button", {
|
const darkNode = tokensSidebar.getByRole("button", {
|
||||||
@ -88,8 +102,22 @@ test.describe("Tokens - node tree", () => {
|
|||||||
const { tokensSidebar } = await setupTokensFileRender(page);
|
const { tokensSidebar } = await setupTokensFileRender(page);
|
||||||
|
|
||||||
// Create multiple tokens in a group
|
// Create multiple tokens in a group
|
||||||
await createToken(page, "Color", "dark.primary", "Value", "#000000");
|
await createToken(
|
||||||
await createToken(page, "Color", "dark.secondary", "Value", "#111111");
|
page,
|
||||||
|
"Color",
|
||||||
|
"dark.primary",
|
||||||
|
"Value",
|
||||||
|
"textbox",
|
||||||
|
"#000000",
|
||||||
|
);
|
||||||
|
await createToken(
|
||||||
|
page,
|
||||||
|
"Color",
|
||||||
|
"dark.secondary",
|
||||||
|
"Value",
|
||||||
|
"textbox",
|
||||||
|
"#111111",
|
||||||
|
);
|
||||||
|
|
||||||
// Verify that the node and child token are visible before deletion
|
// Verify that the node and child token are visible before deletion
|
||||||
const darkNode = tokensSidebar.getByRole("button", {
|
const darkNode = tokensSidebar.getByRole("button", {
|
||||||
|
|||||||
@ -25,8 +25,8 @@
|
|||||||
grid-auto-rows: auto;
|
grid-auto-rows: auto;
|
||||||
gap: var(--sp-s);
|
gap: var(--sp-s);
|
||||||
width: $sz-500;
|
width: $sz-500;
|
||||||
margin-block: var(--sp-xxxl) $sz-120; /* FIXME: this should be a proper token */
|
|
||||||
padding-block-start: var(--sp-xxxl);
|
padding-block-start: var(--sp-xxxl);
|
||||||
|
margin: var(--sp-xxxl) $sz-120; /* FIXME: this should be a proper token */
|
||||||
border-block-start: $b-1 solid var(--color-background-quaternary);
|
border-block-start: $b-1 solid var(--color-background-quaternary);
|
||||||
color: var(--color-foreground-primary);
|
color: var(--color-foreground-primary);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -389,6 +389,10 @@
|
|||||||
resolved-active-tokens
|
resolved-active-tokens
|
||||||
(sd/use-resolved-tokens* active-tokens)
|
(sd/use-resolved-tokens* active-tokens)
|
||||||
|
|
||||||
|
tokenscript-resolved-active-tokens
|
||||||
|
(mf/with-memo [active-tokens tokenscript?]
|
||||||
|
(when tokenscript? (ts/resolve-tokens active-tokens)))
|
||||||
|
|
||||||
tokenscript-resolved-active-tokens-force-set
|
tokenscript-resolved-active-tokens-force-set
|
||||||
(mf/with-memo [active-tokens-force-set tokenscript?]
|
(mf/with-memo [active-tokens-force-set tokenscript?]
|
||||||
(when tokenscript? (ts/resolve-tokens active-tokens-force-set)))
|
(when tokenscript? (ts/resolve-tokens active-tokens-force-set)))
|
||||||
@ -415,4 +419,6 @@
|
|||||||
:file-id file-id
|
:file-id file-id
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:tokens-lib tokens-lib
|
:tokens-lib tokens-lib
|
||||||
:active-tokens resolved-active-tokens}]]))
|
:active-tokens (if tokenscript?
|
||||||
|
tokenscript-resolved-active-tokens
|
||||||
|
resolved-active-tokens)}]]))
|
||||||
|
|||||||
@ -99,11 +99,10 @@
|
|||||||
|
|
||||||
container (hooks/use-portal-container)
|
container (hooks/use-portal-container)
|
||||||
|
|
||||||
raw-tokens-by-type (mf/use-ctx muc/active-tokens-by-type)
|
resolved-tokens-by-type (mf/use-ctx muc/active-tokens-by-type)
|
||||||
|
|
||||||
filtered-tokens-by-type
|
filtered-tokens-by-type
|
||||||
(mf/with-memo [raw-tokens-by-type token-type]
|
(mf/with-memo [resolved-tokens-by-type token-type]
|
||||||
(csu/filter-tokens-for-input raw-tokens-by-type token-type))
|
(csu/filter-tokens-for-input resolved-tokens-by-type token-type))
|
||||||
|
|
||||||
visible-options
|
visible-options
|
||||||
(mf/with-memo [filtered-tokens-by-type token]
|
(mf/with-memo [filtered-tokens-by-type token]
|
||||||
|
|||||||
@ -35,13 +35,32 @@
|
|||||||
(mf/with-memo [token-path tokens-in-selected-set]
|
(mf/with-memo [token-path tokens-in-selected-set]
|
||||||
(-> (ctob/tokens-tree tokens-in-selected-set)
|
(-> (ctob/tokens-tree tokens-in-selected-set)
|
||||||
(d/dissoc-in token-path)))
|
(d/dissoc-in token-path)))
|
||||||
|
|
||||||
props
|
props
|
||||||
(mf/spread-props props {:token-type token-type
|
(if (contains? cf/flags :token-combobox)
|
||||||
:tokens-tree-in-selected-set tokens-tree-in-selected-set
|
(mf/spread-props props {:token-type token-type
|
||||||
:token token})
|
:tokens-tree-in-selected-set tokens-tree-in-selected-set
|
||||||
text-case-props (mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-case-value-enter")})
|
:selected-token-set-id (mf/deref refs/selected-token-set-id)
|
||||||
text-decoration-props (mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-decoration-value-enter")})
|
:token token
|
||||||
font-weight-props (mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.font-weight-value-enter")})
|
:input-component token.controls/value-combobox*})
|
||||||
|
(mf/spread-props props {:token-type token-type
|
||||||
|
:tokens-tree-in-selected-set tokens-tree-in-selected-set
|
||||||
|
:selected-token-set-id (mf/deref refs/selected-token-set-id)
|
||||||
|
:token token}))
|
||||||
|
text-case-props (if (contains? cf/flags :token-combobox)
|
||||||
|
(mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-case-value-enter")
|
||||||
|
:input-component token.controls/value-combobox*})
|
||||||
|
(mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-case-value-enter")}))
|
||||||
|
text-decoration-props (if (contains? cf/flags :token-combobox)
|
||||||
|
(mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-decoration-value-enter")
|
||||||
|
:input-component token.controls/value-combobox*})
|
||||||
|
(mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-decoration-value-enter")}))
|
||||||
|
|
||||||
|
font-weight-props (if (contains? cf/flags :token-combobox)
|
||||||
|
(mf/spread-props props {:input-component token.controls/value-combobox*
|
||||||
|
:input-value-placeholder (tr "workspace.tokens.font-weight-value-enter")})
|
||||||
|
(mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.font-weight-value-enter")}))
|
||||||
|
|
||||||
border-radius-props (if (contains? cf/flags :token-combobox)
|
border-radius-props (if (contains? cf/flags :token-combobox)
|
||||||
(mf/spread-props props {:input-component token.controls/value-combobox*})
|
(mf/spread-props props {:input-component token.controls/value-combobox*})
|
||||||
props)]
|
props)]
|
||||||
@ -55,4 +74,4 @@
|
|||||||
:text-decoration [:> generic/form* text-decoration-props]
|
:text-decoration [:> generic/form* text-decoration-props]
|
||||||
:font-weight [:> generic/form* font-weight-props]
|
:font-weight [:> generic/form* font-weight-props]
|
||||||
:border-radius [:> generic/form* border-radius-props]
|
:border-radius [:> generic/form* border-radius-props]
|
||||||
[:> generic/form* props])))
|
[:> generic/form* props])))
|
||||||
|
|||||||
@ -10,9 +10,12 @@
|
|||||||
[app.common.files.tokens :as cfo]
|
[app.common.files.tokens :as cfo]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.types.tokens-lib :as ctob]
|
[app.common.types.tokens-lib :as ctob]
|
||||||
|
[app.config :as cf]
|
||||||
[app.main.constants :refer [max-input-length]]
|
[app.main.constants :refer [max-input-length]]
|
||||||
[app.main.data.helpers :as dh]
|
[app.main.data.helpers :as dh]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.style-dictionary :as sd]
|
||||||
|
[app.main.data.tokenscript :as ts]
|
||||||
[app.main.data.workspace.tokens.application :as dwta]
|
[app.main.data.workspace.tokens.application :as dwta]
|
||||||
[app.main.data.workspace.tokens.errors :as wte]
|
[app.main.data.workspace.tokens.errors :as wte]
|
||||||
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||||
@ -83,23 +86,41 @@
|
|||||||
|
|
||||||
token-title (str/lower (:title token-properties))
|
token-title (str/lower (:title token-properties))
|
||||||
|
|
||||||
tokens (mf/deref refs/workspace-all-tokens-map)
|
;; All tokens in the lib, as a map name -> token, flattened
|
||||||
|
;; including tokens in inactive sets.
|
||||||
|
tokens-tree (mf/deref refs/workspace-all-tokens-map)
|
||||||
|
|
||||||
|
;; A map name -> token, tokens only in actual set.
|
||||||
tokens-in-selected-set
|
tokens-in-selected-set
|
||||||
(mf/deref refs/workspace-all-tokens-in-selected-set)
|
(mf/deref refs/workspace-all-tokens-in-selected-set)
|
||||||
|
|
||||||
|
;; Make actual set tokens take precedence over tokens in other sets.
|
||||||
tokens
|
tokens
|
||||||
(mf/with-memo [tokens tokens-in-selected-set token]
|
(mf/with-memo [tokens-tree tokens-in-selected-set token]
|
||||||
;; Ensure that the resolved value uses the currently editing token
|
;; Ensure that the resolved value uses the currently editing token
|
||||||
;; even if the name has been overriden by a token with the same name
|
;; even if the name has been overriden by a token with the same name
|
||||||
;; in another set below.
|
;; in another set below.
|
||||||
(cond-> (merge tokens tokens-in-selected-set)
|
(cond-> (merge tokens-tree tokens-in-selected-set)
|
||||||
(and (:name token) (:value token))
|
(and (:name token) (:value token))
|
||||||
(assoc (:name token) token)))
|
(assoc (:name token) token)))
|
||||||
|
|
||||||
|
tokenscript? (contains? cf/flags :tokenscript)
|
||||||
|
|
||||||
|
;; A map name-> token with resolved-values, resolved with style dictionary
|
||||||
|
resolved-active-tokens
|
||||||
|
(sd/use-resolved-tokens* tokens-tree)
|
||||||
|
|
||||||
|
;; A map name-> token with resolved-values, resolved with tokescript
|
||||||
|
tokenscript-resolved-active-tokens
|
||||||
|
(mf/with-memo [tokens-tree tokenscript?]
|
||||||
|
(when tokenscript? (ts/resolve-tokens tokens-tree)))
|
||||||
|
|
||||||
|
;; A map which keys are token types and values are vectors of tokens of that type, with resolved values.
|
||||||
active-tokens-by-type
|
active-tokens-by-type
|
||||||
(mf/with-memo [tokens]
|
(mf/with-memo [resolved-active-tokens tokenscript-resolved-active-tokens tokenscript?]
|
||||||
(delay (ctob/group-by-type tokens)))
|
(delay (ctob/group-by-type (if tokenscript?
|
||||||
|
tokenscript-resolved-active-tokens
|
||||||
|
resolved-active-tokens))))
|
||||||
|
|
||||||
schema
|
schema
|
||||||
(mf/with-memo [tokens-tree-in-selected-set active-tab]
|
(mf/with-memo [tokens-tree-in-selected-set active-tab]
|
||||||
|
|||||||
@ -118,27 +118,15 @@
|
|||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
(mf/defc color-modal
|
|
||||||
{::mf/register modal/components
|
|
||||||
::mf/register-as :tokens/color}
|
|
||||||
[properties]
|
|
||||||
[:& token-update-create-modal properties])
|
|
||||||
|
|
||||||
(mf/defc stroke-width-modal
|
|
||||||
{::mf/register modal/components
|
|
||||||
::mf/register-as :tokens/stroke-width}
|
|
||||||
[properties]
|
|
||||||
[:& token-update-create-modal properties])
|
|
||||||
|
|
||||||
(mf/defc box-shadow-modal
|
(mf/defc box-shadow-modal
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :tokens/shadow}
|
::mf/register-as :tokens/shadow}
|
||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
(mf/defc sizing-modal
|
(mf/defc color-modal
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :tokens/sizing}
|
::mf/register-as :tokens/color}
|
||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
@ -148,6 +136,30 @@
|
|||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
|
(mf/defc font-familiy-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/font-family}
|
||||||
|
[properties]
|
||||||
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
|
(mf/defc font-size-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/font-size}
|
||||||
|
[properties]
|
||||||
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
|
(mf/defc font-weight-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/font-weight}
|
||||||
|
[properties]
|
||||||
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
|
(mf/defc letter-spacing-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/letter-spacing}
|
||||||
|
[properties]
|
||||||
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
(mf/defc number-modal
|
(mf/defc number-modal
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :tokens/number}
|
::mf/register-as :tokens/number}
|
||||||
@ -172,6 +184,12 @@
|
|||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
|
(mf/defc sizing-modal
|
||||||
|
{::mf/register modal/components
|
||||||
|
::mf/register-as :tokens/sizing}
|
||||||
|
[properties]
|
||||||
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
(mf/defc spacing-modal
|
(mf/defc spacing-modal
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :tokens/spacing}
|
::mf/register-as :tokens/spacing}
|
||||||
@ -184,27 +202,9 @@
|
|||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
(mf/defc typography-modal
|
(mf/defc stroke-width-modal
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :tokens/typography}
|
::mf/register-as :tokens/stroke-width}
|
||||||
[properties]
|
|
||||||
[:& token-update-create-modal properties])
|
|
||||||
|
|
||||||
(mf/defc font-size-modal
|
|
||||||
{::mf/register modal/components
|
|
||||||
::mf/register-as :tokens/font-size}
|
|
||||||
[properties]
|
|
||||||
[:& token-update-create-modal properties])
|
|
||||||
|
|
||||||
(mf/defc letter-spacing-modal
|
|
||||||
{::mf/register modal/components
|
|
||||||
::mf/register-as :tokens/letter-spacing}
|
|
||||||
[properties]
|
|
||||||
[:& token-update-create-modal properties])
|
|
||||||
|
|
||||||
(mf/defc font-familiy-modal
|
|
||||||
{::mf/register modal/components
|
|
||||||
::mf/register-as :tokens/font-family}
|
|
||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
@ -220,8 +220,8 @@
|
|||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|
||||||
(mf/defc font-weight-modal
|
(mf/defc typography-modal
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :tokens/font-weight}
|
::mf/register-as :tokens/typography}
|
||||||
[properties]
|
[properties]
|
||||||
[:& token-update-create-modal properties])
|
[:& token-update-create-modal properties])
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user