mirror of
https://github.com/penpot/penpot.git
synced 2026-01-20 20:32:22 -05:00
Compare commits
6 Commits
eva-replac
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
079b3fbfad | ||
|
|
299f628951 | ||
|
|
32d0fe6463 | ||
|
|
cecd3d4a90 | ||
|
|
1c2c0987f5 | ||
|
|
0418147e74 |
2
.github/workflows/build-bundle.yml
vendored
2
.github/workflows/build-bundle.yml
vendored
@@ -40,7 +40,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build-bundle:
|
build-bundle:
|
||||||
name: Build and Upload Penpot Bundle
|
name: Build and Upload Penpot Bundle
|
||||||
runs-on: ubuntu-24.04
|
runs-on: penpot-runner-01
|
||||||
env:
|
env:
|
||||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
- Fix wrong register image [Taiga #12955](https://tree.taiga.io/project/penpot/task/12955)
|
- Fix wrong register image [Taiga #12955](https://tree.taiga.io/project/penpot/task/12955)
|
||||||
- Fix error message on components doesn't close automatically [Taiga #12012](https://tree.taiga.io/project/penpot/issue/12012)
|
- Fix error message on components doesn't close automatically [Taiga #12012](https://tree.taiga.io/project/penpot/issue/12012)
|
||||||
- Fix incorrect default option on tokens import dialog [Github #8051](https://github.com/penpot/penpot/pull/8051)
|
- Fix incorrect default option on tokens import dialog [Github #8051](https://github.com/penpot/penpot/pull/8051)
|
||||||
|
- Fix unhandled exception tokens creation dialog [Github #8110](https://github.com/penpot/penpot/issues/8110)
|
||||||
|
|
||||||
## 2.13.0 (Unreleased)
|
## 2.13.0 (Unreleased)
|
||||||
|
|
||||||
|
|||||||
@@ -474,8 +474,8 @@
|
|||||||
:height #{:sizing :dimensions}
|
:height #{:sizing :dimensions}
|
||||||
:max-width #{:sizing :dimensions}
|
:max-width #{:sizing :dimensions}
|
||||||
:max-height #{:sizing :dimensions}
|
:max-height #{:sizing :dimensions}
|
||||||
:x #{:dimensions}
|
:x #{:spacing :dimensions}
|
||||||
:y #{:dimensions}
|
:y #{:spacing :dimensions}
|
||||||
:rotation #{:number :rotation}
|
:rotation #{:number :rotation}
|
||||||
:border-radius #{:border-radius :dimensions}
|
:border-radius #{:border-radius :dimensions}
|
||||||
:row-gap #{:spacing :dimensions}
|
:row-gap #{:spacing :dimensions}
|
||||||
@@ -488,7 +488,6 @@
|
|||||||
:sided-margins #{:spacing :dimensions}
|
:sided-margins #{:spacing :dimensions}
|
||||||
:line-height #{:line-height :number}
|
:line-height #{:line-height :number}
|
||||||
:opacity #{:opacity}
|
:opacity #{:opacity}
|
||||||
:stroke-width #{:stroke-width}
|
|
||||||
:font-size #{:font-size}
|
:font-size #{:font-size}
|
||||||
:letter-spacing #{:letter-spacing}
|
:letter-spacing #{:letter-spacing}
|
||||||
:fill #{:color}
|
:fill #{:color}
|
||||||
|
|||||||
@@ -149,14 +149,12 @@ test.describe("Tokens: Apply token", () => {
|
|||||||
await detachButton.click();
|
await detachButton.click();
|
||||||
|
|
||||||
// Open dropdown from input
|
// Open dropdown from input
|
||||||
const dropdownBtn = layerMenuSection.getByLabel("Open token list");
|
const dropdownBtn = layerMenuSection.getByLabel('Open token list');
|
||||||
await expect(dropdownBtn).toBeVisible();
|
await expect(dropdownBtn).toBeVisible();
|
||||||
await dropdownBtn.click();
|
await dropdownBtn.click();
|
||||||
|
|
||||||
// Change token from dropdown
|
// Change token from dropdown
|
||||||
const opacityLowOption = layerMenuSection.getByRole("option", {
|
const opacityLowOption = layerMenuSection.getByRole('option', { name: 'opacity.low' });
|
||||||
name: "opacity.low",
|
|
||||||
});
|
|
||||||
await expect(opacityLowOption).toBeVisible();
|
await expect(opacityLowOption).toBeVisible();
|
||||||
await opacityLowOption.click();
|
await opacityLowOption.click();
|
||||||
|
|
||||||
@@ -484,219 +482,4 @@ test.describe("Tokens: Apply token", () => {
|
|||||||
await expect(shadowSection).toHaveCount(2);
|
await expect(shadowSection).toHaveCount(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("User applies dimension token to a shape on width and height", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
|
||||||
await setupTokensFile(page);
|
|
||||||
|
|
||||||
// Unfolds dimensions on token panel
|
|
||||||
await page.getByRole("tab", { name: "Layers" }).click();
|
|
||||||
|
|
||||||
await workspacePage.layers.getByTestId("layer-row").nth(1).click();
|
|
||||||
|
|
||||||
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
|
||||||
await tokensTabButton.click();
|
|
||||||
|
|
||||||
unfoldTokenTree(tokensSidebar, "dimensions", "dimension.dimension.sm");
|
|
||||||
|
|
||||||
// Apply token to width and height token from token panel
|
|
||||||
await tokensSidebar.getByRole("button", { name: "dimension.sm" }).click();
|
|
||||||
|
|
||||||
// Check if measures sections is visible on right sidebar
|
|
||||||
const measuresSection = page.getByRole("region", {
|
|
||||||
name: "shape-measures-section",
|
|
||||||
});
|
|
||||||
await expect(measuresSection).toBeVisible();
|
|
||||||
|
|
||||||
// Check if token pill is visible on design tab on right sidebar
|
|
||||||
const dimensionSMTokenPill = measuresSection.getByRole("button", {
|
|
||||||
name: "dimension.sm",
|
|
||||||
});
|
|
||||||
await expect(dimensionSMTokenPill).toHaveCount(2);
|
|
||||||
await dimensionSMTokenPill.nth(1).click();
|
|
||||||
|
|
||||||
// Change token from dropdown
|
|
||||||
const dimensionTokenOptionXl = measuresSection.getByLabel("dimension.xl");
|
|
||||||
await expect(dimensionTokenOptionXl).toBeVisible();
|
|
||||||
await dimensionTokenOptionXl.click();
|
|
||||||
|
|
||||||
await expect(dimensionSMTokenPill).toHaveCount(1);
|
|
||||||
const dimensionXLTokenPill = measuresSection.getByRole("button", {
|
|
||||||
name: "dimension.xl",
|
|
||||||
});
|
|
||||||
await expect(dimensionXLTokenPill).toBeVisible();
|
|
||||||
|
|
||||||
// Detach token from design tab on right sidebar
|
|
||||||
const detachButton = measuresSection.getByRole("button", {
|
|
||||||
name: "Detach token",
|
|
||||||
});
|
|
||||||
await detachButton.nth(1).click();
|
|
||||||
await expect(dimensionXLTokenPill).not.toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("User applies dimension token to a shape on x position", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
|
||||||
await setupTokensFile(page);
|
|
||||||
|
|
||||||
// Unfolds dimensions on token panel
|
|
||||||
await page.getByRole("tab", { name: "Layers" }).click();
|
|
||||||
|
|
||||||
await workspacePage.layers.getByTestId("layer-row").nth(1).click();
|
|
||||||
|
|
||||||
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
|
||||||
await tokensTabButton.click();
|
|
||||||
|
|
||||||
unfoldTokenTree(tokensSidebar, "dimensions", "dimension.dimension.sm");
|
|
||||||
|
|
||||||
// Apply token to width and height token from token panel
|
|
||||||
await tokensSidebar
|
|
||||||
.getByRole("button", { name: "dimension.sm" })
|
|
||||||
.click({ button: "right" });
|
|
||||||
await tokenContextMenuForToken.getByText("AxisX").click();
|
|
||||||
|
|
||||||
// Check if measures sections is visible on right sidebar
|
|
||||||
const measuresSection = page.getByRole("region", {
|
|
||||||
name: "shape-measures-section",
|
|
||||||
});
|
|
||||||
await expect(measuresSection).toBeVisible();
|
|
||||||
|
|
||||||
// Check if token pill is visible on design tab on right sidebar
|
|
||||||
const dimensionSMTokenPill = measuresSection.getByRole("button", {
|
|
||||||
name: "dimension.sm",
|
|
||||||
});
|
|
||||||
await expect(dimensionSMTokenPill).toBeVisible();
|
|
||||||
await dimensionSMTokenPill.click();
|
|
||||||
|
|
||||||
// Change token from dropdown
|
|
||||||
const dimensionTokenOptionXl = measuresSection.getByLabel("dimension.xl");
|
|
||||||
await expect(dimensionTokenOptionXl).toBeVisible();
|
|
||||||
await dimensionTokenOptionXl.click();
|
|
||||||
|
|
||||||
await expect(dimensionSMTokenPill).not.toBeVisible();
|
|
||||||
const dimensionXLTokenPill = measuresSection.getByRole("button", {
|
|
||||||
name: "dimension.xl",
|
|
||||||
});
|
|
||||||
await expect(dimensionXLTokenPill).toBeVisible();
|
|
||||||
|
|
||||||
// Detach token from design tab on right sidebar
|
|
||||||
const detachButton = measuresSection.getByRole("button", {
|
|
||||||
name: "Detach token",
|
|
||||||
});
|
|
||||||
await detachButton.nth(0).click();
|
|
||||||
await expect(dimensionXLTokenPill).not.toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("User applies dimension token to a shape on y position", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
|
||||||
await setupTokensFile(page);
|
|
||||||
|
|
||||||
// Unfolds dimensions on token panel
|
|
||||||
await page.getByRole("tab", { name: "Layers" }).click();
|
|
||||||
|
|
||||||
await workspacePage.layers.getByTestId("layer-row").nth(1).click();
|
|
||||||
|
|
||||||
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
|
||||||
await tokensTabButton.click();
|
|
||||||
|
|
||||||
unfoldTokenTree(tokensSidebar, "dimensions", "dimension.dimension.sm");
|
|
||||||
|
|
||||||
// Apply token to width and height token from token panel
|
|
||||||
await tokensSidebar
|
|
||||||
.getByRole("button", { name: "dimension.sm" })
|
|
||||||
.click({ button: "right" });
|
|
||||||
await tokenContextMenuForToken.getByText("Y").click();
|
|
||||||
|
|
||||||
// Check if measures sections is visible on right sidebar
|
|
||||||
const measuresSection = page.getByRole("region", {
|
|
||||||
name: "shape-measures-section",
|
|
||||||
});
|
|
||||||
await expect(measuresSection).toBeVisible();
|
|
||||||
|
|
||||||
// Check if token pill is visible on design tab on right sidebar
|
|
||||||
const dimensionSMTokenPill = measuresSection.getByRole("button", {
|
|
||||||
name: "dimension.sm",
|
|
||||||
});
|
|
||||||
await expect(dimensionSMTokenPill).toBeVisible();
|
|
||||||
await dimensionSMTokenPill.click();
|
|
||||||
|
|
||||||
// Change token from dropdown
|
|
||||||
const dimensionTokenOptionXl = measuresSection.getByLabel("dimension.xl");
|
|
||||||
await expect(dimensionTokenOptionXl).toBeVisible();
|
|
||||||
await dimensionTokenOptionXl.click();
|
|
||||||
|
|
||||||
await expect(dimensionSMTokenPill).not.toBeVisible();
|
|
||||||
const dimensionXLTokenPill = measuresSection.getByRole("button", {
|
|
||||||
name: "dimension.xl",
|
|
||||||
});
|
|
||||||
await expect(dimensionXLTokenPill).toBeVisible();
|
|
||||||
|
|
||||||
// Detach token from design tab on right sidebar
|
|
||||||
const detachButton = measuresSection.getByRole("button", {
|
|
||||||
name: "Detach token",
|
|
||||||
});
|
|
||||||
await detachButton.nth(0).click();
|
|
||||||
await expect(dimensionXLTokenPill).not.toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("User applies dimension token to a shape border-radius", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
const { workspacePage, tokensSidebar, tokenContextMenuForToken } =
|
|
||||||
await setupTokensFile(page);
|
|
||||||
|
|
||||||
// Unfolds dimensions on token panel
|
|
||||||
await page.getByRole("tab", { name: "Layers" }).click();
|
|
||||||
|
|
||||||
await workspacePage.layers.getByTestId("layer-row").nth(2).click();
|
|
||||||
|
|
||||||
const tokensTabButton = page.getByRole("tab", { name: "Tokens" });
|
|
||||||
await tokensTabButton.click();
|
|
||||||
|
|
||||||
unfoldTokenTree(tokensSidebar, "dimensions", "dimension.dimension.xs");
|
|
||||||
|
|
||||||
// Apply token to width and height token from token panel
|
|
||||||
await tokensSidebar
|
|
||||||
.getByRole("button", { name: "dimension.xs" })
|
|
||||||
.click({ button: "right" });
|
|
||||||
await tokenContextMenuForToken.getByText("Border radius").hover();
|
|
||||||
await tokenContextMenuForToken.getByText("RadiusAll").click();
|
|
||||||
|
|
||||||
// Check if border radius sections is visible on right sidebar
|
|
||||||
const borderRadiusSection = page.getByRole("region", {
|
|
||||||
name: "border-radius-section",
|
|
||||||
});
|
|
||||||
await expect(borderRadiusSection).toBeVisible();
|
|
||||||
|
|
||||||
// Check if token pill is visible on design tab on right sidebar
|
|
||||||
const dimensionXSTokenPill = borderRadiusSection.getByRole("button", {
|
|
||||||
name: "dimension.xs",
|
|
||||||
});
|
|
||||||
await expect(dimensionXSTokenPill).toBeVisible();
|
|
||||||
await dimensionXSTokenPill.click();
|
|
||||||
|
|
||||||
// Change token from dropdown
|
|
||||||
const dimensionTokenOptionXl = borderRadiusSection.getByLabel("dimension.xl");
|
|
||||||
await expect(dimensionTokenOptionXl).toBeVisible();
|
|
||||||
await dimensionTokenOptionXl.click();
|
|
||||||
|
|
||||||
await expect(dimensionXSTokenPill).not.toBeVisible();
|
|
||||||
const dimensionXLTokenPill = borderRadiusSection.getByRole("button", {
|
|
||||||
name: "dimension.xl",
|
|
||||||
});
|
|
||||||
await expect(dimensionXLTokenPill).toBeVisible();
|
|
||||||
|
|
||||||
// Detach token from design tab on right sidebar
|
|
||||||
const detachButton = borderRadiusSection.getByRole("button", {
|
|
||||||
name: "Detach token",
|
|
||||||
});
|
|
||||||
await detachButton.nth(0).click();
|
|
||||||
await expect(dimensionXLTokenPill).not.toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
--app-background: var(--color-background-primary);
|
--app-background: var(--color-background-primary);
|
||||||
--loader-background: var(--color-background-primary);
|
--loader-background: var(--color-background-primary);
|
||||||
--panel-title-background-color: var(--color-background-secondary);
|
|
||||||
|
|
||||||
// BUTTONS
|
// BUTTONS
|
||||||
--button-foreground-hover: var(--color-accent-primary);
|
--button-foreground-hover: var(--color-accent-primary);
|
||||||
|
|||||||
@@ -191,6 +191,16 @@
|
|||||||
(when (:fill attributes) (update-fill value shape-ids attributes page-id))
|
(when (:fill attributes) (update-fill value shape-ids attributes page-id))
|
||||||
(when (:stroke-color attributes) (update-stroke-color value shape-ids attributes page-id)))))))
|
(when (:stroke-color attributes) (update-stroke-color value shape-ids attributes page-id)))))))
|
||||||
|
|
||||||
|
(defn update-shape-dimensions
|
||||||
|
([value shape-ids attributes] (update-shape-dimensions value shape-ids attributes nil))
|
||||||
|
([value shape-ids attributes page-id]
|
||||||
|
(ptk/reify ::update-shape-dimensions
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ _ _]
|
||||||
|
(when (number? value)
|
||||||
|
(rx/of
|
||||||
|
(when (:width attributes) (dwtr/update-dimensions shape-ids :width value {:ignore-touched true :page-id page-id}))
|
||||||
|
(when (:height attributes) (dwtr/update-dimensions shape-ids :height value {:ignore-touched true :page-id page-id}))))))))
|
||||||
|
|
||||||
(defn- attributes->layout-gap [attributes value]
|
(defn- attributes->layout-gap [attributes value]
|
||||||
(let [layout-gap (-> (set/intersection attributes #{:column-gap :row-gap})
|
(let [layout-gap (-> (set/intersection attributes #{:column-gap :row-gap})
|
||||||
@@ -238,6 +248,21 @@
|
|||||||
{:ignore-touched true
|
{:ignore-touched true
|
||||||
:page-id page-id}))))))))
|
:page-id page-id}))))))))
|
||||||
|
|
||||||
|
(defn update-layout-spacing
|
||||||
|
([value shape-ids attributes] (update-layout-spacing value shape-ids attributes nil))
|
||||||
|
([value shape-ids attributes page-id]
|
||||||
|
(ptk/reify ::update-layout-spacing
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(when (number? value)
|
||||||
|
(let [ids-with-layout (shape-ids-with-layout state (or page-id (:current-page-id state)) shape-ids)
|
||||||
|
layout-attributes (attributes->layout-gap attributes value)]
|
||||||
|
(rx/of
|
||||||
|
(dwsl/update-layout ids-with-layout
|
||||||
|
layout-attributes
|
||||||
|
{:ignore-touched true
|
||||||
|
:page-id page-id}))))))))
|
||||||
|
|
||||||
(defn update-shape-position
|
(defn update-shape-position
|
||||||
([value shape-ids attributes] (update-shape-position value shape-ids attributes nil))
|
([value shape-ids attributes] (update-shape-position value shape-ids attributes nil))
|
||||||
([value shape-ids attributes page-id]
|
([value shape-ids attributes page-id]
|
||||||
@@ -251,20 +276,6 @@
|
|||||||
{:ignore-touched true
|
{:ignore-touched true
|
||||||
:page-id page-id})))))))))
|
:page-id page-id})))))))))
|
||||||
|
|
||||||
(defn update-layout-gap
|
|
||||||
[value shape-ids attributes page-id]
|
|
||||||
(ptk/reify ::update-layout-gao
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(when (number? value)
|
|
||||||
(let [ids-with-layout (shape-ids-with-layout state (or page-id (:current-page-id state)) shape-ids)
|
|
||||||
layout-attributes (attributes->layout-gap attributes value)]
|
|
||||||
(rx/of
|
|
||||||
(dwsl/update-layout ids-with-layout
|
|
||||||
layout-attributes
|
|
||||||
{:ignore-touched true
|
|
||||||
:page-id page-id})))))))
|
|
||||||
|
|
||||||
(defn update-layout-sizing-limits
|
(defn update-layout-sizing-limits
|
||||||
([value shape-ids attributes] (update-layout-sizing-limits value shape-ids attributes nil))
|
([value shape-ids attributes] (update-layout-sizing-limits value shape-ids attributes nil))
|
||||||
([value shape-ids attributes page-id]
|
([value shape-ids attributes page-id]
|
||||||
@@ -459,126 +470,20 @@
|
|||||||
value
|
value
|
||||||
[shape-ids attributes page-id])))))
|
[shape-ids attributes page-id])))))
|
||||||
|
|
||||||
(defn update-shape-dimensions
|
(defn update-typography-interactive
|
||||||
([value shape-ids attributes] (update-shape-dimensions value shape-ids attributes nil))
|
([value shape-ids attributes] (update-typography value shape-ids attributes nil))
|
||||||
([value shape-ids attributes page-id]
|
([value shape-ids attributes page-id]
|
||||||
(ptk/reify ::update-shape-dimensions
|
(when (map? value)
|
||||||
ptk/WatchEvent
|
(rx/merge
|
||||||
(watch [_ _ _]
|
(apply-functions-map
|
||||||
(when (number? value)
|
{:font-size update-font-size
|
||||||
(rx/of
|
:font-family update-font-family-interactive
|
||||||
(when (:width attributes) (dwtr/update-dimensions shape-ids :width value {:ignore-touched true :page-id page-id}))
|
:font-weight update-font-weight-interactive
|
||||||
(when (:height attributes) (dwtr/update-dimensions shape-ids :height value {:ignore-touched true :page-id page-id}))))))))
|
:letter-spacing update-letter-spacing
|
||||||
|
:text-case update-text-case
|
||||||
(defn- attributes->actions
|
:text-decoration update-text-decoration-interactive}
|
||||||
[{:keys [value shape-ids attributes page-id]}]
|
value
|
||||||
(cond-> []
|
[shape-ids attributes page-id])))))
|
||||||
(some attributes #{:width :height})
|
|
||||||
(conj #(update-shape-dimensions
|
|
||||||
value shape-ids
|
|
||||||
(set (filter attributes #{:width :height}))
|
|
||||||
page-id))
|
|
||||||
|
|
||||||
(some attributes #{:x :y})
|
|
||||||
(conj #(update-shape-position
|
|
||||||
value shape-ids
|
|
||||||
(set (filter attributes #{:x :y}))
|
|
||||||
page-id))
|
|
||||||
|
|
||||||
(some attributes #{:p1 :p2 :p3 :p4})
|
|
||||||
(conj #(update-layout-padding
|
|
||||||
value shape-ids
|
|
||||||
(set (filter attributes #{:p1 :p2 :p3 :p4}))
|
|
||||||
page-id))
|
|
||||||
|
|
||||||
(some attributes #{:m1 :m2 :m3 :m4})
|
|
||||||
(conj #(update-layout-item-margin
|
|
||||||
value shape-ids
|
|
||||||
(set (filter attributes #{:m1 :m2 :m3 :m4}))
|
|
||||||
page-id))
|
|
||||||
|
|
||||||
(some attributes #{:row-gap :column-gap})
|
|
||||||
(conj #(update-layout-gap
|
|
||||||
value shape-ids
|
|
||||||
(set (filter attributes #{:row-gap :column-gap}))
|
|
||||||
page-id))
|
|
||||||
|
|
||||||
(some attributes #{:r1 :r2 :r3 :r4})
|
|
||||||
(conj #(if (= attributes #{:r1 :r2 :r3 :r4})
|
|
||||||
(update-shape-radius-all value shape-ids attributes page-id)
|
|
||||||
(update-shape-radius-for-corners
|
|
||||||
value shape-ids
|
|
||||||
(set (filter attributes #{:r1 :r2 :r3 :r4}))
|
|
||||||
page-id)))
|
|
||||||
|
|
||||||
(some attributes #{:strole-width})
|
|
||||||
(conj #(update-stroke-width
|
|
||||||
value shape-ids
|
|
||||||
#{:strole-width}
|
|
||||||
page-id))
|
|
||||||
(some attributes #{:max-width :max-height})
|
|
||||||
(conj #(update-layout-sizing-limits
|
|
||||||
value shape-ids
|
|
||||||
(set (filter attributes #{:max-width :max-height}))
|
|
||||||
page-id))))
|
|
||||||
|
|
||||||
(defn use-dimensions-token
|
|
||||||
([value shape-ids attributes] (use-dimensions-token value shape-ids attributes nil))
|
|
||||||
([value shape-ids attributes page-id]
|
|
||||||
(ptk/reify ::use-dimensions-token
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(when (number? value)
|
|
||||||
(let [actions (attributes->actions
|
|
||||||
{:value value
|
|
||||||
:shape-ids shape-ids
|
|
||||||
:attributes attributes
|
|
||||||
:page-id page-id
|
|
||||||
:state state})]
|
|
||||||
(apply rx/of (map #(%) actions))))))))
|
|
||||||
|
|
||||||
(defn use-spacing-token
|
|
||||||
([value shape-ids attributes] (use-spacing-token value shape-ids attributes nil))
|
|
||||||
([value shape-ids attributes page-id]
|
|
||||||
(ptk/reify ::use-spacing-token
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [spacing-attrs
|
|
||||||
#{:row-gap :column-gap
|
|
||||||
:m1 :m2 :m3 :m4
|
|
||||||
:p1 :p2 :p3 :p4}]
|
|
||||||
(when (and (number? value)
|
|
||||||
(set? attributes)
|
|
||||||
(set/subset? attributes spacing-attrs))
|
|
||||||
|
|
||||||
(let [actions (attributes->actions
|
|
||||||
{:value value
|
|
||||||
:shape-ids shape-ids
|
|
||||||
:attributes attributes
|
|
||||||
:page-id page-id
|
|
||||||
:state state})]
|
|
||||||
(apply rx/of (map #(%) actions)))))))))
|
|
||||||
|
|
||||||
(defn use-sizing-token
|
|
||||||
([value shape-ids attributes] (use-sizing-token value shape-ids attributes nil))
|
|
||||||
([value shape-ids attributes page-id]
|
|
||||||
(ptk/reify ::use-sizing-token
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state _]
|
|
||||||
(let [sizing-attrs
|
|
||||||
#{:width :height
|
|
||||||
:max-width :max-height}]
|
|
||||||
(when (and (number? value)
|
|
||||||
(set? attributes)
|
|
||||||
(set/subset? attributes sizing-attrs))
|
|
||||||
|
|
||||||
(let [actions (attributes->actions
|
|
||||||
{:value value
|
|
||||||
:shape-ids shape-ids
|
|
||||||
:attributes attributes
|
|
||||||
:page-id page-id
|
|
||||||
:state state})]
|
|
||||||
(apply rx/of (map #(%) actions)))))))))
|
|
||||||
|
|
||||||
;; Events to apply / unapply tokens to shapes ------------------------------------------------------------
|
;; Events to apply / unapply tokens to shapes ------------------------------------------------------------
|
||||||
|
|
||||||
@@ -718,19 +623,54 @@
|
|||||||
:token token
|
:token token
|
||||||
:shape-ids shape-ids}))
|
:shape-ids shape-ids}))
|
||||||
(rx/of
|
(rx/of
|
||||||
(cond
|
(case (:type token)
|
||||||
(and (= (:type token) :spacing)
|
:spacing
|
||||||
(nil? attrs))
|
|
||||||
(apply-spacing-token {:token token
|
(apply-spacing-token {:token token
|
||||||
:attr attrs
|
:attr attrs
|
||||||
:shapes shapes})
|
:shapes shapes})
|
||||||
|
|
||||||
:else
|
|
||||||
(apply-token {:attributes (if (empty? attrs) attributes attrs)
|
(apply-token {:attributes (if (empty? attrs) attributes attrs)
|
||||||
:token token
|
:token token
|
||||||
:shape-ids shape-ids
|
:shape-ids shape-ids
|
||||||
:on-update-shape on-update-shape}))))))))
|
:on-update-shape on-update-shape}))))))))
|
||||||
|
|
||||||
|
(defn toggle-border-radius-token
|
||||||
|
[{:keys [token attrs shape-ids expand-with-children]}]
|
||||||
|
(ptk/reify ::on-toggle-border-radius-token
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [objects (dsh/lookup-page-objects state)
|
||||||
|
shapes (into [] (keep (d/getf objects)) shape-ids)
|
||||||
|
|
||||||
|
shapes
|
||||||
|
(if expand-with-children
|
||||||
|
(into []
|
||||||
|
(mapcat (fn [shape]
|
||||||
|
(if (= (:type shape) :group)
|
||||||
|
(keep objects (:shapes shape))
|
||||||
|
[shape])))
|
||||||
|
shapes)
|
||||||
|
shapes)
|
||||||
|
|
||||||
|
{:keys [attributes all-attributes]}
|
||||||
|
(get token-properties (:type token))
|
||||||
|
|
||||||
|
unapply-tokens?
|
||||||
|
(cft/shapes-token-applied? token shapes (or attrs all-attributes attributes))
|
||||||
|
|
||||||
|
shape-ids (map :id shapes)]
|
||||||
|
|
||||||
|
(if unapply-tokens?
|
||||||
|
(rx/of
|
||||||
|
(unapply-token {:attributes (or attrs all-attributes attributes)
|
||||||
|
:token token
|
||||||
|
:shape-ids shape-ids}))
|
||||||
|
(rx/of
|
||||||
|
(apply-token {:attributes attrs
|
||||||
|
:token token
|
||||||
|
:shape-ids shape-ids
|
||||||
|
:on-update-shape update-shape-radius-for-corners})))))))
|
||||||
|
|
||||||
|
|
||||||
(defn apply-token-on-selected
|
(defn apply-token-on-selected
|
||||||
[color-operations token]
|
[color-operations token]
|
||||||
(ptk/reify ::apply-token-on-selected
|
(ptk/reify ::apply-token-on-selected
|
||||||
@@ -860,7 +800,7 @@
|
|||||||
{:title "Sizing"
|
{:title "Sizing"
|
||||||
:attributes #{:width :height}
|
:attributes #{:width :height}
|
||||||
:all-attributes ctt/sizing-keys
|
:all-attributes ctt/sizing-keys
|
||||||
:on-update-shape use-sizing-token
|
:on-update-shape update-shape-dimensions
|
||||||
:modal {:key :tokens/sizing
|
:modal {:key :tokens/sizing
|
||||||
:fields [{:label "Sizing"
|
:fields [{:label "Sizing"
|
||||||
:key :sizing}]}}
|
:key :sizing}]}}
|
||||||
@@ -873,7 +813,7 @@
|
|||||||
ctt/border-radius-keys
|
ctt/border-radius-keys
|
||||||
ctt/axis-keys
|
ctt/axis-keys
|
||||||
ctt/stroke-width-keys)
|
ctt/stroke-width-keys)
|
||||||
:on-update-shape use-dimensions-token
|
:on-update-shape update-shape-dimensions
|
||||||
:modal {:key :tokens/dimensions
|
:modal {:key :tokens/dimensions
|
||||||
:fields [{:label "Dimensions"
|
:fields [{:label "Dimensions"
|
||||||
:key :dimensions}]}}
|
:key :dimensions}]}}
|
||||||
@@ -906,7 +846,7 @@
|
|||||||
{:title "Spacing"
|
{:title "Spacing"
|
||||||
:attributes #{:column-gap :row-gap}
|
:attributes #{:column-gap :row-gap}
|
||||||
:all-attributes ctt/spacing-keys
|
:all-attributes ctt/spacing-keys
|
||||||
:on-update-shape use-spacing-token
|
:on-update-shape update-layout-spacing
|
||||||
:modal {:key :tokens/spacing
|
:modal {:key :tokens/spacing
|
||||||
:fields [{:label "Spacing"
|
:fields [{:label "Spacing"
|
||||||
:key :spacing}]}}))
|
:key :spacing}]}}))
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
{ctt/border-radius-keys dwta/update-shape-radius-for-corners
|
{ctt/border-radius-keys dwta/update-shape-radius-for-corners
|
||||||
ctt/color-keys dwta/update-fill-stroke
|
ctt/color-keys dwta/update-fill-stroke
|
||||||
ctt/stroke-width-keys dwta/update-stroke-width
|
ctt/stroke-width-keys dwta/update-stroke-width
|
||||||
ctt/sizing-keys dwta/use-dimensions-token
|
ctt/sizing-keys dwta/update-shape-dimensions
|
||||||
ctt/opacity-keys dwta/update-opacity
|
ctt/opacity-keys dwta/update-opacity
|
||||||
ctt/rotation-keys dwta/update-rotation
|
ctt/rotation-keys dwta/update-rotation
|
||||||
|
|
||||||
@@ -73,8 +73,8 @@
|
|||||||
#{:x :y} dwta/update-shape-position
|
#{:x :y} dwta/update-shape-position
|
||||||
#{:p1 :p2 :p3 :p4} dwta/update-layout-padding
|
#{:p1 :p2 :p3 :p4} dwta/update-layout-padding
|
||||||
#{:m1 :m2 :m3 :m4} dwta/update-layout-item-margin
|
#{:m1 :m2 :m3 :m4} dwta/update-layout-item-margin
|
||||||
#{:column-gap :row-gap} dwta/update-layout-gap
|
#{:column-gap :row-gap} dwta/update-layout-spacing
|
||||||
#{:width :height} dwta/use-dimensions-token
|
#{:width :height} dwta/update-shape-dimensions
|
||||||
#{:layout-item-min-w :layout-item-min-h :layout-item-max-w :layout-item-max-h} dwta/update-layout-sizing-limits})
|
#{:layout-item-min-w :layout-item-min-h :layout-item-max-w :layout-item-max-h} dwta/update-layout-sizing-limits})
|
||||||
|
|
||||||
(def ^:private attribute-actions-map
|
(def ^:private attribute-actions-map
|
||||||
|
|||||||
@@ -483,6 +483,9 @@
|
|||||||
(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))
|
||||||
|
|
||||||
|
(def workspace-all-tokens-map
|
||||||
|
(l/derived (d/nilf ctob/get-all-tokens-map) tokens-lib))
|
||||||
|
|
||||||
(defn token-sets-at-path-all-active
|
(defn token-sets-at-path-all-active
|
||||||
[group-path]
|
[group-path]
|
||||||
(l/derived
|
(l/derived
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
[app.main.ui.ds.product.loader :refer [loader*]]
|
[app.main.ui.ds.product.loader :refer [loader*]]
|
||||||
[app.main.ui.ds.product.milestone :refer [milestone*]]
|
[app.main.ui.ds.product.milestone :refer [milestone*]]
|
||||||
[app.main.ui.ds.product.milestone-group :refer [milestone-group*]]
|
[app.main.ui.ds.product.milestone-group :refer [milestone-group*]]
|
||||||
|
[app.main.ui.ds.product.panel-title :refer [panel-title*]]
|
||||||
[app.main.ui.ds.storybook :as sb]
|
[app.main.ui.ds.storybook :as sb]
|
||||||
[app.main.ui.ds.tooltip.tooltip :refer [tooltip*]]
|
[app.main.ui.ds.tooltip.tooltip :refer [tooltip*]]
|
||||||
[app.main.ui.ds.utilities.date :refer [date*]]
|
[app.main.ui.ds.utilities.date :refer [date*]]
|
||||||
@@ -81,6 +82,7 @@
|
|||||||
:Milestone milestone*
|
:Milestone milestone*
|
||||||
:MilestoneGroup milestone-group*
|
:MilestoneGroup milestone-group*
|
||||||
:Date date*
|
:Date date*
|
||||||
|
:PanelTitle panel-title*
|
||||||
|
|
||||||
:set-default-translations
|
:set-default-translations
|
||||||
(fn [data]
|
(fn [data]
|
||||||
|
|||||||
34
frontend/src/app/main/ui/ds/product/panel_title.cljs
Normal file
34
frontend/src/app/main/ui/ds/product/panel_title.cljs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
;; 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.main.ui.ds.product.panel-title
|
||||||
|
(:require-macros
|
||||||
|
[app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
|
[app.main.ui.ds.foundations.assets.icon :as i]
|
||||||
|
[app.util.i18n :refer [tr]]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(def ^:private schema:panel-title
|
||||||
|
[:map
|
||||||
|
[:class {:optional true} :string]
|
||||||
|
[:text :string]
|
||||||
|
[:on-close {:optional true} fn?]])
|
||||||
|
|
||||||
|
(mf/defc panel-title*
|
||||||
|
{::mf/schema schema:panel-title}
|
||||||
|
[{:keys [class text on-close] :rest props}]
|
||||||
|
(let [props
|
||||||
|
(mf/spread-props props {:class [class (stl/css :panel-title)]})]
|
||||||
|
|
||||||
|
[:> :div props
|
||||||
|
[:span {:class (stl/css :panel-title-text)} text]
|
||||||
|
(when on-close
|
||||||
|
[:> icon-button* {:variant "ghost"
|
||||||
|
:aria-label (tr "labels.close")
|
||||||
|
:on-click on-close
|
||||||
|
:icon i/close}])]))
|
||||||
26
frontend/src/app/main/ui/ds/product/panel_title.mdx
Normal file
26
frontend/src/app/main/ui/ds/product/panel_title.mdx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{ /* 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 */ }
|
||||||
|
|
||||||
|
import { Canvas, Meta } from '@storybook/addon-docs/blocks';
|
||||||
|
import * as PanelTitle from "./panel_title.stories";
|
||||||
|
|
||||||
|
<Meta title="Product/PanelTitle" />
|
||||||
|
|
||||||
|
# PanelTitle
|
||||||
|
|
||||||
|
The `panel-title*` is used as a header for some sidebar sections.
|
||||||
|
|
||||||
|
<Canvas of={PanelTitle.Default} />
|
||||||
|
|
||||||
|
## Technical notes
|
||||||
|
|
||||||
|
The only mandatory parameter is `text`. Usually you'll want to pass a function property `on-close` that will be called when the user clicks on the close button on the right.
|
||||||
|
|
||||||
|
```clj
|
||||||
|
[:> panel-title* {:class class
|
||||||
|
:text text
|
||||||
|
:on-close on-close}]
|
||||||
|
```
|
||||||
25
frontend/src/app/main/ui/ds/product/panel_title.scss
Normal file
25
frontend/src/app/main/ui/ds/product/panel_title.scss
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
@use "ds/_sizes.scss" as *;
|
||||||
|
@use "ds/_borders.scss" as *;
|
||||||
|
@use "ds/typography.scss" as t;
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
block-size: $sz-32;
|
||||||
|
border-radius: $br-8;
|
||||||
|
background-color: var(--color-background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-title-text {
|
||||||
|
@include t.use-typography("headline-small");
|
||||||
|
flex-grow: 1;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-foreground-primary);
|
||||||
|
}
|
||||||
21
frontend/src/app/main/ui/ds/product/panel_title.stories.jsx
Normal file
21
frontend/src/app/main/ui/ds/product/panel_title.stories.jsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import Components from "@target/components";
|
||||||
|
|
||||||
|
const { PanelTitle } = Components;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Product/PanelTitle",
|
||||||
|
component: PanelTitle,
|
||||||
|
argTypes: {
|
||||||
|
text: {
|
||||||
|
control: { type: "text" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
text: "Lorem ipsum",
|
||||||
|
onClose: () => null,
|
||||||
|
},
|
||||||
|
render: ({ ...args }) => <PanelTitle {...args} />,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = {};
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
[app.main.ui.comments :as cmt]
|
[app.main.ui.comments :as cmt]
|
||||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
|
||||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
[app.main.ui.ds.foundations.assets.icon :as i]
|
||||||
[app.main.ui.ds.product.empty-state :refer [empty-state*]]
|
[app.main.ui.ds.product.empty-state :refer [empty-state*]]
|
||||||
|
[app.main.ui.ds.product.panel-title :refer [panel-title*]]
|
||||||
[app.main.ui.icons :as deprecated-icon]
|
[app.main.ui.icons :as deprecated-icon]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
@@ -123,13 +123,10 @@
|
|||||||
|
|
||||||
[:div {:class (stl/css-case :comments-section true
|
[:div {:class (stl/css-case :comments-section true
|
||||||
:from-viewer from-viewer)}
|
:from-viewer from-viewer)}
|
||||||
[:div {:class (stl/css-case :comments-section-title true
|
|
||||||
:viewer-title from-viewer)}
|
[:> panel-title* {:class (stl/css :comments-title)
|
||||||
[:span (tr "labels.comments")]
|
:text (tr "labels.comments")
|
||||||
[:> icon-button* {:variant "ghost"
|
:on-close close-section}]
|
||||||
:aria-label (tr "labels.close")
|
|
||||||
:on-click close-section
|
|
||||||
:icon i/close}]]
|
|
||||||
|
|
||||||
[:button {:class (stl/css :mode-dropdown-wrapper)
|
[:button {:class (stl/css :mode-dropdown-wrapper)
|
||||||
:on-click toggle-mode-selector}
|
:on-click toggle-mode-selector}
|
||||||
|
|||||||
@@ -18,25 +18,8 @@
|
|||||||
padding: 0 deprecated.$s-8;
|
padding: 0 deprecated.$s-8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.comments-section-title {
|
.comments-title {
|
||||||
@include deprecated.flexCenter;
|
margin: var(--sp-s) var(--sp-s) 0 var(--sp-s);
|
||||||
@include deprecated.uppercaseTitleTipography;
|
|
||||||
position: relative;
|
|
||||||
height: deprecated.$s-32;
|
|
||||||
min-height: deprecated.$s-32;
|
|
||||||
margin: deprecated.$s-8 deprecated.$s-8 0 deprecated.$s-8;
|
|
||||||
border-radius: deprecated.$br-8;
|
|
||||||
background-color: var(--panel-title-background-color);
|
|
||||||
span {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
flex-grow: 1;
|
|
||||||
color: var(--title-foreground-color-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewer-title {
|
|
||||||
margin: 0;
|
|
||||||
margin-block-start: deprecated.$s-8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode-dropdown-wrapper {
|
.mode-dropdown-wrapper {
|
||||||
|
|||||||
@@ -11,12 +11,11 @@
|
|||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.product.panel-title :refer [panel-title*]]
|
||||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
|
||||||
[app.main.ui.icons :as deprecated-icon]
|
[app.main.ui.icons :as deprecated-icon]
|
||||||
[app.util.debug :as dbg]
|
[app.util.debug :as dbg]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(mf/defc debug-panel*
|
(mf/defc debug-panel*
|
||||||
@@ -35,12 +34,9 @@
|
|||||||
(st/emit! (dw/remove-layout-flag :debug-panel))))]
|
(st/emit! (dw/remove-layout-flag :debug-panel))))]
|
||||||
|
|
||||||
[:div {:class (dm/str class " " (stl/css :debug-panel))}
|
[:div {:class (dm/str class " " (stl/css :debug-panel))}
|
||||||
[:div {:class (stl/css :panel-title)}
|
[:> panel-title* {:class (stl/css :debug-panel-title)
|
||||||
[:span "Debugging tools"]
|
:text (tr "workspace.debug.title")
|
||||||
[:> icon-button* {:variant "ghost"
|
:on-close handle-close}]
|
||||||
:aria-label (tr "labels.close")
|
|
||||||
:on-click handle-close
|
|
||||||
:icon i/close}]]
|
|
||||||
|
|
||||||
[:div {:class (stl/css :debug-panel-inner)}
|
[:div {:class (stl/css :debug-panel-inner)}
|
||||||
(for [option (sort-by d/name dbg/options)]
|
(for [option (sort-by d/name dbg/options)]
|
||||||
|
|||||||
@@ -12,21 +12,12 @@
|
|||||||
background-color: var(--panel-background-color);
|
background-color: var(--panel-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-title {
|
.debug-panel-title {
|
||||||
@include deprecated.flexCenter;
|
margin: var(--sp-s) var(--sp-s) 0 var(--sp-s);
|
||||||
@include deprecated.uppercaseTitleTipography;
|
}
|
||||||
position: relative;
|
|
||||||
height: deprecated.$s-32;
|
|
||||||
min-height: deprecated.$s-32;
|
|
||||||
margin: deprecated.$s-8 deprecated.$s-8 0 deprecated.$s-8;
|
|
||||||
border-radius: deprecated.$br-8;
|
|
||||||
background-color: var(--panel-title-background-color);
|
|
||||||
|
|
||||||
span {
|
.debug-panel-inner {
|
||||||
@include deprecated.flexCenter;
|
padding: deprecated.$s-16 deprecated.$s-8;
|
||||||
flex-grow: 1;
|
|
||||||
color: var(--title-foreground-color-hover);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-wrapper {
|
.checkbox-wrapper {
|
||||||
@@ -39,7 +30,3 @@
|
|||||||
@extend .checkbox-icon;
|
@extend .checkbox-icon;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.debug-panel-inner {
|
|
||||||
padding: deprecated.$s-16 deprecated.$s-8;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.icons :as deprecated-icon]
|
[app.main.ui.ds.product.panel-title :refer [panel-title*]]
|
||||||
[debug :as dbg]
|
[debug :as dbg]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
@@ -125,11 +125,9 @@
|
|||||||
(map (d/getf objects)))]
|
(map (d/getf objects)))]
|
||||||
|
|
||||||
[:div {:class (stl/css :shape-info)}
|
[:div {:class (stl/css :shape-info)}
|
||||||
[:div {:class (stl/css :shape-info-title)}
|
[:> panel-title* {:class (stl/css :shape-info-title)
|
||||||
[:span "Debug"]
|
:text "Debug"
|
||||||
[:div {:class (stl/css :close-button)
|
:on-close #(dbg/disable! :shape-panel)}]
|
||||||
:on-click #(dbg/disable! :shape-panel)}
|
|
||||||
deprecated-icon/close]]
|
|
||||||
|
|
||||||
(if (empty? selected)
|
(if (empty? selected)
|
||||||
[:div {:class (stl/css :attrs-container)} "No shapes selected"]
|
[:div {:class (stl/css :attrs-container)} "No shapes selected"]
|
||||||
|
|||||||
@@ -16,34 +16,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.shape-info-title {
|
.shape-info-title {
|
||||||
@include deprecated.flexCenter;
|
margin: var(--sp-s) var(--sp-s) 0 var(--sp-s);
|
||||||
@include deprecated.uppercaseTitleTipography;
|
|
||||||
position: relative;
|
|
||||||
height: deprecated.$s-32;
|
|
||||||
min-height: deprecated.$s-32;
|
|
||||||
margin: deprecated.$s-8 deprecated.$s-8 0 deprecated.$s-8;
|
|
||||||
border-radius: deprecated.$br-8;
|
|
||||||
background-color: var(--panel-title-background-color);
|
|
||||||
|
|
||||||
span {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
flex-grow: 1;
|
|
||||||
color: var(--title-foreground-color-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button {
|
|
||||||
@extend .button-tertiary;
|
|
||||||
position: absolute;
|
|
||||||
right: deprecated.$s-2;
|
|
||||||
top: deprecated.$s-2;
|
|
||||||
height: deprecated.$s-28;
|
|
||||||
width: deprecated.$s-28;
|
|
||||||
border-radius: deprecated.$br-6;
|
|
||||||
svg {
|
|
||||||
@extend .button-icon;
|
|
||||||
stroke: var(--icon-foreground);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.attrs-container {
|
.attrs-container {
|
||||||
|
|||||||
@@ -13,23 +13,6 @@
|
|||||||
background-color: var(--panel-background-color);
|
background-color: var(--panel-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-toolbox-title {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
@include deprecated.uppercaseTitleTipography;
|
|
||||||
position: relative;
|
|
||||||
height: deprecated.$s-32;
|
|
||||||
min-height: deprecated.$s-32;
|
|
||||||
margin: deprecated.$s-8 deprecated.$s-8 0 deprecated.$s-8;
|
|
||||||
border-radius: deprecated.$br-8;
|
|
||||||
background-color: var(--panel-title-background-color);
|
|
||||||
|
|
||||||
span {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
flex-grow: 1;
|
|
||||||
color: var(--title-foreground-color-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.history-entry-empty {
|
.history-entry-empty {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -192,10 +192,11 @@
|
|||||||
(st/emit!
|
(st/emit!
|
||||||
(change-radius (fn [shape]
|
(change-radius (fn [shape]
|
||||||
(ctsr/set-radius-to-all-corners shape value))))
|
(ctsr/set-radius-to-all-corners shape value))))
|
||||||
|
(doseq [attr [:r1 :r2 :r3 :r4]]
|
||||||
(st/emit!
|
(st/emit!
|
||||||
(dwta/toggle-token {:token (first value)
|
(dwta/toggle-token {:token (first value)
|
||||||
:attrs #{:r1 :r2 :r3 :r4}
|
:attrs #{attr}
|
||||||
:shape-ids ids})))))
|
:shape-ids ids}))))))
|
||||||
|
|
||||||
|
|
||||||
on-single-radius-change
|
on-single-radius-change
|
||||||
@@ -204,10 +205,9 @@
|
|||||||
(fn [value attr]
|
(fn [value attr]
|
||||||
(if (or (string? value) (number? value))
|
(if (or (string? value) (number? value))
|
||||||
(st/emit! (change-one-radius #(ctsr/set-radius-to-single-corner % attr value) attr))
|
(st/emit! (change-one-radius #(ctsr/set-radius-to-single-corner % attr value) attr))
|
||||||
(st/emit! (st/emit!
|
(st/emit! (dwta/toggle-border-radius-token {:token (first value)
|
||||||
(dwta/toggle-token {:token (first value)
|
|
||||||
:attrs #{attr}
|
:attrs #{attr}
|
||||||
:shape-ids ids}))))))
|
:shape-ids ids})))))
|
||||||
|
|
||||||
on-radius-r1-change #(on-single-radius-change % :r1)
|
on-radius-r1-change #(on-single-radius-change % :r1)
|
||||||
on-radius-r2-change #(on-single-radius-change % :r2)
|
on-radius-r2-change #(on-single-radius-change % :r2)
|
||||||
|
|||||||
@@ -369,12 +369,12 @@
|
|||||||
(if (or (string? value) (int? value))
|
(if (or (string? value) (int? value))
|
||||||
(on-change :simple attr value event)
|
(on-change :simple attr value event)
|
||||||
(do
|
(do
|
||||||
(st/emit!
|
(let [resolved-value (:resolved-value (first value))
|
||||||
(dwta/toggle-token {:token (first value)
|
updated-attr (if (= :p1 attr) #{:p1 :p3} #{:p2 :p4})]
|
||||||
:attrs (if (= :p1 attr)
|
(st/emit! (dwta/toggle-token {:token (first value)
|
||||||
#{:p1 :p3}
|
:attrs updated-attr
|
||||||
#{:p2 :p4})
|
:shape-ids ids}))
|
||||||
:shape-ids ids}))))))
|
(on-change :simple attr resolved-value event))))))
|
||||||
|
|
||||||
on-detach-token
|
on-detach-token
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@@ -483,9 +483,11 @@
|
|||||||
(if (or (string? value) (int? value))
|
(if (or (string? value) (int? value))
|
||||||
(on-change :multiple attr value event)
|
(on-change :multiple attr value event)
|
||||||
(do
|
(do
|
||||||
|
(let [resolved-value (:resolved-value (first value))]
|
||||||
(st/emit! (dwta/toggle-token {:token (first value)
|
(st/emit! (dwta/toggle-token {:token (first value)
|
||||||
:attrs #{attr}
|
:attrs #{attr}
|
||||||
:shape-ids ids}))))))
|
:shape-ids ids}))
|
||||||
|
(on-change :multiple attr resolved-value event))))))
|
||||||
|
|
||||||
on-focus
|
on-focus
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@@ -714,12 +716,11 @@
|
|||||||
(if (or (string? value) (int? value))
|
(if (or (string? value) (int? value))
|
||||||
(on-change (= "nowrap" wrap-type) attr value event)
|
(on-change (= "nowrap" wrap-type) attr value event)
|
||||||
(do
|
(do
|
||||||
(st/emit!
|
(let [resolved-value (:resolved-value (first value))]
|
||||||
(dwta/toggle-token {:token (first value)
|
(st/emit! (dwta/toggle-token {:token (first value)
|
||||||
:attrs (if (= "nowrap" wrap-type)
|
:attrs #{attr}
|
||||||
#{:row-gap :colum-gap}
|
:shape-ids ids}))
|
||||||
#{attr})
|
(on-change (= "nowrap" wrap-type) attr resolved-value event))))))
|
||||||
:shape-ids ids}))))))
|
|
||||||
|
|
||||||
on-detach-token
|
on-detach-token
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|||||||
@@ -284,17 +284,28 @@
|
|||||||
(st/emit! (udw/change-orientation ids (keyword orientation)))))
|
(st/emit! (udw/change-orientation ids (keyword orientation)))))
|
||||||
|
|
||||||
;; SIZE AND PROPORTION LOCK
|
;; SIZE AND PROPORTION LOCK
|
||||||
|
do-size-change
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps ids)
|
||||||
|
(fn [value attr]
|
||||||
|
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||||
|
(udw/update-dimensions ids attr value))))
|
||||||
|
|
||||||
on-size-change
|
on-size-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps ids shapes)
|
(mf/deps ids shapes)
|
||||||
(fn [value attr]
|
(fn [value attr]
|
||||||
(if (or (string? value) (number? value))
|
(if (or (string? value) (number? value))
|
||||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
(do
|
||||||
(udw/update-dimensions ids attr value))
|
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
||||||
|
(run! #(do-size-change value attr) shapes))
|
||||||
|
(do
|
||||||
|
(let [resolved-value (:resolved-value (first value))]
|
||||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||||
(dwta/toggle-token {:token (first value)
|
(dwta/toggle-token {:token (first value)
|
||||||
:attrs #{attr}
|
:attrs #{attr}
|
||||||
:shape-ids ids})))))
|
:shape-ids ids}))
|
||||||
|
(run! #(do-size-change resolved-value attr) shapes))))))
|
||||||
|
|
||||||
on-proportion-lock-change
|
on-proportion-lock-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@@ -304,6 +315,11 @@
|
|||||||
(run! #(st/emit! (udw/set-shape-proportion-lock % new-lock)) ids))))
|
(run! #(st/emit! (udw/set-shape-proportion-lock % new-lock)) ids))))
|
||||||
|
|
||||||
;; POSITION
|
;; POSITION
|
||||||
|
do-position-change
|
||||||
|
(mf/use-fn
|
||||||
|
(fn [shape' value attr]
|
||||||
|
(st/emit! (udw/update-position (:id shape') {attr value}))))
|
||||||
|
|
||||||
on-position-change
|
on-position-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps ids)
|
(mf/deps ids)
|
||||||
@@ -311,11 +327,21 @@
|
|||||||
(if (or (string? value) (number? value))
|
(if (or (string? value) (number? value))
|
||||||
(do
|
(do
|
||||||
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
||||||
(st/emit! (udw/update-position ids {attr value})))
|
(run! #(do-position-change %1 value attr) shapes))
|
||||||
|
(do
|
||||||
|
(let [resolved-value (:resolved-value (first value))]
|
||||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||||
(dwta/toggle-token {:token (first value)
|
(dwta/toggle-token {:token (first value)
|
||||||
:attrs #{attr}
|
:attrs #{attr}
|
||||||
:shape-ids ids})))))
|
:shape-ids ids}))
|
||||||
|
(run! #(do-position-change %1 resolved-value attr) shapes))))))
|
||||||
|
|
||||||
|
;; ROTATION
|
||||||
|
do-rotation-change
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps ids)
|
||||||
|
(fn [value]
|
||||||
|
(st/emit! (udw/increase-rotation ids value))))
|
||||||
|
|
||||||
on-rotation-change
|
on-rotation-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
@@ -324,11 +350,14 @@
|
|||||||
(if (or (string? value) (number? value))
|
(if (or (string? value) (number? value))
|
||||||
(do
|
(do
|
||||||
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
(st/emit! (udw/trigger-bounding-box-cloaking ids))
|
||||||
(st/emit! (udw/increase-rotation ids value)))
|
(run! #(do-rotation-change value) shapes))
|
||||||
|
(do
|
||||||
|
(let [resolved-value (:resolved-value (first value))]
|
||||||
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
(st/emit! (udw/trigger-bounding-box-cloaking ids)
|
||||||
(dwta/toggle-token {:token (first value)
|
(dwta/toggle-token {:token (first value)
|
||||||
:attrs #{:rotation}
|
:attrs #{:rotation}
|
||||||
:shape-ids ids})))))
|
:shape-ids ids}))
|
||||||
|
(run! #(do-rotation-change resolved-value) shapes))))))
|
||||||
|
|
||||||
on-width-change
|
on-width-change
|
||||||
(mf/use-fn (mf/deps on-size-change) #(on-size-change % :width))
|
(mf/use-fn (mf/deps on-size-change) #(on-size-change % :width))
|
||||||
@@ -381,8 +410,7 @@
|
|||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dwt/selected-fit-content))))]
|
(st/emit! (dwt/selected-fit-content))))]
|
||||||
|
|
||||||
[:section {:class (stl/css :element-set)
|
[:div {:class (stl/css :element-set)}
|
||||||
:aria-label "shape-measures-section"}
|
|
||||||
(when (and (options :presets)
|
(when (and (options :presets)
|
||||||
(or (nil? all-types) (= (count all-types) 1)))
|
(or (nil? all-types) (= (count all-types) 1)))
|
||||||
[:div {:class (stl/css :presets)}
|
[:div {:class (stl/css :presets)}
|
||||||
|
|||||||
@@ -9,50 +9,18 @@
|
|||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.types.color :as ctc]
|
[app.common.types.color :as ctc]
|
||||||
[app.common.types.token :as tk]
|
|
||||||
[app.main.data.workspace.tokens.application :as dwta]
|
[app.main.data.workspace.tokens.application :as dwta]
|
||||||
[app.main.features :as features]
|
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.numeric-input :as deprecated-input]
|
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||||
[app.main.ui.components.reorder-handler :refer [reorder-handler*]]
|
[app.main.ui.components.reorder-handler :refer [reorder-handler*]]
|
||||||
[app.main.ui.components.select :refer [select]]
|
[app.main.ui.components.select :refer [select]]
|
||||||
[app.main.ui.context :as muc]
|
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||||
[app.main.ui.ds.controls.numeric-input :refer [numeric-input*]]
|
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
||||||
[app.main.ui.hooks :as h]
|
[app.main.ui.hooks :as h]
|
||||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row*]]
|
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row*]]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(mf/defc numeric-input-wrapper*
|
|
||||||
{::mf/private true}
|
|
||||||
[{:keys [values name applied-tokens align on-detach] :rest props}]
|
|
||||||
(let [tokens (mf/use-ctx muc/active-tokens-by-type)
|
|
||||||
tokens (mf/with-memo [tokens name]
|
|
||||||
(delay
|
|
||||||
(-> (deref tokens)
|
|
||||||
(select-keys (get tk/tokens-by-input name))
|
|
||||||
(not-empty))))
|
|
||||||
|
|
||||||
on-detach-attr (mf/use-fn
|
|
||||||
(mf/deps on-detach name)
|
|
||||||
#(on-detach % name))
|
|
||||||
|
|
||||||
applied-token (get applied-tokens name)
|
|
||||||
|
|
||||||
props (mf/spread-props props
|
|
||||||
{:placeholder (if (= :multiple values)
|
|
||||||
(tr "settings.multiple")
|
|
||||||
"--")
|
|
||||||
:applied-token applied-token
|
|
||||||
:tokens (if (delay? tokens) @tokens tokens)
|
|
||||||
:align align
|
|
||||||
:on-detach on-detach-attr
|
|
||||||
:name name
|
|
||||||
:value values})]
|
|
||||||
[:> numeric-input* props]))
|
|
||||||
|
|
||||||
(mf/defc stroke-row*
|
(mf/defc stroke-row*
|
||||||
[{:keys [index
|
[{:keys [index
|
||||||
stroke
|
stroke
|
||||||
@@ -77,10 +45,7 @@
|
|||||||
select-on-focus
|
select-on-focus
|
||||||
ids]}]
|
ids]}]
|
||||||
|
|
||||||
(let [token-numeric-inputs
|
(let [on-drop
|
||||||
(features/use-feature "tokens/numeric-input")
|
|
||||||
|
|
||||||
on-drop
|
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps on-reorder index)
|
(mf/deps on-reorder index)
|
||||||
(fn [relative-pos data]
|
(fn [relative-pos data]
|
||||||
@@ -123,13 +88,7 @@
|
|||||||
on-width-change
|
on-width-change
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps index on-stroke-width-change)
|
(mf/deps index on-stroke-width-change)
|
||||||
(fn [value]
|
#(on-stroke-width-change index %))
|
||||||
(if (or (string? value) (int? value))
|
|
||||||
(on-stroke-width-change index value)
|
|
||||||
(do
|
|
||||||
(st/emit! (dwta/toggle-token {:token (first value)
|
|
||||||
:attrs #{:stroke-width}
|
|
||||||
:shape-ids ids}))))))
|
|
||||||
|
|
||||||
stroke-alignment (or (:stroke-alignment stroke) :center)
|
stroke-alignment (or (:stroke-alignment stroke) :center)
|
||||||
|
|
||||||
@@ -190,12 +149,6 @@
|
|||||||
(fn [token]
|
(fn [token]
|
||||||
(on-detach-token token #{:stroke-color})))
|
(on-detach-token token #{:stroke-color})))
|
||||||
|
|
||||||
on-detach-token-width
|
|
||||||
(mf/use-fn
|
|
||||||
(mf/deps on-detach-token)
|
|
||||||
(fn [token]
|
|
||||||
(on-detach-token (first token) #{:stroke-width})))
|
|
||||||
|
|
||||||
stroke-caps-options
|
stroke-caps-options
|
||||||
[{:value nil :label (tr "workspace.options.stroke-cap.none")}
|
[{:value nil :label (tr "workspace.options.stroke-cap.none")}
|
||||||
:separator
|
:separator
|
||||||
@@ -242,30 +195,17 @@
|
|||||||
|
|
||||||
;; Stroke Width, Alignment & Style
|
;; Stroke Width, Alignment & Style
|
||||||
[:div {:class (stl/css :stroke-options)}
|
[:div {:class (stl/css :stroke-options)}
|
||||||
(if token-numeric-inputs
|
|
||||||
[:> numeric-input-wrapper* {:on-change on-width-change
|
|
||||||
:on-detach on-detach-token-width
|
|
||||||
:icon i/stroke-size
|
|
||||||
:min 0
|
|
||||||
:on-focus on-focus
|
|
||||||
:on-blur on-blur
|
|
||||||
:name :stroke-width
|
|
||||||
:class (stl/css :numeric-input-wrapper)
|
|
||||||
:property (tr "workspace.options.stroke-width")
|
|
||||||
:applied-tokens applied-tokens
|
|
||||||
:values stroke-width}]
|
|
||||||
|
|
||||||
[:div {:class (stl/css :stroke-width-input)
|
[:div {:class (stl/css :stroke-width-input)
|
||||||
:title (tr "workspace.options.stroke-width")}
|
:title (tr "workspace.options.stroke-width")}
|
||||||
[:> icon* {:icon-id i/stroke-size
|
[:> icon* {:icon-id i/stroke-size
|
||||||
:size "s"}]
|
:size "s"}]
|
||||||
[:> deprecated-input/numeric-input* {:value stroke-width
|
[:> numeric-input* {:value stroke-width
|
||||||
:min 0
|
:min 0
|
||||||
:placeholder (tr "settings.multiple")
|
:placeholder (tr "settings.multiple")
|
||||||
:on-change on-width-change
|
:on-change on-width-change
|
||||||
:on-focus on-focus
|
:on-focus on-focus
|
||||||
:select-on-focus select-on-focus
|
:select-on-focus select-on-focus
|
||||||
:on-blur on-blur}]])
|
:on-blur on-blur}]]
|
||||||
|
|
||||||
[:div {:class (stl/css :stroke-alignment-select)
|
[:div {:class (stl/css :stroke-alignment-select)
|
||||||
:data-testid "stroke.alignment"}
|
:data-testid "stroke.alignment"}
|
||||||
|
|||||||
@@ -45,11 +45,6 @@
|
|||||||
padding-inline-start: var(--sp-xs);
|
padding-inline-start: var(--sp-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.numeric-input-wrapper {
|
|
||||||
grid-column: span 2;
|
|
||||||
--dropdown-width: var(--7-columns-dropdown-width);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stroke-alignment-select {
|
.stroke-alignment-select {
|
||||||
grid-column: span 3;
|
grid-column: span 3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
[app.main.data.workspace.shortcuts]
|
[app.main.data.workspace.shortcuts]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.search-bar :refer [search-bar*]]
|
[app.main.ui.components.search-bar :refer [search-bar*]]
|
||||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
|
||||||
[app.main.ui.ds.foundations.assets.icon :as i :refer [icon*]]
|
[app.main.ui.ds.foundations.assets.icon :as i :refer [icon*]]
|
||||||
|
[app.main.ui.ds.product.panel-title :refer [panel-title*]]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :refer [tr]]
|
[app.util.i18n :refer [tr]]
|
||||||
[app.util.strings :refer [matches-search]]
|
[app.util.strings :refer [matches-search]]
|
||||||
@@ -487,13 +487,9 @@
|
|||||||
(dom/focus! (dom/get-element "shortcut-search")))
|
(dom/focus! (dom/get-element "shortcut-search")))
|
||||||
|
|
||||||
[:div {:class (dm/str class " " (stl/css :shortcuts))}
|
[:div {:class (dm/str class " " (stl/css :shortcuts))}
|
||||||
[:div {:class (stl/css :shortcuts-header)}
|
[:> panel-title* {:class (stl/css :shortcuts-title)
|
||||||
[:div {:class (stl/css :shortcuts-title)} (tr "shortcuts.title")]
|
:text (tr "shortcuts.title")
|
||||||
[:> icon-button* {:variant "ghost"
|
:on-close close-fn}]
|
||||||
:icon i/close
|
|
||||||
:class (stl/css :shortcuts-close-button)
|
|
||||||
:on-click close-fn
|
|
||||||
:aria-label (tr "labels.close")}]]
|
|
||||||
|
|
||||||
[:div {:class (stl/css :search-field)}
|
[:div {:class (stl/css :search-field)}
|
||||||
[:> search-bar* {:on-change on-search-term-change-2
|
[:> search-bar* {:on-change on-search-term-change-2
|
||||||
|
|||||||
@@ -18,27 +18,8 @@
|
|||||||
margin: deprecated.$s-16 deprecated.$s-12 deprecated.$s-4 deprecated.$s-12;
|
margin: deprecated.$s-16 deprecated.$s-12 deprecated.$s-4 deprecated.$s-12;
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcuts-header {
|
.shortcuts-title {
|
||||||
@include deprecated.flexCenter;
|
margin: var(--sp-s) var(--sp-s) 0 var(--sp-s);
|
||||||
@include deprecated.uppercaseTitleTipography;
|
|
||||||
position: relative;
|
|
||||||
height: deprecated.$s-32;
|
|
||||||
padding: deprecated.$s-2 deprecated.$s-2 deprecated.$s-2 0;
|
|
||||||
margin: deprecated.$s-4 deprecated.$s-4 0 deprecated.$s-4;
|
|
||||||
border-radius: deprecated.$br-6;
|
|
||||||
background-color: var(--panel-title-background-color);
|
|
||||||
|
|
||||||
.shortcuts-title {
|
|
||||||
@include deprecated.flexCenter;
|
|
||||||
flex-grow: 1;
|
|
||||||
color: var(--title-foreground-color-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.shortcuts-close-button {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
|
|||||||
@@ -223,7 +223,7 @@
|
|||||||
gap-items (all-or-separate-actions {:attribute-labels {:column-gap "Column Gap"
|
gap-items (all-or-separate-actions {:attribute-labels {:column-gap "Column Gap"
|
||||||
:row-gap "Row Gap"}
|
:row-gap "Row Gap"}
|
||||||
:hint (tr "workspace.tokens.gaps")
|
:hint (tr "workspace.tokens.gaps")
|
||||||
:on-update-shape dwta/update-layout-gap}
|
:on-update-shape dwta/update-layout-spacing}
|
||||||
context-data)]
|
context-data)]
|
||||||
(->> (concat
|
(->> (concat
|
||||||
gap-items
|
gap-items
|
||||||
@@ -239,7 +239,7 @@
|
|||||||
(all-or-separate-actions {:attribute-labels {:width "Width"
|
(all-or-separate-actions {:attribute-labels {:width "Width"
|
||||||
:height "Height"}
|
:height "Height"}
|
||||||
:hint (tr "workspace.tokens.size")
|
:hint (tr "workspace.tokens.size")
|
||||||
:on-update-shape dwta/use-dimensions-token}
|
:on-update-shape dwta/update-shape-dimensions}
|
||||||
context-data)
|
context-data)
|
||||||
[:separator]
|
[:separator]
|
||||||
(all-or-separate-actions {:attribute-labels {:layout-item-min-w "Min Width"
|
(all-or-separate-actions {:attribute-labels {:layout-item-min-w "Min Width"
|
||||||
|
|||||||
@@ -140,6 +140,9 @@
|
|||||||
error
|
error
|
||||||
(get-in @form [:errors input-name])
|
(get-in @form [:errors input-name])
|
||||||
|
|
||||||
|
extra-error
|
||||||
|
(get-in @form [:extra-errors input-name])
|
||||||
|
|
||||||
value
|
value
|
||||||
(get-in @form [:data input-name] "")
|
(get-in @form [:data input-name] "")
|
||||||
|
|
||||||
@@ -247,9 +250,14 @@
|
|||||||
:hint-type (:type hint)})
|
:hint-type (:type hint)})
|
||||||
|
|
||||||
props
|
props
|
||||||
(if (and error touched?)
|
(cond
|
||||||
|
(and error touched?)
|
||||||
(mf/spread-props props {:hint-type "error"
|
(mf/spread-props props {:hint-type "error"
|
||||||
:hint-message (:message error)})
|
:hint-message (:message error)})
|
||||||
|
(and extra-error touched?)
|
||||||
|
(mf/spread-props props {:hint-type "error"
|
||||||
|
:hint-message (:message extra-error)})
|
||||||
|
:else
|
||||||
props)]
|
props)]
|
||||||
|
|
||||||
(mf/with-effect [resolve-stream tokens token input-name]
|
(mf/with-effect [resolve-stream tokens token input-name]
|
||||||
|
|||||||
@@ -23,21 +23,19 @@
|
|||||||
(let [token-type
|
(let [token-type
|
||||||
(or (:type token) token-type)
|
(or (:type token) token-type)
|
||||||
|
|
||||||
tokens-in-selected-set
|
|
||||||
(mf/deref refs/workspace-all-tokens-in-selected-set)
|
|
||||||
|
|
||||||
token-path
|
token-path
|
||||||
(mf/with-memo [token]
|
(mf/with-memo [token]
|
||||||
(cft/token-name->path (:name token)))
|
(cft/token-name->path (:name token)))
|
||||||
|
|
||||||
tokens-tree-in-selected-set
|
all-tokens (mf/deref refs/workspace-all-tokens-map)
|
||||||
(mf/with-memo [token-path tokens-in-selected-set]
|
|
||||||
(-> (ctob/tokens-tree tokens-in-selected-set)
|
all-tokens
|
||||||
|
(mf/with-memo [token-path all-tokens]
|
||||||
|
(-> (ctob/tokens-tree all-tokens)
|
||||||
(d/dissoc-in token-path)))
|
(d/dissoc-in token-path)))
|
||||||
props
|
props
|
||||||
(mf/spread-props props {:token-type token-type
|
(mf/spread-props props {:token-type token-type
|
||||||
:tokens-tree-in-selected-set tokens-tree-in-selected-set
|
:all-token-tree all-tokens
|
||||||
:tokens-in-selected-set tokens-in-selected-set
|
|
||||||
:token token})
|
:token token})
|
||||||
text-case-props (mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-case-value-enter")})
|
text-case-props (mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-case-value-enter")})
|
||||||
text-decoration-props (mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-decoration-value-enter")})
|
text-decoration-props (mf/spread-props props {:input-value-placeholder (tr "workspace.tokens.text-decoration-value-enter")})
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
[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.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.library-edit :as dwtl]
|
[app.main.data.workspace.tokens.library-edit :as dwtl]
|
||||||
[app.main.data.workspace.tokens.propagation :as dwtp]
|
[app.main.data.workspace.tokens.propagation :as dwtp]
|
||||||
[app.main.data.workspace.tokens.remapping :as remap]
|
[app.main.data.workspace.tokens.remapping :as remap]
|
||||||
@@ -88,14 +89,13 @@
|
|||||||
action
|
action
|
||||||
is-create
|
is-create
|
||||||
selected-token-set-id
|
selected-token-set-id
|
||||||
tokens-tree-in-selected-set
|
all-token-tree
|
||||||
token-type
|
token-type
|
||||||
make-schema
|
make-schema
|
||||||
input-component
|
input-component
|
||||||
initial
|
initial
|
||||||
type
|
type
|
||||||
value-subfield
|
value-subfield
|
||||||
tokens-in-selected-set
|
|
||||||
input-value-placeholder] :as props}]
|
input-value-placeholder] :as props}]
|
||||||
|
|
||||||
(let [make-schema (or make-schema default-make-schema)
|
(let [make-schema (or make-schema default-make-schema)
|
||||||
@@ -124,6 +124,9 @@
|
|||||||
tokens
|
tokens
|
||||||
(mf/deref refs/workspace-active-theme-sets-tokens)
|
(mf/deref refs/workspace-active-theme-sets-tokens)
|
||||||
|
|
||||||
|
tokens-in-selected-set
|
||||||
|
(mf/deref refs/workspace-all-tokens-in-selected-set)
|
||||||
|
|
||||||
tokens
|
tokens
|
||||||
(mf/with-memo [tokens tokens-in-selected-set token]
|
(mf/with-memo [tokens 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
|
||||||
@@ -134,8 +137,8 @@
|
|||||||
(assoc (:name token) token)))
|
(assoc (:name token) token)))
|
||||||
|
|
||||||
schema
|
schema
|
||||||
(mf/with-memo [tokens-tree-in-selected-set active-tab]
|
(mf/with-memo [all-token-tree active-tab]
|
||||||
(make-schema tokens-tree-in-selected-set active-tab))
|
(make-schema all-token-tree active-tab))
|
||||||
|
|
||||||
initial
|
initial
|
||||||
(mf/with-memo [token]
|
(mf/with-memo [token]
|
||||||
@@ -224,7 +227,12 @@
|
|||||||
:description description}))
|
:description description}))
|
||||||
(dwtl/toggle-token-path path)
|
(dwtl/toggle-token-path path)
|
||||||
(dwtp/propagate-workspace-tokens)
|
(dwtp/propagate-workspace-tokens)
|
||||||
(modal/hide!))))))))))]
|
(modal/hide!)))))
|
||||||
|
;; WORKAROUND: display validation errors in the form instead of crashing
|
||||||
|
(fn [{:keys [errors]}]
|
||||||
|
(let [error-messages (wte/humanize-errors errors)
|
||||||
|
error-message (first error-messages)]
|
||||||
|
(swap! form assoc-in [:extra-errors :value] {:message error-message}))))))))]
|
||||||
|
|
||||||
[:> fc/form* {:class (stl/css :form-wrapper)
|
[:> fc/form* {:class (stl/css :form-wrapper)
|
||||||
:form form
|
:form form
|
||||||
|
|||||||
@@ -228,7 +228,7 @@
|
|||||||
:class (stl/css :main-toolbar-options-button)
|
:class (stl/css :main-toolbar-options-button)
|
||||||
:icon i/bug
|
:icon i/bug
|
||||||
:aria-pressed (contains? layout :debug-panel)
|
:aria-pressed (contains? layout :debug-panel)
|
||||||
:aria-label "Debugging tool"
|
:aria-label (tr "workspace.toolbar.debug")
|
||||||
:tooltip-placement "bottom"
|
:tooltip-placement "bottom"
|
||||||
:on-click toggle-debug-panel}]])]]
|
:on-click toggle-debug-panel}]])]]
|
||||||
|
|
||||||
|
|||||||
@@ -260,7 +260,7 @@
|
|||||||
events [(dwta/apply-token {:shape-ids [(:id rect-1)]
|
events [(dwta/apply-token {:shape-ids [(:id rect-1)]
|
||||||
:attributes #{:width :height}
|
:attributes #{:width :height}
|
||||||
:token (toht/get-token file "dimensions.sm")
|
:token (toht/get-token file "dimensions.sm")
|
||||||
:on-update-shape dwta/use-dimensions-token})]]
|
:on-update-shape dwta/update-shape-dimensions})]]
|
||||||
(tohs/run-store-async
|
(tohs/run-store-async
|
||||||
store done events
|
store done events
|
||||||
(fn [new-state]
|
(fn [new-state]
|
||||||
@@ -333,7 +333,7 @@
|
|||||||
events [(dwta/apply-token {:shape-ids [(:id rect-1)]
|
events [(dwta/apply-token {:shape-ids [(:id rect-1)]
|
||||||
:attributes #{:width :height}
|
:attributes #{:width :height}
|
||||||
:token (toht/get-token file "sizing.sm")
|
:token (toht/get-token file "sizing.sm")
|
||||||
:on-update-shape dwta/use-dimensions-token})]]
|
:on-update-shape dwta/update-shape-dimensions})]]
|
||||||
(tohs/run-store-async
|
(tohs/run-store-async
|
||||||
store done events
|
store done events
|
||||||
(fn [new-state]
|
(fn [new-state]
|
||||||
|
|||||||
@@ -5476,6 +5476,10 @@ msgstr "Delete row and shapes"
|
|||||||
msgid "workspace.context-menu.grid-track.row.duplicate"
|
msgid "workspace.context-menu.grid-track.row.duplicate"
|
||||||
msgstr "Duplicate row"
|
msgstr "Duplicate row"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/debug.cljs:37
|
||||||
|
msgid "workspace.debug.title"
|
||||||
|
msgstr "Debugging tools"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/layers.cljs:512
|
#: src/app/main/ui/workspace/sidebar/layers.cljs:512
|
||||||
msgid "workspace.focus.focus-mode"
|
msgid "workspace.focus.focus-mode"
|
||||||
msgstr "Focus mode"
|
msgstr "Focus mode"
|
||||||
@@ -8421,6 +8425,10 @@ msgstr "Comments (%s)"
|
|||||||
msgid "workspace.toolbar.curve"
|
msgid "workspace.toolbar.curve"
|
||||||
msgstr "Curve (%s)"
|
msgstr "Curve (%s)"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/top_toolbar.cljs:231
|
||||||
|
msgid "workspace.toolbar.debug"
|
||||||
|
msgstr "Debugging tools"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/top_toolbar.cljs:172
|
#: src/app/main/ui/workspace/top_toolbar.cljs:172
|
||||||
msgid "workspace.toolbar.ellipse"
|
msgid "workspace.toolbar.ellipse"
|
||||||
msgstr "Ellipse (%s)"
|
msgstr "Ellipse (%s)"
|
||||||
|
|||||||
@@ -5461,6 +5461,10 @@ msgstr "Borrar fila con el contenido"
|
|||||||
msgid "workspace.context-menu.grid-track.row.duplicate"
|
msgid "workspace.context-menu.grid-track.row.duplicate"
|
||||||
msgstr "Duplicar fila"
|
msgstr "Duplicar fila"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/sidebar/debug.cljs:37
|
||||||
|
msgid "workspace.debug.title"
|
||||||
|
msgstr "Herramientas de depuración"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/layers.cljs:512
|
#: src/app/main/ui/workspace/sidebar/layers.cljs:512
|
||||||
msgid "workspace.focus.focus-mode"
|
msgid "workspace.focus.focus-mode"
|
||||||
msgstr "Modo foco"
|
msgstr "Modo foco"
|
||||||
@@ -7965,7 +7969,7 @@ msgstr "Line height (multiplicador, px o %) o {alias}"
|
|||||||
|
|
||||||
#: src/app/main/data/workspace/tokens/errors.cljs:57
|
#: src/app/main/data/workspace/tokens/errors.cljs:57
|
||||||
msgid "workspace.tokens.missing-references"
|
msgid "workspace.tokens.missing-references"
|
||||||
msgstr "Referéncias de tokens no encontradas:"
|
msgstr "Referencias de tokens no encontradas: "
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:123
|
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:123
|
||||||
msgid "workspace.tokens.more-options"
|
msgid "workspace.tokens.more-options"
|
||||||
@@ -8282,6 +8286,10 @@ msgstr "Comentarios (%s)"
|
|||||||
msgid "workspace.toolbar.curve"
|
msgid "workspace.toolbar.curve"
|
||||||
msgstr "Curva (%s)"
|
msgstr "Curva (%s)"
|
||||||
|
|
||||||
|
#: src/app/main/ui/workspace/top_toolbar.cljs:231
|
||||||
|
msgid "workspace.toolbar.debug"
|
||||||
|
msgstr "Herramientas de depuración"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/top_toolbar.cljs:172
|
#: src/app/main/ui/workspace/top_toolbar.cljs:172
|
||||||
msgid "workspace.toolbar.ellipse"
|
msgid "workspace.toolbar.ellipse"
|
||||||
msgstr "Elipse (%s)"
|
msgstr "Elipse (%s)"
|
||||||
|
|||||||
Reference in New Issue
Block a user